diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 9fd8054a12e..ec76a1a42ef 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -25,3 +25,5 @@ b2d2184edea578109a48ec3d8decbee5948e8f35 ec2cc761bc7067712ecc7734502f703fe3b024c8 # format use declarations 84ac80f1921afc243d71fd0caaa4f2838c294102 +# bless mir-opt tests to add `copy` +99cb0c6bc399fb94a0ddde7e9b38e9c00d523bad diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml index b137497594f..83b92b7fa09 100644 --- a/.github/workflows/dependencies.yml +++ b/.github/workflows/dependencies.yml @@ -64,16 +64,21 @@ jobs: - name: cargo update # Remove first line that always just says "Updating crates.io index" run: cargo update 2>&1 | sed '/crates.io index/d' | tee -a cargo_update.log + - name: cargo update library + run: | + echo -e "\nlibrary dependencies:" >> cargo_update.log + cargo update --manifest-path library/Cargo.toml 2>&1 | sed '/crates.io index/d' | tee -a cargo_update.log - name: cargo update rustbook run: | echo -e "\nrustbook dependencies:" >> cargo_update.log - cargo update --manifest-path src/tools/rustbook 2>&1 | sed '/crates.io index/d' | tee -a cargo_update.log + cargo update --manifest-path src/tools/rustbook/Cargo.toml 2>&1 | sed '/crates.io index/d' | tee -a cargo_update.log - name: upload Cargo.lock artifact for use in PR uses: actions/upload-artifact@v4 with: name: Cargo-lock path: | Cargo.lock + library/Cargo.lock src/tools/rustbook/Cargo.lock retention-days: 1 - name: upload cargo-update log artifact for use in PR @@ -119,7 +124,7 @@ jobs: git config user.name github-actions git config user.email github-actions@github.com git switch --force-create cargo_update - git add ./Cargo.lock ./src/tools/rustbook/Cargo.lock + git add ./Cargo.lock ./library/Cargo.lock ./src/tools/rustbook/Cargo.lock git commit --no-verify --file=commit.txt - name: push diff --git a/.gitignore b/.gitignore index a36cb51de33..2e6499081a6 100644 --- a/.gitignore +++ b/.gitignore @@ -56,7 +56,9 @@ build/ /src/tools/x/target # Created by default with `src/ci/docker/run.sh` /obj/ -/rustc-ice* + +## ICE reports +rustc-ice-*.txt ## Temporary files *~ diff --git a/Cargo.lock b/Cargo.lock index 4bd99b7fbe7..6ea4cd8f5ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -94,16 +94,6 @@ dependencies = [ "yansi-term", ] -[[package]] -name = "annotate-snippets" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d9b665789884a7e8fb06c84b295e923b03ca51edbb7d08f91a6a50322ecbfe6" -dependencies = [ - "anstyle", - "unicode-width", -] - [[package]] name = "annotate-snippets" version = "0.11.4" @@ -125,9 +115,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.14" +version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" dependencies = [ "anstyle", "anstyle-parse", @@ -140,42 +130,42 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "anstyle-lossy" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fcff6599f06e21b0165c85052ccd6e67dc388ddd1c516a9dc5f55dc8cacf004" +checksum = "f45c79b3b9413932fc255f2c19ca0d48eaab72c4ea1913bafaebf289cbc099f2" dependencies = [ "anstyle", ] [[package]] name = "anstyle-parse" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-svg" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbbf0bf947d663010f0b4132f28ca08da9151f3b9035fa7578a38de521c1d1aa" +checksum = "962f6d5681926dbe5503b71057202d6723a33abe464c983b1d160bca3095a3bb" dependencies = [ "anstream", "anstyle", @@ -186,9 +176,9 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "3.0.3" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -205,18 +195,18 @@ dependencies = [ [[package]] name = "ar_archive_writer" -version = "0.3.3" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f2bcb7cf51decfbbfc7ef476e28b0775b13e5eb1190f8b7df145cd53d4f4374" +checksum = "01667f6f40216b9a0b2945e05fed5f1ad0ab6470e69cb9378001e37b1c0668e4" dependencies = [ - "object 0.36.2", + "object 0.36.3", ] [[package]] name = "arrayvec" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "autocfg" @@ -271,9 +261,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "block-buffer" @@ -291,7 +281,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05" dependencies = [ "memchr", - "regex-automata 0.3.7", + "regex-automata 0.3.9", "serde", ] @@ -351,15 +341,15 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.6.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "camino" -version = "1.1.7" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239" +checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" dependencies = [ "serde", ] @@ -420,9 +410,9 @@ version = "0.1.0" [[package]] name = "cc" -version = "1.0.99" +version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" +checksum = "5208975e568d83b6b05cc0a063c8e7e9acc2b43bee6da15616a5b73e109d7437" [[package]] name = "cfg-if" @@ -432,9 +422,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cfg_aliases" -version = "0.1.1" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" @@ -446,7 +436,7 @@ dependencies = [ "iana-time-zone", "num-traits", "serde", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -483,9 +473,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.7" +version = "4.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" +checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" dependencies = [ "clap_builder", "clap_derive", @@ -503,9 +493,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.7" +version = "4.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" +checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" dependencies = [ "anstream", "anstyle", @@ -516,36 +506,37 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.6" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbca90c87c2a04da41e95d1856e8bcd22f159bdbfa147314d2ce5218057b0e58" +checksum = "1ee158892bd7ce77aa15c208abbdb73e155d191c287a659b57abd5adb92feb03" dependencies = [ "clap", ] [[package]] name = "clap_derive" -version = "4.5.5" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.67", + "syn 2.0.75", ] [[package]] name = "clap_lex" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "clippy" version = "0.1.82" dependencies = [ "anstream", + "cargo_metadata 0.18.1", "clippy_config", "clippy_lints", "clippy_utils", @@ -559,7 +550,8 @@ dependencies = [ "regex", "rustc_tools_util", "serde", - "syn 2.0.67", + "serde_json", + "syn 2.0.75", "tempfile", "termize", "tokio", @@ -573,7 +565,6 @@ name = "clippy_config" version = "0.1.82" dependencies = [ "itertools", - "rustc-semver", "serde", "toml 0.7.8", "walkdir", @@ -605,7 +596,6 @@ dependencies = [ "quine-mc_cluskey", "regex", "regex-syntax 0.8.4", - "rustc-semver", "semver", "serde", "serde_json", @@ -624,7 +614,6 @@ dependencies = [ "arrayvec", "clippy_config", "itertools", - "rustc-semver", "rustc_apfloat", ] @@ -671,7 +660,7 @@ dependencies = [ "nom", "proc-macro2", "quote", - "syn 2.0.67", + "syn 2.0.75", ] [[package]] @@ -688,9 +677,9 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" [[package]] name = "colored" @@ -750,9 +739,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "coverage-dump" @@ -768,9 +757,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" dependencies = [ "libc", ] @@ -830,12 +819,12 @@ dependencies = [ [[package]] name = "ctrlc" -version = "3.4.4" +version = "3.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "672465ae37dc1bc6380a6547a8883d5dd397b0f1faaad4f265726cc7042a5345" +checksum = "90eeab0aa92f3f9b4e87f258c72b139c207d251f9cbc1080a0086b86a8870dd3" dependencies = [ "nix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -855,9 +844,9 @@ dependencies = [ [[package]] name = "curl-sys" -version = "0.4.72+curl-8.6.0" +version = "0.4.74+curl-8.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29cbdc8314c447d11e8fd156dcdd031d9e02a7a976163e396b548c03153bc9ea" +checksum = "8af10b986114528fcdc4b63b6f5f021b7057618411046a4de2ba0f0149a097bf" dependencies = [ "cc", "libc", @@ -870,9 +859,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.9" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" dependencies = [ "darling_core", "darling_macro", @@ -880,27 +869,27 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.9" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", - "syn 2.0.67", + "syn 2.0.75", ] [[package]] name = "darling_macro" -version = "0.20.9" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.67", + "syn 2.0.75", ] [[package]] @@ -926,7 +915,7 @@ version = "0.1.82" dependencies = [ "itertools", "quote", - "syn 2.0.67", + "syn 2.0.75", ] [[package]] @@ -946,7 +935,7 @@ checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25" dependencies = [ "proc-macro2", "quote", - "syn 2.0.67", + "syn 2.0.75", ] [[package]] @@ -967,7 +956,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.67", + "syn 2.0.75", ] [[package]] @@ -977,7 +966,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b" dependencies = [ "derive_builder_core", - "syn 2.0.67", + "syn 2.0.75", ] [[package]] @@ -988,7 +977,7 @@ checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "proc-macro2", "quote", - "syn 2.0.67", + "syn 2.0.75", ] [[package]] @@ -1000,7 +989,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.67", + "syn 2.0.75", ] [[package]] @@ -1078,7 +1067,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.67", + "syn 2.0.75", ] [[package]] @@ -1089,9 +1078,9 @@ checksum = "59f8e79d1fbf76bdfbde321e902714bf6c49df88a7dda6fc682fc2979226962d" [[package]] name = "either" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "elasticlunr-rs" @@ -1131,9 +1120,9 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "env_filter" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea" +checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" dependencies = [ "log", "regex", @@ -1141,9 +1130,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.3" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9" +checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" dependencies = [ "anstream", "anstyle", @@ -1219,21 +1208,21 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.23" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" +checksum = "bf401df4a4e3872c4fe8151134cf483738e74b67fc934d6532c882b3d24a4550" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.4.1", - "windows-sys 0.52.0", + "libredox", + "windows-sys 0.59.0", ] [[package]] name = "flate2" -version = "1.0.30" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +checksum = "7f211bbe8e69bbd0cfdea405084f128ae8b4aaa6b0b522fc8f2b009084797920" dependencies = [ "crc32fast", "miniz_oxide", @@ -1369,7 +1358,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.67", + "syn 2.0.75", ] [[package]] @@ -1587,7 +1576,7 @@ dependencies = [ "markup5ever", "proc-macro2", "quote", - "syn 2.0.67", + "syn 2.0.75", ] [[package]] @@ -1719,7 +1708,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.67", + "syn 2.0.75", ] [[package]] @@ -1775,9 +1764,9 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] name = "indexmap" -version = "2.2.6" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" dependencies = [ "equivalent", "hashbrown", @@ -1856,9 +1845,9 @@ dependencies = [ [[package]] name = "is_terminal_polyfill" -version = "1.70.0" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itertools" @@ -1887,18 +1876,18 @@ dependencies = [ [[package]] name = "jobserver" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" dependencies = [ "wasm-bindgen", ] @@ -1965,9 +1954,9 @@ checksum = "baff4b617f7df3d896f97fe922b64817f6cd9a756bb81d40f8883f2f66dcb401" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.157" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "374af5f94e54fa97cf75e945cce8a6b201e88a1a07e688b47dfd2a59c66dbd86" [[package]] name = "libdbus-sys" @@ -2000,12 +1989,12 @@ dependencies = [ [[package]] name = "libloading" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -2020,15 +2009,16 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "libc", + "redox_syscall", ] [[package]] name = "libz-sys" -version = "1.1.18" +version = "1.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c15da26e5af7e25c90b37a2d75cdbf940cf4a55316de9d84c679c9b8bfabf82e" +checksum = "fdc53a7799a7496ebc9fd29f31f7df80e83c9bda5299768af5f9e59eeea74647" dependencies = [ "cc", "libc", @@ -2092,9 +2082,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "lzma-sys" @@ -2169,7 +2159,7 @@ dependencies = [ "log", "memchr", "once_cell", - "opener 0.7.1", + "opener 0.7.2", "pulldown-cmark 0.10.3", "regex", "serde", @@ -2226,9 +2216,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "mime_guess" -version = "2.0.4" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" dependencies = [ "mime", "unicase", @@ -2236,9 +2226,12 @@ dependencies = [ [[package]] name = "minifier" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95bbbf96b9ac3482c2a25450b67a15ed851319bc5fabf3b40742ea9066e84282" +checksum = "9aa3f302fe0f8de065d4a2d1ed64f60204623cac58b80cd3c2a83a25d5a7d437" +dependencies = [ + "clap", +] [[package]] name = "minimal-lexical" @@ -2301,11 +2294,11 @@ checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" [[package]] name = "nix" -version = "0.28.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cfg-if", "cfg_aliases", "libc", @@ -2323,11 +2316,11 @@ dependencies = [ [[package]] name = "normpath" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5831952a9476f2fed74b77d74182fa5ddc4d21c72ec45a333b250e3ed0272804" +checksum = "c8911957c4b1549ac0dc74e30db9c8b0e66ddcd6d7acc33098f4c63a64a6d7ed" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2342,11 +2335,11 @@ dependencies = [ [[package]] name = "nu-ansi-term" -version = "0.50.0" +version = "0.50.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd2800e1520bdc966782168a627aa5d1ad92e33b984bf7c7615d31280c83ff14" +checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2460,9 +2453,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.2" +version = "0.36.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e" +checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" dependencies = [ "crc32fast", "flate2", @@ -2470,7 +2463,7 @@ dependencies = [ "indexmap", "memchr", "ruzstd 0.7.0", - "wasmparser 0.214.0", + "wasmparser", ] [[package]] @@ -2513,14 +2506,14 @@ dependencies = [ [[package]] name = "opener" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8df34be653210fbe9ffaff41d3b92721c56ce82dfee58ee684f9afb5e3a90c0" +checksum = "d0812e5e4df08da354c851a3376fead46db31c2214f849d3de356d774d057681" dependencies = [ "bstr", "dbus", "normpath", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2531,9 +2524,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.102" +version = "0.9.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" dependencies = [ "cc", "libc", @@ -2621,9 +2614,9 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.2", + "redox_syscall", "smallvec", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -2658,9 +2651,9 @@ dependencies = [ [[package]] name = "pest" -version = "2.7.10" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "560131c633294438da9f7c4b08189194b20946c8274c6b9e38881a7874dc8ee8" +checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" dependencies = [ "memchr", "thiserror", @@ -2669,9 +2662,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.10" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26293c9193fbca7b1a3bf9b79dc1e388e927e6cacaa78b4a3ab705a1d3d41459" +checksum = "2a548d2beca6773b1c244554d36fcf8548a8a58e74156968211567250e48e49a" dependencies = [ "pest", "pest_generator", @@ -2679,22 +2672,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.10" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ec22af7d3fb470a85dd2ca96b7c577a1eb4ef6f1683a9fe9a8c16e136c04687" +checksum = "3c93a82e8d145725dcbaf44e5ea887c8a869efdcc28706df2d08c69e17077183" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.67", + "syn 2.0.75", ] [[package]] name = "pest_meta" -version = "2.7.10" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7a240022f37c361ec1878d646fc5b7d7c4d28d5946e1a80ad5a7a4f4ca0bdcd" +checksum = "a941429fea7e08bedec25e4f6785b6ffaacc6b755da98df5ef3e7dcf4a124c4f" dependencies = [ "once_cell", "pest", @@ -2789,9 +2782,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" +checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265" [[package]] name = "powerfmt" @@ -2801,9 +2794,12 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "precomputed-hash" @@ -2861,7 +2857,7 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "memchr", "unicase", ] @@ -2872,7 +2868,7 @@ version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76979bea66e7875e7509c4ec5300112b316af87fa7a252ca91c448b32dfe3993" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "memchr", "pulldown-cmark-escape 0.10.1", "unicase", @@ -2880,11 +2876,11 @@ dependencies = [ [[package]] name = "pulldown-cmark" -version = "0.11.0" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8746739f11d39ce5ad5c2520a9b75285310dbfe78c541ccf832d38615765aec0" +checksum = "cb4e75767fbc9d92b90e4d0c011f61358cde9513b31ef07ea3631b15ffc3b4fd" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "memchr", "pulldown-cmark-escape 0.11.0", "unicase", @@ -2984,20 +2980,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" -dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", ] [[package]] @@ -3013,13 +3000,12 @@ dependencies = [ [[package]] name = "regex" -version = "1.9.4" +version = "1.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12de2eff854e5fa4b1295edd650e227e9d8fb0c9e90b12e7f36d6a6811791a29" +checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.3.7", "regex-syntax 0.7.5", ] @@ -3043,14 +3029,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.7" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49530408a136e16e5b486e883fbb6ba058e8e4e8ae6621a77b048b314336e629" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax 0.7.5", -] +checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" [[package]] name = "regex-lite" @@ -3120,7 +3101,7 @@ dependencies = [ "quote", "rinja_parser", "serde", - "syn 2.0.67", + "syn 2.0.75", ] [[package]] @@ -3147,10 +3128,12 @@ dependencies = [ "bstr", "build_helper", "gimli 0.31.0", - "object 0.36.2", + "libc", + "object 0.36.3", "regex", + "serde_json", "similar", - "wasmparser 0.214.0", + "wasmparser", ] [[package]] @@ -3218,12 +3201,6 @@ dependencies = [ "num_cpus", ] -[[package]] -name = "rustc-semver" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be1bdc7edf596692617627bbfeaba522131b18e06ca4df2b6b689e3c5d5ce84" - [[package]] name = "rustc-stable-hash" version = "0.1.0" @@ -3234,7 +3211,7 @@ checksum = "e5c9f15eec8235d7cb775ee6f81891db79b98fd54ba1ad8fae565b88ef1ae4e2" name = "rustc_abi" version = "0.0.0" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "rand", "rand_xoshiro", "rustc_data_structures", @@ -3246,9 +3223,9 @@ dependencies = [ [[package]] name = "rustc_apfloat" -version = "0.2.0+llvm-462a31f5a5ab" +version = "0.2.1+llvm-462a31f5a5ab" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "465187772033a5ee566f69fe008df03628fce549a0899aae76f0a0c2e34696be" +checksum = "886d94c63c812a8037c4faca2607453a0fa4cf82f734665266876b022244543f" dependencies = [ "bitflags 1.3.2", "smallvec", @@ -3265,7 +3242,7 @@ dependencies = [ name = "rustc_ast" version = "0.0.0" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "memchr", "rustc_ast_ir", "rustc_data_structures", @@ -3427,11 +3404,11 @@ dependencies = [ name = "rustc_codegen_llvm" version = "0.0.0" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "itertools", "libc", "measureme", - "object 0.36.2", + "object 0.36.3", "rustc-demangle", "rustc_ast", "rustc_attr", @@ -3464,13 +3441,13 @@ version = "0.0.0" dependencies = [ "ar_archive_writer", "arrayvec", - "bitflags 2.5.0", + "bitflags 2.6.0", "cc", "either", "itertools", "jobserver", "libc", - "object 0.36.2", + "object 0.36.3", "pathdiff", "regex", "rustc_arena", @@ -3500,7 +3477,7 @@ dependencies = [ "thin-vec", "thorin-dwp", "tracing", - "wasm-encoder 0.210.0", + "wasm-encoder", "windows 0.52.0", ] @@ -3534,7 +3511,7 @@ name = "rustc_data_structures" version = "0.0.0" dependencies = [ "arrayvec", - "bitflags 2.5.0", + "bitflags 2.6.0", "either", "elsa", "ena", @@ -3649,7 +3626,7 @@ dependencies = [ name = "rustc_errors" version = "0.0.0" dependencies = [ - "annotate-snippets 0.10.2", + "annotate-snippets 0.11.4", "derive_setters", "rustc_ast", "rustc_ast_pretty", @@ -3709,12 +3686,12 @@ dependencies = [ name = "rustc_fluent_macro" version = "0.0.0" dependencies = [ - "annotate-snippets 0.10.2", + "annotate-snippets 0.11.4", "fluent-bundle", "fluent-syntax", "proc-macro2", "quote", - "syn 2.0.67", + "syn 2.0.75", "unic-langid", ] @@ -3848,7 +3825,7 @@ version = "0.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.67", + "syn 2.0.75", ] [[package]] @@ -3997,7 +3974,7 @@ version = "0.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.67", + "syn 2.0.75", "synstructure", ] @@ -4005,7 +3982,7 @@ dependencies = [ name = "rustc_metadata" version = "0.0.0" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "libloading", "odht", "rustc_ast", @@ -4035,7 +4012,7 @@ dependencies = [ name = "rustc_middle" version = "0.0.0" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "derive-where", "either", "field-offset", @@ -4166,7 +4143,7 @@ dependencies = [ name = "rustc_next_trait_solver" version = "0.0.0" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "derive-where", "rustc_ast_ir", "rustc_data_structures", @@ -4182,7 +4159,7 @@ dependencies = [ name = "rustc_parse" version = "0.0.0" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "rustc_ast", "rustc_ast_pretty", "rustc_data_structures", @@ -4320,8 +4297,8 @@ dependencies = [ name = "rustc_resolve" version = "0.0.0" dependencies = [ - "bitflags 2.5.0", - "pulldown-cmark 0.11.0", + "bitflags 2.6.0", + "pulldown-cmark 0.11.2", "rustc_arena", "rustc_ast", "rustc_ast_pretty", @@ -4348,7 +4325,7 @@ dependencies = [ name = "rustc_sanitizers" version = "0.0.0" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "rustc_data_structures", "rustc_hir", "rustc_middle", @@ -4374,7 +4351,7 @@ dependencies = [ name = "rustc_session" version = "0.0.0" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "getopts", "libc", "rustc_ast", @@ -4453,8 +4430,8 @@ dependencies = [ name = "rustc_target" version = "0.0.0" dependencies = [ - "bitflags 2.5.0", - "object 0.36.2", + "bitflags 2.6.0", + "object 0.36.3", "rustc_abi", "rustc_data_structures", "rustc_feature", @@ -4556,9 +4533,10 @@ dependencies = [ name = "rustc_type_ir" version = "0.0.0" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "derive-where", "indexmap", + "rustc-hash", "rustc_ast_ir", "rustc_data_structures", "rustc_index", @@ -4576,7 +4554,7 @@ version = "0.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.67", + "syn 2.0.75", "synstructure", ] @@ -4676,7 +4654,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.67", + "syn 2.0.75", ] [[package]] @@ -4714,7 +4692,7 @@ version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", @@ -4810,41 +4788,42 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.203" +version = "1.0.208" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.203" +version = "1.0.208" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.67", + "syn 2.0.75", ] [[package]] name = "serde_json" -version = "1.0.117" +version = "1.0.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +checksum = "83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31ed" dependencies = [ "indexmap", "itoa", + "memchr", "ryu", "serde", ] [[package]] name = "serde_spanned" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" +checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" dependencies = [ "serde", ] @@ -4894,9 +4873,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "similar" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa42c91313f1d05da9b26f267f931cf178d4aba455b4c4622dd7355eb80c6640" +checksum = "1de1d4f81173b03af4c0cbed3c898f6bff5b870e4a7f5d6f4057d62a7a4b686e" [[package]] name = "siphasher" @@ -5088,9 +5067,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.67" +version = "2.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff8655ed1d86f3af4ee3fd3263786bc14245ad17c4c7e85ba7187fb3ae028c90" +checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" dependencies = [ "proc-macro2", "quote", @@ -5105,7 +5084,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.67", + "syn 2.0.75", ] [[package]] @@ -5142,14 +5121,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.10.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" dependencies = [ "cfg-if", "fastrand", + "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -5222,22 +5202,22 @@ checksum = "a38c90d48152c236a3ab59271da4f4ae63d678c5d7ad6b7714d7cb9760be5e4b" [[package]] name = "thiserror" -version = "1.0.61" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.61" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.67", + "syn 2.0.75", ] [[package]] @@ -5335,9 +5315,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -5350,9 +5330,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.38.0" +version = "1.39.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5" dependencies = [ "backtrace", "bytes", @@ -5382,9 +5362,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.6" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" dependencies = [ "serde", ] @@ -5428,7 +5408,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.67", + "syn 2.0.75", ] [[package]] @@ -5487,7 +5467,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b56c62d2c80033cb36fae448730a2f2ef99410fe3ecbffc916681a32f6807dbe" dependencies = [ - "nu-ansi-term 0.50.0", + "nu-ansi-term 0.50.1", "tracing-core", "tracing-log", "tracing-subscriber", @@ -5627,7 +5607,7 @@ checksum = "1ed7f4237ba393424195053097c1516bd4590dc82b84f2f97c5c69e12704555b" dependencies = [ "proc-macro-hack", "quote", - "syn 2.0.67", + "syn 2.0.75", "unic-langid-impl", ] @@ -5756,9 +5736,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" dependencies = [ "getrandom", ] @@ -5777,9 +5757,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "walkdir" @@ -5798,35 +5778,42 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] -name = "wasm-bindgen" -version = "0.2.92" +name = "wasi-preview1-component-adapter-provider" +version = "23.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "f91d3d13afef569b9fc80cfbb807c87c16ef49bd3ac1a93285ea6a264b600d2d" + +[[package]] +name = "wasm-bindgen" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.67", + "syn 2.0.75", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5834,36 +5821,38 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.67", + "syn 2.0.75", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "wasm-component-ld" -version = "0.5.4" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "314d932d5e84c9678751b85498b1482b2f32f185744e449d3ce0b1d400376dad" +checksum = "51449c63d1ce69f92b8465a084ed5b91f1a7eb583fa95796650a6bfcffc4f9cb" dependencies = [ "anyhow", "clap", "lexopt", "tempfile", - "wasmparser 0.210.0", + "wasi-preview1-component-adapter-provider", + "wasmparser", "wat", "wit-component", + "wit-parser", ] [[package]] @@ -5875,27 +5864,19 @@ dependencies = [ [[package]] name = "wasm-encoder" -version = "0.210.0" +version = "0.215.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7e3764d9d6edabd8c9e16195e177be0d20f6ab942ad18af52860f12f82bc59a" -dependencies = [ - "leb128", -] - -[[package]] -name = "wasm-encoder" -version = "0.211.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e7d931a1120ef357f32b74547646b6fa68ea25e377772b72874b131a9ed70d4" +checksum = "4fb56df3e06b8e6b77e37d2969a50ba51281029a9aeb3855e76b7f49b6418847" dependencies = [ "leb128", + "wasmparser", ] [[package]] name = "wasm-metadata" -version = "0.210.0" +version = "0.215.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "012729d1294907fcb0866f08460ab95426a6d0b176a599619b84cac7653452b4" +checksum = "0c6bb07c5576b608f7a2a9baa2294c1a3584a249965d695a9814a496cb6d232f" dependencies = [ "anyhow", "indexmap", @@ -5903,52 +5884,42 @@ dependencies = [ "serde_derive", "serde_json", "spdx", - "wasm-encoder 0.210.0", - "wasmparser 0.210.0", + "wasm-encoder", + "wasmparser", ] [[package]] name = "wasmparser" -version = "0.210.0" +version = "0.215.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7bbcd21e7581619d9f6ca00f8c4f08f1cacfe58bf63f83af57cd0476f1026f5" +checksum = "53fbde0881f24199b81cf49b6ff8f9c145ac8eb1b7fc439adb5c099734f7d90e" dependencies = [ "ahash", - "bitflags 2.5.0", + "bitflags 2.6.0", "hashbrown", "indexmap", "semver", "serde", ] -[[package]] -name = "wasmparser" -version = "0.214.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5309c1090e3e84dad0d382f42064e9933fdaedb87e468cc239f0eabea73ddcb6" -dependencies = [ - "bitflags 2.5.0", - "indexmap", -] - [[package]] name = "wast" -version = "211.0.1" +version = "215.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b25506dd82d00da6b14a87436b3d52b1d264083fa79cdb72a0d1b04a8595ccaa" +checksum = "1ff1d00d893593249e60720be04a7c1f42f1c4dc3806a2869f4e66ab61eb54cb" dependencies = [ "bumpalo", "leb128", "memchr", "unicode-width", - "wasm-encoder 0.211.1", + "wasm-encoder", ] [[package]] name = "wat" -version = "1.211.1" +version = "1.215.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb716ca6c86eecac2d82541ffc39860118fc0af9309c4f2670637bea2e1bdd7d" +checksum = "670bf4d9c8cf76ae242d70ded47c546525b6dafaa6871f9bcb065344bf2b4e3d" dependencies = [ "wast", ] @@ -5971,11 +5942,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -5991,7 +5962,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" dependencies = [ "windows-core 0.52.0", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -6001,7 +5972,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" dependencies = [ "windows-core 0.57.0", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -6014,7 +5985,7 @@ dependencies = [ "rayon", "serde", "serde_json", - "syn 2.0.67", + "syn 2.0.75", "windows-metadata", ] @@ -6024,7 +5995,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -6036,7 +6007,7 @@ dependencies = [ "windows-implement", "windows-interface", "windows-result", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -6047,7 +6018,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.67", + "syn 2.0.75", ] [[package]] @@ -6058,7 +6029,7 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.67", + "syn 2.0.75", ] [[package]] @@ -6073,7 +6044,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -6091,7 +6062,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -6111,18 +6091,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -6133,9 +6113,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -6145,9 +6125,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -6157,15 +6137,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -6175,9 +6155,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -6187,9 +6167,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -6199,9 +6179,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -6211,9 +6191,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" @@ -6226,28 +6206,28 @@ dependencies = [ [[package]] name = "wit-component" -version = "0.210.0" +version = "0.215.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a450bdb5d032acf1fa0865451fa0c6f50e62f2d31eaa8dba967c2e2d068694a4" +checksum = "f725e3885fc5890648be5c5cbc1353b755dc932aa5f1aa7de968b912a3280743" dependencies = [ "anyhow", - "bitflags 2.5.0", + "bitflags 2.6.0", "indexmap", "log", "serde", "serde_derive", "serde_json", - "wasm-encoder 0.210.0", + "wasm-encoder", "wasm-metadata", - "wasmparser 0.210.0", + "wasmparser", "wit-parser", ] [[package]] name = "wit-parser" -version = "0.210.0" +version = "0.215.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a965cbd439af19a4b44a54a97ab8957d86f02d01320efc9e31c1d3605c6710" +checksum = "935a97eaffd57c3b413aa510f8f0b550a4a9fe7d59e79cd8b89a83dcb860321f" dependencies = [ "anyhow", "id-arena", @@ -6258,7 +6238,7 @@ dependencies = [ "serde_derive", "serde_json", "unicode-xid", - "wasmparser 0.210.0", + "wasmparser", ] [[package]] @@ -6316,28 +6296,29 @@ checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" dependencies = [ "proc-macro2", "quote", - "syn 2.0.67", + "syn 2.0.75", "synstructure", ] [[package]] name = "zerocopy" -version = "0.7.34" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.34" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.67", + "syn 2.0.75", ] [[package]] @@ -6357,15 +6338,15 @@ checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.67", + "syn 2.0.75", "synstructure", ] [[package]] name = "zerovec" -version = "0.10.2" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2cc8827d6c0994478a15c53f374f46fbd41bea663d809b14744bc42e6b109c" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" dependencies = [ "yoke", "zerofrom", @@ -6374,11 +6355,11 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97cf56601ee5052b4417d90c8755c6683473c926039908196cf35d99f893ebe7" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.67", + "syn 2.0.75", ] diff --git a/Cargo.toml b/Cargo.toml index 131feec70ab..d4b84250fc4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -resolver = "1" +resolver = "2" members = [ "compiler/rustc", "src/etc/test-float-parse", diff --git a/RELEASES.md b/RELEASES.md index 2c91ddf7826..5e4827be4ec 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -143,6 +143,8 @@ Compatibility Notes - [Turn `proc_macro_back_compat` lint into a hard error.](https://github.com/rust-lang/rust/pull/125596/) - [Detect unused structs even when implementing private traits](https://github.com/rust-lang/rust/pull/122382/) - [`std::sync::ReentrantLockGuard` is no longer `Sync` if `T: !Sync`](https://github.com/rust-lang/rust/pull/125527) which means [`std::io::StdoutLock` and `std::io::StderrLock` are no longer Sync](https://github.com/rust-lang/rust/issues/127340) +- [Type inference will fail in some cases due to new implementations of `FromIterator for Box`.](https://github.com/rust-lang/rust/pull/99969/) + Notably, this breaks versions of the `time` crate before 0.3.35, due to no longer inferring the implementation for `Box<[_]>`. diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 3dc548c4554..df29b3d54f0 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -3,6 +3,7 @@ #![cfg_attr(feature = "nightly", doc(rust_logo))] #![cfg_attr(feature = "nightly", feature(rustdoc_internals))] #![cfg_attr(feature = "nightly", feature(step_trait))] +#![warn(unreachable_pub)] // tidy-alphabetical-end use std::fmt; @@ -1699,7 +1700,9 @@ impl LayoutS { /// Checks if these two `Layout` are equal enough to be considered "the same for all function /// call ABIs". Note however that real ABIs depend on more details that are not reflected in the - /// `Layout`; the `PassMode` need to be compared as well. + /// `Layout`; the `PassMode` need to be compared as well. Also note that we assume + /// aggregates are passed via `PassMode::Indirect` or `PassMode::Cast`; more strict + /// checks would otherwise be required. pub fn eq_abi(&self, other: &Self) -> bool { // The one thing that we are not capturing here is that for unsized types, the metadata must // also have the same ABI, and moreover that the same metadata leads to the same size. The diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index f5f01348e46..260c9fe44ba 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -21,10 +21,10 @@ #![feature(decl_macro)] #![feature(dropck_eyepatch)] #![feature(maybe_uninit_slice)] -#![feature(new_uninit)] #![feature(rustc_attrs)] #![feature(rustdoc_internals)] #![feature(strict_provenance)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use std::alloc::Layout; diff --git a/compiler/rustc_arena/src/tests.rs b/compiler/rustc_arena/src/tests.rs index 9eaa292e989..bfde8abd589 100644 --- a/compiler/rustc_arena/src/tests.rs +++ b/compiler/rustc_arena/src/tests.rs @@ -32,7 +32,7 @@ impl TypedArena { } #[test] -pub fn test_unused() { +fn test_unused() { let arena: TypedArena = TypedArena::default(); assert!(arena.chunks.borrow().is_empty()); } @@ -75,7 +75,7 @@ fn test_arena_alloc_nested() { } #[test] -pub fn test_copy() { +fn test_copy() { let arena = TypedArena::default(); #[cfg(not(miri))] const N: usize = 100000; @@ -87,13 +87,13 @@ pub fn test_copy() { } #[bench] -pub fn bench_copy(b: &mut Bencher) { +fn bench_copy(b: &mut Bencher) { let arena = TypedArena::default(); b.iter(|| arena.alloc(Point { x: 1, y: 2, z: 3 })) } #[bench] -pub fn bench_copy_nonarena(b: &mut Bencher) { +fn bench_copy_nonarena(b: &mut Bencher) { b.iter(|| { let _: Box<_> = Box::new(Point { x: 1, y: 2, z: 3 }); }) @@ -106,7 +106,7 @@ struct Noncopy { } #[test] -pub fn test_noncopy() { +fn test_noncopy() { let arena = TypedArena::default(); #[cfg(not(miri))] const N: usize = 100000; @@ -118,7 +118,7 @@ pub fn test_noncopy() { } #[test] -pub fn test_typed_arena_zero_sized() { +fn test_typed_arena_zero_sized() { let arena = TypedArena::default(); #[cfg(not(miri))] const N: usize = 100000; @@ -130,7 +130,7 @@ pub fn test_typed_arena_zero_sized() { } #[test] -pub fn test_typed_arena_clear() { +fn test_typed_arena_clear() { let mut arena = TypedArena::default(); for _ in 0..10 { arena.clear(); @@ -145,7 +145,7 @@ pub fn test_typed_arena_clear() { } #[bench] -pub fn bench_typed_arena_clear(b: &mut Bencher) { +fn bench_typed_arena_clear(b: &mut Bencher) { let mut arena = TypedArena::default(); b.iter(|| { arena.alloc(Point { x: 1, y: 2, z: 3 }); @@ -154,7 +154,7 @@ pub fn bench_typed_arena_clear(b: &mut Bencher) { } #[bench] -pub fn bench_typed_arena_clear_100(b: &mut Bencher) { +fn bench_typed_arena_clear_100(b: &mut Bencher) { let mut arena = TypedArena::default(); b.iter(|| { for _ in 0..100 { @@ -230,7 +230,7 @@ fn test_typed_arena_drop_small_count() { } #[bench] -pub fn bench_noncopy(b: &mut Bencher) { +fn bench_noncopy(b: &mut Bencher) { let arena = TypedArena::default(); b.iter(|| { arena.alloc(Noncopy { string: "hello world".to_string(), array: vec![1, 2, 3, 4, 5] }) @@ -238,7 +238,7 @@ pub fn bench_noncopy(b: &mut Bencher) { } #[bench] -pub fn bench_noncopy_nonarena(b: &mut Bencher) { +fn bench_noncopy_nonarena(b: &mut Bencher) { b.iter(|| { let _: Box<_> = Box::new(Noncopy { string: "hello world".to_string(), array: vec![1, 2, 3, 4, 5] }); diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index a44ed828504..85d38a0e28b 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2902,6 +2902,17 @@ pub struct AttrItem { pub tokens: Option, } +impl AttrItem { + pub fn is_valid_for_outer_style(&self) -> bool { + self.path == sym::cfg_attr + || self.path == sym::cfg + || self.path == sym::forbid + || self.path == sym::warn + || self.path == sym::allow + || self.path == sym::deny + } +} + /// `TraitRef`s appear in impls. /// /// Resolution maps each `TraitRef`'s `ref_id` to its defining trait; that's all diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index 27e9f3d137f..7730d0b4b78 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -19,6 +19,7 @@ #![feature(never_type)] #![feature(rustdoc_internals)] #![feature(stmt_expr_attributes)] +#![warn(unreachable_pub)] // tidy-alphabetical-end pub mod util { diff --git a/compiler/rustc_ast_ir/src/lib.rs b/compiler/rustc_ast_ir/src/lib.rs index 1d0c76f6cea..eeed5d36151 100644 --- a/compiler/rustc_ast_ir/src/lib.rs +++ b/compiler/rustc_ast_ir/src/lib.rs @@ -2,6 +2,7 @@ #![cfg_attr(feature = "nightly", allow(internal_features))] #![cfg_attr(feature = "nightly", feature(never_type))] #![cfg_attr(feature = "nightly", feature(rustc_attrs))] +#![warn(unreachable_pub)] // tidy-alphabetical-end #[cfg(feature = "nightly")] diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index 0a7f75039f6..a5ee6713be8 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -175,8 +175,6 @@ ast_lowering_underscore_expr_lhs_assign = .label = `_` not allowed here ast_lowering_unstable_inline_assembly = inline assembly is not stable yet on this architecture -ast_lowering_unstable_inline_assembly_const_operands = - const operands for inline assembly are unstable ast_lowering_unstable_inline_assembly_label_operands = label operands for inline assembly are unstable ast_lowering_unstable_may_unwind = the `may_unwind` option is unstable diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 8acca78379b..e077c544965 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -86,9 +86,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Multiple different abi names may actually be the same ABI // If the specified ABIs are not the same name, alert the user that they resolve to the same ABI let source_map = self.tcx.sess.source_map(); - let equivalent = (source_map.span_to_snippet(*prev_sp) - != source_map.span_to_snippet(*abi_span)) - .then_some(()); + let equivalent = source_map.span_to_snippet(*prev_sp) + != source_map.span_to_snippet(*abi_span); self.dcx().emit_err(AbiSpecifiedMultipleTimes { abi_span: *abi_span, @@ -183,20 +182,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { out_expr: out_expr.as_ref().map(|expr| self.lower_expr(expr)), } } - InlineAsmOperand::Const { anon_const } => { - if !self.tcx.features().asm_const { - feature_err( - sess, - sym::asm_const, - *op_sp, - fluent::ast_lowering_unstable_inline_assembly_const_operands, - ) - .emit(); - } - hir::InlineAsmOperand::Const { - anon_const: self.lower_anon_const_to_anon_const(anon_const), - } - } + InlineAsmOperand::Const { anon_const } => hir::InlineAsmOperand::Const { + anon_const: self.lower_anon_const_to_anon_const(anon_const), + }, InlineAsmOperand::Sym { sym } => { let static_def_id = self .resolver @@ -232,7 +220,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let parent_def_id = self.current_def_id_parent; let node_id = self.next_node_id(); // HACK(min_generic_const_args): see lower_anon_const - if !expr.is_potential_trivial_const_arg() { + if !self.tcx.features().const_arg_path + || !expr.is_potential_trivial_const_arg() + { self.create_def( parent_def_id, node_id, diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index 300bfa101c6..80077348204 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -51,7 +51,7 @@ use rustc_span::Span; use rustc_target::spec::abi; use {rustc_ast as ast, rustc_hir as hir}; -use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs}; +use super::{GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode}; use crate::{ImplTraitPosition, ResolverAstLoweringExt}; pub(crate) struct DelegationResults<'hir> { @@ -189,7 +189,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ) -> hir::FnSig<'hir> { let header = if let Some(local_sig_id) = sig_id.as_local() { match self.resolver.delegation_fn_sigs.get(&local_sig_id) { - Some(sig) => self.lower_fn_header(sig.header), + Some(sig) => self.lower_fn_header(sig.header, hir::Safety::Safe), None => self.generate_header_error(), } } else { @@ -323,7 +323,7 @@ impl<'hir> LoweringContext<'_, 'hir> { delegation.path.span, ast_segment, ParamMode::Optional, - ParenthesizedGenericArgs::Err, + GenericArgsMode::Err, ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index 7a6c9d8d0d3..6b39c2d3955 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -6,7 +6,7 @@ use rustc_span::{Span, Symbol}; #[derive(Diagnostic)] #[diag(ast_lowering_generic_type_with_parentheses, code = E0214)] -pub struct GenericTypeWithParentheses { +pub(crate) struct GenericTypeWithParentheses { #[primary_span] #[label] pub span: Span, @@ -16,7 +16,7 @@ pub struct GenericTypeWithParentheses { #[derive(Subdiagnostic)] #[multipart_suggestion(ast_lowering_use_angle_brackets, applicability = "maybe-incorrect")] -pub struct UseAngleBrackets { +pub(crate) struct UseAngleBrackets { #[suggestion_part(code = "<")] pub open_param: Span, #[suggestion_part(code = ">")] @@ -26,7 +26,7 @@ pub struct UseAngleBrackets { #[derive(Diagnostic)] #[diag(ast_lowering_invalid_abi, code = E0703)] #[note] -pub struct InvalidAbi { +pub(crate) struct InvalidAbi { #[primary_span] #[label] pub span: Span, @@ -38,7 +38,7 @@ pub struct InvalidAbi { pub suggestion: Option, } -pub struct InvalidAbiReason(pub &'static str); +pub(crate) struct InvalidAbiReason(pub &'static str); impl Subdiagnostic for InvalidAbiReason { fn add_to_diag_with>( @@ -57,7 +57,7 @@ impl Subdiagnostic for InvalidAbiReason { code = "{suggestion}", applicability = "maybe-incorrect" )] -pub struct InvalidAbiSuggestion { +pub(crate) struct InvalidAbiSuggestion { #[primary_span] pub span: Span, pub suggestion: String, @@ -65,7 +65,7 @@ pub struct InvalidAbiSuggestion { #[derive(Diagnostic)] #[diag(ast_lowering_assoc_ty_parentheses)] -pub struct AssocTyParentheses { +pub(crate) struct AssocTyParentheses { #[primary_span] pub span: Span, #[subdiagnostic] @@ -73,7 +73,7 @@ pub struct AssocTyParentheses { } #[derive(Subdiagnostic)] -pub enum AssocTyParenthesesSub { +pub(crate) enum AssocTyParenthesesSub { #[multipart_suggestion(ast_lowering_remove_parentheses)] Empty { #[suggestion_part(code = "")] @@ -91,7 +91,7 @@ pub enum AssocTyParenthesesSub { #[derive(Diagnostic)] #[diag(ast_lowering_misplaced_impl_trait, code = E0562)] #[note] -pub struct MisplacedImplTrait<'a> { +pub(crate) struct MisplacedImplTrait<'a> { #[primary_span] pub span: Span, pub position: DiagArgFromDisplay<'a>, @@ -99,7 +99,7 @@ pub struct MisplacedImplTrait<'a> { #[derive(Diagnostic)] #[diag(ast_lowering_assoc_ty_binding_in_dyn)] -pub struct MisplacedAssocTyBinding { +pub(crate) struct MisplacedAssocTyBinding { #[primary_span] pub span: Span, #[suggestion(code = " = impl", applicability = "maybe-incorrect", style = "verbose")] @@ -108,7 +108,7 @@ pub struct MisplacedAssocTyBinding { #[derive(Diagnostic)] #[diag(ast_lowering_underscore_expr_lhs_assign)] -pub struct UnderscoreExprLhsAssign { +pub(crate) struct UnderscoreExprLhsAssign { #[primary_span] #[label] pub span: Span, @@ -116,7 +116,7 @@ pub struct UnderscoreExprLhsAssign { #[derive(Diagnostic)] #[diag(ast_lowering_base_expression_double_dot, code = E0797)] -pub struct BaseExpressionDoubleDot { +pub(crate) struct BaseExpressionDoubleDot { #[primary_span] #[suggestion(code = "/* expr */", applicability = "has-placeholders", style = "verbose")] pub span: Span, @@ -124,7 +124,7 @@ pub struct BaseExpressionDoubleDot { #[derive(Diagnostic)] #[diag(ast_lowering_await_only_in_async_fn_and_blocks, code = E0728)] -pub struct AwaitOnlyInAsyncFnAndBlocks { +pub(crate) struct AwaitOnlyInAsyncFnAndBlocks { #[primary_span] #[label] pub await_kw_span: Span, @@ -134,21 +134,21 @@ pub struct AwaitOnlyInAsyncFnAndBlocks { #[derive(Diagnostic)] #[diag(ast_lowering_coroutine_too_many_parameters, code = E0628)] -pub struct CoroutineTooManyParameters { +pub(crate) struct CoroutineTooManyParameters { #[primary_span] pub fn_decl_span: Span, } #[derive(Diagnostic)] #[diag(ast_lowering_closure_cannot_be_static, code = E0697)] -pub struct ClosureCannotBeStatic { +pub(crate) struct ClosureCannotBeStatic { #[primary_span] pub fn_decl_span: Span, } #[derive(Diagnostic)] #[diag(ast_lowering_functional_record_update_destructuring_assignment)] -pub struct FunctionalRecordUpdateDestructuringAssignment { +pub(crate) struct FunctionalRecordUpdateDestructuringAssignment { #[primary_span] #[suggestion(code = "", applicability = "machine-applicable")] pub span: Span, @@ -156,40 +156,40 @@ pub struct FunctionalRecordUpdateDestructuringAssignment { #[derive(Diagnostic)] #[diag(ast_lowering_async_coroutines_not_supported, code = E0727)] -pub struct AsyncCoroutinesNotSupported { +pub(crate) struct AsyncCoroutinesNotSupported { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_lowering_inline_asm_unsupported_target, code = E0472)] -pub struct InlineAsmUnsupportedTarget { +pub(crate) struct InlineAsmUnsupportedTarget { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_lowering_att_syntax_only_x86)] -pub struct AttSyntaxOnlyX86 { +pub(crate) struct AttSyntaxOnlyX86 { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_lowering_abi_specified_multiple_times)] -pub struct AbiSpecifiedMultipleTimes { +pub(crate) struct AbiSpecifiedMultipleTimes { #[primary_span] pub abi_span: Span, pub prev_name: Symbol, #[label] pub prev_span: Span, #[note] - pub equivalent: Option<()>, + pub equivalent: bool, } #[derive(Diagnostic)] #[diag(ast_lowering_clobber_abi_not_supported)] -pub struct ClobberAbiNotSupported { +pub(crate) struct ClobberAbiNotSupported { #[primary_span] pub abi_span: Span, } @@ -197,7 +197,7 @@ pub struct ClobberAbiNotSupported { #[derive(Diagnostic)] #[note] #[diag(ast_lowering_invalid_abi_clobber_abi)] -pub struct InvalidAbiClobberAbi { +pub(crate) struct InvalidAbiClobberAbi { #[primary_span] pub abi_span: Span, pub supported_abis: String, @@ -205,7 +205,7 @@ pub struct InvalidAbiClobberAbi { #[derive(Diagnostic)] #[diag(ast_lowering_invalid_register)] -pub struct InvalidRegister<'a> { +pub(crate) struct InvalidRegister<'a> { #[primary_span] pub op_span: Span, pub reg: Symbol, @@ -214,7 +214,7 @@ pub struct InvalidRegister<'a> { #[derive(Diagnostic)] #[diag(ast_lowering_invalid_register_class)] -pub struct InvalidRegisterClass<'a> { +pub(crate) struct InvalidRegisterClass<'a> { #[primary_span] pub op_span: Span, pub reg_class: Symbol, @@ -223,7 +223,7 @@ pub struct InvalidRegisterClass<'a> { #[derive(Diagnostic)] #[diag(ast_lowering_invalid_asm_template_modifier_reg_class)] -pub struct InvalidAsmTemplateModifierRegClass { +pub(crate) struct InvalidAsmTemplateModifierRegClass { #[primary_span] #[label(ast_lowering_template_modifier)] pub placeholder_span: Span, @@ -234,7 +234,7 @@ pub struct InvalidAsmTemplateModifierRegClass { } #[derive(Subdiagnostic)] -pub enum InvalidAsmTemplateModifierRegClassSub { +pub(crate) enum InvalidAsmTemplateModifierRegClassSub { #[note(ast_lowering_support_modifiers)] SupportModifier { class_name: Symbol, modifiers: String }, #[note(ast_lowering_does_not_support_modifiers)] @@ -243,7 +243,7 @@ pub enum InvalidAsmTemplateModifierRegClassSub { #[derive(Diagnostic)] #[diag(ast_lowering_invalid_asm_template_modifier_const)] -pub struct InvalidAsmTemplateModifierConst { +pub(crate) struct InvalidAsmTemplateModifierConst { #[primary_span] #[label(ast_lowering_template_modifier)] pub placeholder_span: Span, @@ -253,7 +253,7 @@ pub struct InvalidAsmTemplateModifierConst { #[derive(Diagnostic)] #[diag(ast_lowering_invalid_asm_template_modifier_sym)] -pub struct InvalidAsmTemplateModifierSym { +pub(crate) struct InvalidAsmTemplateModifierSym { #[primary_span] #[label(ast_lowering_template_modifier)] pub placeholder_span: Span, @@ -263,7 +263,7 @@ pub struct InvalidAsmTemplateModifierSym { #[derive(Diagnostic)] #[diag(ast_lowering_invalid_asm_template_modifier_label)] -pub struct InvalidAsmTemplateModifierLabel { +pub(crate) struct InvalidAsmTemplateModifierLabel { #[primary_span] #[label(ast_lowering_template_modifier)] pub placeholder_span: Span, @@ -273,7 +273,7 @@ pub struct InvalidAsmTemplateModifierLabel { #[derive(Diagnostic)] #[diag(ast_lowering_register_class_only_clobber)] -pub struct RegisterClassOnlyClobber { +pub(crate) struct RegisterClassOnlyClobber { #[primary_span] pub op_span: Span, pub reg_class_name: Symbol, @@ -281,7 +281,7 @@ pub struct RegisterClassOnlyClobber { #[derive(Diagnostic)] #[diag(ast_lowering_register_conflict)] -pub struct RegisterConflict<'a> { +pub(crate) struct RegisterConflict<'a> { #[primary_span] #[label(ast_lowering_register1)] pub op_span1: Span, @@ -296,7 +296,7 @@ pub struct RegisterConflict<'a> { #[derive(Diagnostic)] #[help] #[diag(ast_lowering_sub_tuple_binding)] -pub struct SubTupleBinding<'a> { +pub(crate) struct SubTupleBinding<'a> { #[primary_span] #[label] #[suggestion( @@ -313,7 +313,7 @@ pub struct SubTupleBinding<'a> { #[derive(Diagnostic)] #[diag(ast_lowering_extra_double_dot)] -pub struct ExtraDoubleDot<'a> { +pub(crate) struct ExtraDoubleDot<'a> { #[primary_span] #[label] pub span: Span, @@ -325,21 +325,21 @@ pub struct ExtraDoubleDot<'a> { #[derive(Diagnostic)] #[note] #[diag(ast_lowering_misplaced_double_dot)] -pub struct MisplacedDoubleDot { +pub(crate) struct MisplacedDoubleDot { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_lowering_misplaced_relax_trait_bound)] -pub struct MisplacedRelaxTraitBound { +pub(crate) struct MisplacedRelaxTraitBound { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_lowering_match_arm_with_no_body)] -pub struct MatchArmWithNoBody { +pub(crate) struct MatchArmWithNoBody { #[primary_span] pub span: Span, #[suggestion(code = " => todo!(),", applicability = "has-placeholders")] @@ -348,7 +348,7 @@ pub struct MatchArmWithNoBody { #[derive(Diagnostic)] #[diag(ast_lowering_never_pattern_with_body)] -pub struct NeverPatternWithBody { +pub(crate) struct NeverPatternWithBody { #[primary_span] #[label] #[suggestion(code = "", applicability = "maybe-incorrect")] @@ -357,7 +357,7 @@ pub struct NeverPatternWithBody { #[derive(Diagnostic)] #[diag(ast_lowering_never_pattern_with_guard)] -pub struct NeverPatternWithGuard { +pub(crate) struct NeverPatternWithGuard { #[primary_span] #[suggestion(code = "", applicability = "maybe-incorrect")] pub span: Span, @@ -365,7 +365,7 @@ pub struct NeverPatternWithGuard { #[derive(Diagnostic)] #[diag(ast_lowering_arbitrary_expression_in_pattern)] -pub struct ArbitraryExpressionInPattern { +pub(crate) struct ArbitraryExpressionInPattern { #[primary_span] pub span: Span, #[note(ast_lowering_pattern_from_macro_note)] @@ -374,13 +374,13 @@ pub struct ArbitraryExpressionInPattern { #[derive(Diagnostic)] #[diag(ast_lowering_inclusive_range_with_no_end)] -pub struct InclusiveRangeWithNoEnd { +pub(crate) struct InclusiveRangeWithNoEnd { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -pub enum BadReturnTypeNotation { +pub(crate) enum BadReturnTypeNotation { #[diag(ast_lowering_bad_return_type_notation_inputs)] Inputs { #[primary_span] diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index b5d8a547a8f..a6c7714a182 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -20,7 +20,7 @@ use super::errors::{ NeverPatternWithBody, NeverPatternWithGuard, UnderscoreExprLhsAssign, }; use super::{ - ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs, ResolverAstLoweringExt, + GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode, ResolverAstLoweringExt, }; use crate::errors::YieldInClosure; use crate::{fluent_generated, FnDeclKind, ImplTraitPosition}; @@ -107,7 +107,7 @@ impl<'hir> LoweringContext<'_, 'hir> { e.span, seg, ParamMode::Optional, - ParenthesizedGenericArgs::Err, + GenericArgsMode::Err, ImplTraitContext::Disallowed(ImplTraitPosition::Path), // Method calls can't have bound modifiers None, @@ -387,7 +387,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let node_id = self.next_node_id(); // HACK(min_generic_const_args): see lower_anon_const - if !arg.is_potential_trivial_const_arg() { + if !self.tcx.features().const_arg_path || !arg.is_potential_trivial_const_arg() { // Add a definition for the in-band const def. self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, f.span); } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 7af3945d3f9..c8ec8f308a8 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -237,7 +237,7 @@ impl<'hir> LoweringContext<'_, 'hir> { }); let sig = hir::FnSig { decl, - header: this.lower_fn_header(*header), + header: this.lower_fn_header(*header, hir::Safety::Safe), span: this.lower_span(*fn_sig_span), }; hir::ItemKind::Fn(sig, generics, body_id) @@ -668,7 +668,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ForeignItemKind::Fn(box Fn { sig, generics, .. }) => { let fdec = &sig.decl; let itctx = ImplTraitContext::Universal; - let (generics, (fn_dec, fn_args)) = + let (generics, (decl, fn_args)) = self.lower_generics(generics, Const::No, false, i.id, itctx, |this| { ( // Disallow `impl Trait` in foreign items. @@ -682,9 +682,15 @@ impl<'hir> LoweringContext<'_, 'hir> { this.lower_fn_params_to_names(fdec), ) }); - let safety = self.lower_safety(sig.header.safety, hir::Safety::Unsafe); - hir::ForeignItemKind::Fn(fn_dec, fn_args, generics, safety) + // Unmarked safety in unsafe block defaults to unsafe. + let header = self.lower_fn_header(sig.header, hir::Safety::Unsafe); + + hir::ForeignItemKind::Fn( + hir::FnSig { header, decl, span: self.lower_span(sig.span) }, + fn_args, + generics, + ) } ForeignItemKind::Static(box StaticItem { ty, mutability, expr: _, safety }) => { let ty = self @@ -758,18 +764,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, (index, f): (usize, &FieldDef), ) -> hir::FieldDef<'hir> { - let ty = if let TyKind::Path(qself, path) = &f.ty.kind { - let t = self.lower_path_ty( - &f.ty, - qself, - path, - ParamMode::ExplicitNamed, // no `'_` in declarations (Issue #61124) - ImplTraitContext::Disallowed(ImplTraitPosition::FieldTy), - ); - self.arena.alloc(t) - } else { - self.lower_ty(&f.ty, ImplTraitContext::Disallowed(ImplTraitPosition::FieldTy)) - }; + let ty = self.lower_ty(&f.ty, ImplTraitContext::Disallowed(ImplTraitPosition::FieldTy)); let hir_id = self.lower_node_id(f.id); self.lower_attrs(hir_id, &f.attrs); hir::FieldDef { @@ -1182,7 +1177,7 @@ impl<'hir> LoweringContext<'_, 'hir> { /// into the body. This is to make sure that the future actually owns the /// arguments that are passed to the function, and to ensure things like /// drop order are stable. - pub fn lower_coroutine_body_with_moved_arguments( + pub(crate) fn lower_coroutine_body_with_moved_arguments( &mut self, decl: &FnDecl, lower_body: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::Expr<'hir>, @@ -1390,7 +1385,7 @@ impl<'hir> LoweringContext<'_, 'hir> { coroutine_kind: Option, parent_constness: Const, ) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) { - let header = self.lower_fn_header(sig.header); + let header = self.lower_fn_header(sig.header, hir::Safety::Safe); // Don't pass along the user-provided constness of trait associated functions; we don't want to // synthesize a host effect param for them. We reject `const` on them during AST validation. let constness = @@ -1403,15 +1398,19 @@ impl<'hir> LoweringContext<'_, 'hir> { (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) }) } - pub(super) fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader { + pub(super) fn lower_fn_header( + &mut self, + h: FnHeader, + default_safety: hir::Safety, + ) -> hir::FnHeader { let asyncness = if let Some(CoroutineKind::Async { span, .. }) = h.coroutine_kind { hir::IsAsync::Async(span) } else { hir::IsAsync::NotAsync }; hir::FnHeader { - safety: self.lower_safety(h.safety, hir::Safety::Safe), - asyncness: asyncness, + safety: self.lower_safety(h.safety, default_safety), + asyncness, constness: self.lower_constness(h.constness), abi: self.lower_extern(h.ext), } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 81d17a9dec2..bcc2c29a2ff 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -37,6 +37,7 @@ #![feature(box_patterns)] #![feature(let_chains)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use std::collections::hash_map::Entry; @@ -481,13 +482,11 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> { enum ParamMode { /// Any path in a type context. Explicit, - /// Path in a type definition, where the anonymous lifetime `'_` is not allowed. - ExplicitNamed, /// The `module::Type` in `module::Type::method` in an expression. Optional, } -enum ParenthesizedGenericArgs { +enum GenericArgsMode { ParenSugar, Err, } @@ -2358,7 +2357,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: Span, ) -> &'hir hir::ConstArg<'hir> { let ct_kind = match res { - Res::Def(DefKind::ConstParam, _) => { + Res::Def(DefKind::ConstParam, _) if self.tcx.features().const_arg_path => { let qpath = self.lower_qpath( ty_id, &None, @@ -2433,7 +2432,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.resolver.get_partial_res(expr.id).and_then(|partial_res| partial_res.full_res()); debug!("res={:?}", maybe_res); // FIXME(min_generic_const_args): for now we only lower params to ConstArgKind::Path - if let Some(res) = maybe_res + if self.tcx.features().const_arg_path + && let Some(res) = maybe_res && let Res::Def(DefKind::ConstParam, _) = res && let ExprKind::Path(qself, path) = &expr.kind { @@ -2464,7 +2464,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// See [`hir::ConstArg`] for when to use this function vs /// [`Self::lower_anon_const_to_const_arg`]. fn lower_anon_const_to_anon_const(&mut self, c: &AnonConst) -> &'hir hir::AnonConst { - if c.value.is_potential_trivial_const_arg() { + if self.tcx.features().const_arg_path && c.value.is_potential_trivial_const_arg() { // HACK(min_generic_const_args): see DefCollector::visit_anon_const // Over there, we guess if this is a bare param and only create a def if // we think it's not. However we may can guess wrong (see there for example) diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 077b06acd7c..2ab30eff6d8 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -15,8 +15,8 @@ use super::errors::{ GenericTypeWithParentheses, UseAngleBrackets, }; use super::{ - GenericArgsCtor, ImplTraitContext, LifetimeRes, LoweringContext, ParamMode, - ParenthesizedGenericArgs, ResolverAstLoweringExt, + GenericArgsCtor, GenericArgsMode, ImplTraitContext, LifetimeRes, LoweringContext, ParamMode, + ResolverAstLoweringExt, }; use crate::ImplTraitPosition; @@ -90,10 +90,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { _ => param_mode, }; - let parenthesized_generic_args = match base_res { + let generic_args_mode = match base_res { // `a::b::Trait(Args)` Res::Def(DefKind::Trait, _) if i + 1 == proj_start => { - ParenthesizedGenericArgs::ParenSugar + GenericArgsMode::ParenSugar } // `a::b::Trait(Args)::TraitItem` Res::Def(DefKind::AssocFn, _) @@ -101,19 +101,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { | Res::Def(DefKind::AssocTy, _) if i + 2 == proj_start => { - ParenthesizedGenericArgs::ParenSugar + GenericArgsMode::ParenSugar } // Avoid duplicated errors. - Res::Err => ParenthesizedGenericArgs::ParenSugar, + Res::Err => GenericArgsMode::ParenSugar, // An error - _ => ParenthesizedGenericArgs::Err, + _ => GenericArgsMode::Err, }; self.lower_path_segment( p.span, segment, param_mode, - parenthesized_generic_args, + generic_args_mode, itctx, bound_modifier_allowed_features.clone(), ) @@ -168,7 +168,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { p.span, segment, param_mode, - ParenthesizedGenericArgs::Err, + GenericArgsMode::Err, itctx, None, )); @@ -210,7 +210,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { p.span, segment, param_mode, - ParenthesizedGenericArgs::Err, + GenericArgsMode::Err, ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ) @@ -224,7 +224,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { path_span: Span, segment: &PathSegment, param_mode: ParamMode, - parenthesized_generic_args: ParenthesizedGenericArgs, + generic_args_mode: GenericArgsMode, itctx: ImplTraitContext, // Additional features ungated with a bound modifier like `async`. // This is passed down to the implicit associated type binding in @@ -237,14 +237,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { GenericArgs::AngleBracketed(data) => { self.lower_angle_bracketed_parameter_data(data, param_mode, itctx) } - GenericArgs::Parenthesized(data) => match parenthesized_generic_args { - ParenthesizedGenericArgs::ParenSugar => self - .lower_parenthesized_parameter_data( - data, - itctx, - bound_modifier_allowed_features, - ), - ParenthesizedGenericArgs::Err => { + GenericArgs::Parenthesized(data) => match generic_args_mode { + GenericArgsMode::ParenSugar => self.lower_parenthesized_parameter_data( + data, + itctx, + bound_modifier_allowed_features, + ), + GenericArgsMode::Err => { // Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait` let sub = if !data.inputs.is_empty() { // Start of the span to the 1st character of 1st argument diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index a353c79f12d..a9b65456b8c 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -562,10 +562,8 @@ impl<'a> AstValidator<'a> { FnHeader { safety: _, coroutine_kind, constness, ext }: FnHeader, ) { let report_err = |span| { - self.dcx().emit_err(errors::FnQualifierInExtern { - span: span, - block: self.current_extern_span(), - }); + self.dcx() + .emit_err(errors::FnQualifierInExtern { span, block: self.current_extern_span() }); }; match coroutine_kind { Some(knd) => report_err(knd.span()), @@ -887,7 +885,7 @@ fn validate_generic_param_order(dcx: DiagCtxtHandle<'_>, generics: &[GenericPara impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_attribute(&mut self, attr: &Attribute) { - validate_attr::check_attr(&self.features, &self.session.psess, attr); + validate_attr::check_attr(&self.session.psess, attr); } fn visit_ty(&mut self, ty: &'a Ty) { @@ -963,14 +961,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self_ty, items, }) => { - let error = - |annotation_span, annotation, only_trait: bool| errors::InherentImplCannot { - span: self_ty.span, - annotation_span, - annotation, - self_ty: self_ty.span, - only_trait: only_trait.then_some(()), - }; + let error = |annotation_span, annotation, only_trait| errors::InherentImplCannot { + span: self_ty.span, + annotation_span, + annotation, + self_ty: self_ty.span, + only_trait, + }; self.with_in_trait_impl(None, |this| { this.visibility_not_permitted( @@ -1195,7 +1192,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } else if where_clauses.after.has_where_token { self.dcx().emit_err(errors::WhereClauseAfterTypeAlias { span: where_clauses.after.span, - help: self.session.is_nightly_build().then_some(()), + help: self.session.is_nightly_build(), }); } } diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 9e403680837..67c0396333c 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -11,7 +11,7 @@ use crate::fluent_generated as fluent; #[derive(Diagnostic)] #[diag(ast_passes_visibility_not_permitted, code = E0449)] -pub struct VisibilityNotPermitted { +pub(crate) struct VisibilityNotPermitted { #[primary_span] pub span: Span, #[subdiagnostic] @@ -25,7 +25,7 @@ pub struct VisibilityNotPermitted { } #[derive(Subdiagnostic)] -pub enum VisibilityNotPermittedNote { +pub(crate) enum VisibilityNotPermittedNote { #[note(ast_passes_enum_variant)] EnumVariant, #[note(ast_passes_trait_impl)] @@ -38,7 +38,7 @@ pub enum VisibilityNotPermittedNote { #[derive(Diagnostic)] #[diag(ast_passes_trait_fn_const, code = E0379)] -pub struct TraitFnConst { +pub(crate) struct TraitFnConst { #[primary_span] #[label] pub span: Span, @@ -64,21 +64,21 @@ pub struct TraitFnConst { #[derive(Diagnostic)] #[diag(ast_passes_forbidden_bound)] -pub struct ForbiddenBound { +pub(crate) struct ForbiddenBound { #[primary_span] pub spans: Vec, } #[derive(Diagnostic)] #[diag(ast_passes_forbidden_const_param)] -pub struct ForbiddenConstParam { +pub(crate) struct ForbiddenConstParam { #[primary_span] pub const_param_spans: Vec, } #[derive(Diagnostic)] #[diag(ast_passes_fn_param_too_many)] -pub struct FnParamTooMany { +pub(crate) struct FnParamTooMany { #[primary_span] pub span: Span, pub max_num_args: usize, @@ -86,14 +86,14 @@ pub struct FnParamTooMany { #[derive(Diagnostic)] #[diag(ast_passes_fn_param_c_var_args_not_last)] -pub struct FnParamCVarArgsNotLast { +pub(crate) struct FnParamCVarArgsNotLast { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_passes_fn_param_doc_comment)] -pub struct FnParamDocComment { +pub(crate) struct FnParamDocComment { #[primary_span] #[label] pub span: Span, @@ -101,7 +101,7 @@ pub struct FnParamDocComment { #[derive(Diagnostic)] #[diag(ast_passes_fn_param_forbidden_attr)] -pub struct FnParamForbiddenAttr { +pub(crate) struct FnParamForbiddenAttr { #[primary_span] pub span: Span, } @@ -109,7 +109,7 @@ pub struct FnParamForbiddenAttr { #[derive(Diagnostic)] #[diag(ast_passes_fn_param_forbidden_self)] #[note] -pub struct FnParamForbiddenSelf { +pub(crate) struct FnParamForbiddenSelf { #[primary_span] #[label] pub span: Span, @@ -117,7 +117,7 @@ pub struct FnParamForbiddenSelf { #[derive(Diagnostic)] #[diag(ast_passes_forbidden_default)] -pub struct ForbiddenDefault { +pub(crate) struct ForbiddenDefault { #[primary_span] pub span: Span, #[label] @@ -126,7 +126,7 @@ pub struct ForbiddenDefault { #[derive(Diagnostic)] #[diag(ast_passes_assoc_const_without_body)] -pub struct AssocConstWithoutBody { +pub(crate) struct AssocConstWithoutBody { #[primary_span] pub span: Span, #[suggestion(code = " = ;", applicability = "has-placeholders")] @@ -135,7 +135,7 @@ pub struct AssocConstWithoutBody { #[derive(Diagnostic)] #[diag(ast_passes_assoc_fn_without_body)] -pub struct AssocFnWithoutBody { +pub(crate) struct AssocFnWithoutBody { #[primary_span] pub span: Span, #[suggestion(code = " {{ }}", applicability = "has-placeholders")] @@ -144,7 +144,7 @@ pub struct AssocFnWithoutBody { #[derive(Diagnostic)] #[diag(ast_passes_assoc_type_without_body)] -pub struct AssocTypeWithoutBody { +pub(crate) struct AssocTypeWithoutBody { #[primary_span] pub span: Span, #[suggestion(code = " = ;", applicability = "has-placeholders")] @@ -153,7 +153,7 @@ pub struct AssocTypeWithoutBody { #[derive(Diagnostic)] #[diag(ast_passes_const_without_body)] -pub struct ConstWithoutBody { +pub(crate) struct ConstWithoutBody { #[primary_span] pub span: Span, #[suggestion(code = " = ;", applicability = "has-placeholders")] @@ -162,7 +162,7 @@ pub struct ConstWithoutBody { #[derive(Diagnostic)] #[diag(ast_passes_static_without_body)] -pub struct StaticWithoutBody { +pub(crate) struct StaticWithoutBody { #[primary_span] pub span: Span, #[suggestion(code = " = ;", applicability = "has-placeholders")] @@ -171,7 +171,7 @@ pub struct StaticWithoutBody { #[derive(Diagnostic)] #[diag(ast_passes_ty_alias_without_body)] -pub struct TyAliasWithoutBody { +pub(crate) struct TyAliasWithoutBody { #[primary_span] pub span: Span, #[suggestion(code = " = ;", applicability = "has-placeholders")] @@ -180,7 +180,7 @@ pub struct TyAliasWithoutBody { #[derive(Diagnostic)] #[diag(ast_passes_fn_without_body)] -pub struct FnWithoutBody { +pub(crate) struct FnWithoutBody { #[primary_span] pub span: Span, #[suggestion(code = " {{ }}", applicability = "has-placeholders")] @@ -190,7 +190,7 @@ pub struct FnWithoutBody { } #[derive(Subdiagnostic)] -pub enum ExternBlockSuggestion { +pub(crate) enum ExternBlockSuggestion { #[multipart_suggestion(ast_passes_extern_block_suggestion, applicability = "maybe-incorrect")] Implicit { #[suggestion_part(code = "extern {{")] @@ -210,7 +210,7 @@ pub enum ExternBlockSuggestion { #[derive(Diagnostic)] #[diag(ast_passes_extern_invalid_safety)] -pub struct InvalidSafetyOnExtern { +pub(crate) struct InvalidSafetyOnExtern { #[primary_span] pub item_span: Span, #[suggestion(code = "unsafe ", applicability = "machine-applicable", style = "verbose")] @@ -219,28 +219,28 @@ pub struct InvalidSafetyOnExtern { #[derive(Diagnostic)] #[diag(ast_passes_item_invalid_safety)] -pub struct InvalidSafetyOnItem { +pub(crate) struct InvalidSafetyOnItem { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_passes_bare_fn_invalid_safety)] -pub struct InvalidSafetyOnBareFn { +pub(crate) struct InvalidSafetyOnBareFn { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_passes_unsafe_static)] -pub struct UnsafeStatic { +pub(crate) struct UnsafeStatic { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_passes_bound_in_context)] -pub struct BoundInContext<'a> { +pub(crate) struct BoundInContext<'a> { #[primary_span] pub span: Span, pub ctx: &'a str, @@ -249,7 +249,7 @@ pub struct BoundInContext<'a> { #[derive(Diagnostic)] #[diag(ast_passes_extern_types_cannot)] #[note(ast_passes_extern_keyword_link)] -pub struct ExternTypesCannotHave<'a> { +pub(crate) struct ExternTypesCannotHave<'a> { #[primary_span] #[suggestion(code = "", applicability = "maybe-incorrect")] pub span: Span, @@ -262,7 +262,7 @@ pub struct ExternTypesCannotHave<'a> { #[derive(Diagnostic)] #[diag(ast_passes_body_in_extern)] #[note(ast_passes_extern_keyword_link)] -pub struct BodyInExtern<'a> { +pub(crate) struct BodyInExtern<'a> { #[primary_span] #[label(ast_passes_cannot_have)] pub span: Span, @@ -277,7 +277,7 @@ pub struct BodyInExtern<'a> { #[diag(ast_passes_fn_body_extern)] #[help] #[note(ast_passes_extern_keyword_link)] -pub struct FnBodyInExtern { +pub(crate) struct FnBodyInExtern { #[primary_span] #[label(ast_passes_cannot_have)] pub span: Span, @@ -289,7 +289,7 @@ pub struct FnBodyInExtern { #[derive(Diagnostic)] #[diag(ast_passes_extern_fn_qualifiers)] -pub struct FnQualifierInExtern { +pub(crate) struct FnQualifierInExtern { #[primary_span] #[suggestion(code = "", applicability = "maybe-incorrect")] pub span: Span, @@ -300,7 +300,7 @@ pub struct FnQualifierInExtern { #[derive(Diagnostic)] #[diag(ast_passes_extern_item_ascii)] #[note] -pub struct ExternItemAscii { +pub(crate) struct ExternItemAscii { #[primary_span] pub span: Span, #[label] @@ -309,14 +309,14 @@ pub struct ExternItemAscii { #[derive(Diagnostic)] #[diag(ast_passes_bad_c_variadic)] -pub struct BadCVariadic { +pub(crate) struct BadCVariadic { #[primary_span] pub span: Vec, } #[derive(Diagnostic)] #[diag(ast_passes_item_underscore)] -pub struct ItemUnderscore<'a> { +pub(crate) struct ItemUnderscore<'a> { #[primary_span] #[label] pub span: Span, @@ -325,7 +325,7 @@ pub struct ItemUnderscore<'a> { #[derive(Diagnostic)] #[diag(ast_passes_nomangle_ascii, code = E0754)] -pub struct NoMangleAscii { +pub(crate) struct NoMangleAscii { #[primary_span] pub span: Span, } @@ -333,7 +333,7 @@ pub struct NoMangleAscii { #[derive(Diagnostic)] #[diag(ast_passes_module_nonascii, code = E0754)] #[help] -pub struct ModuleNonAscii { +pub(crate) struct ModuleNonAscii { #[primary_span] pub span: Span, pub name: Symbol, @@ -341,7 +341,7 @@ pub struct ModuleNonAscii { #[derive(Diagnostic)] #[diag(ast_passes_auto_generic, code = E0567)] -pub struct AutoTraitGeneric { +pub(crate) struct AutoTraitGeneric { #[primary_span] #[suggestion(code = "", applicability = "machine-applicable")] pub span: Span, @@ -351,7 +351,7 @@ pub struct AutoTraitGeneric { #[derive(Diagnostic)] #[diag(ast_passes_auto_super_lifetime, code = E0568)] -pub struct AutoTraitBounds { +pub(crate) struct AutoTraitBounds { #[primary_span] #[suggestion(code = "", applicability = "machine-applicable")] pub span: Span, @@ -361,7 +361,7 @@ pub struct AutoTraitBounds { #[derive(Diagnostic)] #[diag(ast_passes_auto_items, code = E0380)] -pub struct AutoTraitItems { +pub(crate) struct AutoTraitItems { #[primary_span] pub spans: Vec, #[suggestion(code = "", applicability = "machine-applicable")] @@ -372,7 +372,7 @@ pub struct AutoTraitItems { #[derive(Diagnostic)] #[diag(ast_passes_generic_before_constraints)] -pub struct ArgsBeforeConstraint { +pub(crate) struct ArgsBeforeConstraint { #[primary_span] pub arg_spans: Vec, #[label(ast_passes_constraints)] @@ -390,7 +390,7 @@ pub struct ArgsBeforeConstraint { pub arg_spans2: EmptyLabelManySpans, } -pub struct EmptyLabelManySpans(pub Vec); +pub(crate) struct EmptyLabelManySpans(pub Vec); // The derive for `Vec` does multiple calls to `span_label`, adding commas between each impl Subdiagnostic for EmptyLabelManySpans { @@ -405,28 +405,28 @@ impl Subdiagnostic for EmptyLabelManySpans { #[derive(Diagnostic)] #[diag(ast_passes_pattern_in_fn_pointer, code = E0561)] -pub struct PatternFnPointer { +pub(crate) struct PatternFnPointer { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_passes_trait_object_single_bound, code = E0226)] -pub struct TraitObjectBound { +pub(crate) struct TraitObjectBound { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_passes_impl_trait_path, code = E0667)] -pub struct ImplTraitPath { +pub(crate) struct ImplTraitPath { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_passes_nested_impl_trait, code = E0666)] -pub struct NestedImplTrait { +pub(crate) struct NestedImplTrait { #[primary_span] pub span: Span, #[label(ast_passes_outer)] @@ -437,14 +437,14 @@ pub struct NestedImplTrait { #[derive(Diagnostic)] #[diag(ast_passes_at_least_one_trait)] -pub struct AtLeastOneTrait { +pub(crate) struct AtLeastOneTrait { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_passes_out_of_order_params)] -pub struct OutOfOrderParams<'a> { +pub(crate) struct OutOfOrderParams<'a> { #[primary_span] pub spans: Vec, #[suggestion(code = "{ordered_params}", applicability = "machine-applicable")] @@ -457,14 +457,14 @@ pub struct OutOfOrderParams<'a> { #[derive(Diagnostic)] #[diag(ast_passes_obsolete_auto)] #[help] -pub struct ObsoleteAuto { +pub(crate) struct ObsoleteAuto { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_passes_unsafe_negative_impl, code = E0198)] -pub struct UnsafeNegativeImpl { +pub(crate) struct UnsafeNegativeImpl { #[primary_span] pub span: Span, #[label(ast_passes_negative)] @@ -475,7 +475,7 @@ pub struct UnsafeNegativeImpl { #[derive(Diagnostic)] #[diag(ast_passes_inherent_cannot_be)] -pub struct InherentImplCannot<'a> { +pub(crate) struct InherentImplCannot<'a> { #[primary_span] pub span: Span, #[label(ast_passes_because)] @@ -484,12 +484,12 @@ pub struct InherentImplCannot<'a> { #[label(ast_passes_type)] pub self_ty: Span, #[note(ast_passes_only_trait)] - pub only_trait: Option<()>, + pub only_trait: bool, } #[derive(Diagnostic)] #[diag(ast_passes_inherent_cannot_be, code = E0197)] -pub struct InherentImplCannotUnsafe<'a> { +pub(crate) struct InherentImplCannotUnsafe<'a> { #[primary_span] pub span: Span, #[label(ast_passes_because)] @@ -501,7 +501,7 @@ pub struct InherentImplCannotUnsafe<'a> { #[derive(Diagnostic)] #[diag(ast_passes_unsafe_item)] -pub struct UnsafeItem { +pub(crate) struct UnsafeItem { #[primary_span] pub span: Span, pub kind: &'static str, @@ -509,14 +509,14 @@ pub struct UnsafeItem { #[derive(Diagnostic)] #[diag(ast_passes_missing_unsafe_on_extern)] -pub struct MissingUnsafeOnExtern { +pub(crate) struct MissingUnsafeOnExtern { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_passes_fieldless_union)] -pub struct FieldlessUnion { +pub(crate) struct FieldlessUnion { #[primary_span] pub span: Span, } @@ -524,17 +524,17 @@ pub struct FieldlessUnion { #[derive(Diagnostic)] #[diag(ast_passes_where_clause_after_type_alias)] #[note] -pub struct WhereClauseAfterTypeAlias { +pub(crate) struct WhereClauseAfterTypeAlias { #[primary_span] pub span: Span, #[help] - pub help: Option<()>, + pub help: bool, } #[derive(Diagnostic)] #[diag(ast_passes_where_clause_before_type_alias)] #[note] -pub struct WhereClauseBeforeTypeAlias { +pub(crate) struct WhereClauseBeforeTypeAlias { #[primary_span] pub span: Span, #[subdiagnostic] @@ -543,7 +543,7 @@ pub struct WhereClauseBeforeTypeAlias { #[derive(Subdiagnostic)] -pub enum WhereClauseBeforeTypeAliasSugg { +pub(crate) enum WhereClauseBeforeTypeAliasSugg { #[suggestion(ast_passes_remove_suggestion, applicability = "machine-applicable", code = "")] Remove { #[primary_span] @@ -565,14 +565,14 @@ pub enum WhereClauseBeforeTypeAliasSugg { #[derive(Diagnostic)] #[diag(ast_passes_generic_default_trailing)] -pub struct GenericDefaultTrailing { +pub(crate) struct GenericDefaultTrailing { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_passes_nested_lifetimes, code = E0316)] -pub struct NestedLifetimes { +pub(crate) struct NestedLifetimes { #[primary_span] pub span: Span, } @@ -580,7 +580,7 @@ pub struct NestedLifetimes { #[derive(Diagnostic)] #[diag(ast_passes_optional_trait_supertrait)] #[note] -pub struct OptionalTraitSupertrait { +pub(crate) struct OptionalTraitSupertrait { #[primary_span] pub span: Span, pub path_str: String, @@ -588,14 +588,14 @@ pub struct OptionalTraitSupertrait { #[derive(Diagnostic)] #[diag(ast_passes_optional_trait_object)] -pub struct OptionalTraitObject { +pub(crate) struct OptionalTraitObject { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_passes_const_bound_trait_object)] -pub struct ConstBoundTraitObject { +pub(crate) struct ConstBoundTraitObject { #[primary_span] pub span: Span, } @@ -604,7 +604,7 @@ pub struct ConstBoundTraitObject { // FIXME(effects): Provide structured suggestions (e.g., add `const` / `#[const_trait]` here). #[derive(Diagnostic)] #[diag(ast_passes_tilde_const_disallowed)] -pub struct TildeConstDisallowed { +pub(crate) struct TildeConstDisallowed { #[primary_span] pub span: Span, #[subdiagnostic] @@ -612,7 +612,7 @@ pub struct TildeConstDisallowed { } #[derive(Subdiagnostic, Copy, Clone)] -pub enum TildeConstReason { +pub(crate) enum TildeConstReason { #[note(ast_passes_closure)] Closure, #[note(ast_passes_function)] @@ -658,7 +658,7 @@ pub enum TildeConstReason { #[derive(Diagnostic)] #[diag(ast_passes_const_and_async)] -pub struct ConstAndAsync { +pub(crate) struct ConstAndAsync { #[primary_span] pub spans: Vec, #[label(ast_passes_const)] @@ -671,7 +671,7 @@ pub struct ConstAndAsync { #[derive(Diagnostic)] #[diag(ast_passes_const_and_c_variadic)] -pub struct ConstAndCVariadic { +pub(crate) struct ConstAndCVariadic { #[primary_span] pub spans: Vec, #[label(ast_passes_const)] @@ -683,7 +683,7 @@ pub struct ConstAndCVariadic { #[derive(Diagnostic)] #[diag(ast_passes_pattern_in_foreign, code = E0130)] // FIXME: deduplicate with rustc_lint (`BuiltinLintDiag::PatternsInFnsWithoutBody`) -pub struct PatternInForeign { +pub(crate) struct PatternInForeign { #[primary_span] #[label] pub span: Span, @@ -692,7 +692,7 @@ pub struct PatternInForeign { #[derive(Diagnostic)] #[diag(ast_passes_pattern_in_bodiless, code = E0642)] // FIXME: deduplicate with rustc_lint (`BuiltinLintDiag::PatternsInFnsWithoutBody`) -pub struct PatternInBodiless { +pub(crate) struct PatternInBodiless { #[primary_span] #[label] pub span: Span, @@ -701,7 +701,7 @@ pub struct PatternInBodiless { #[derive(Diagnostic)] #[diag(ast_passes_equality_in_where)] #[note] -pub struct EqualityInWhere { +pub(crate) struct EqualityInWhere { #[primary_span] #[label] pub span: Span, @@ -718,7 +718,7 @@ pub struct EqualityInWhere { style = "verbose", applicability = "maybe-incorrect" )] -pub struct AssociatedSuggestion { +pub(crate) struct AssociatedSuggestion { #[primary_span] pub span: Span, pub ident: Ident, @@ -728,7 +728,7 @@ pub struct AssociatedSuggestion { #[derive(Subdiagnostic)] #[multipart_suggestion(ast_passes_suggestion_path, applicability = "maybe-incorrect")] -pub struct AssociatedSuggestion2 { +pub(crate) struct AssociatedSuggestion2 { #[suggestion_part(code = "{args}")] pub span: Span, pub args: String, @@ -740,14 +740,14 @@ pub struct AssociatedSuggestion2 { #[derive(Diagnostic)] #[diag(ast_passes_stability_outside_std, code = E0734)] -pub struct StabilityOutsideStd { +pub(crate) struct StabilityOutsideStd { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_passes_feature_on_non_nightly, code = E0554)] -pub struct FeatureOnNonNightly { +pub(crate) struct FeatureOnNonNightly { #[primary_span] pub span: Span, pub channel: &'static str, @@ -757,7 +757,7 @@ pub struct FeatureOnNonNightly { pub sugg: Option, } -pub struct StableFeature { +pub(crate) struct StableFeature { pub name: Symbol, pub since: Symbol, } @@ -777,7 +777,7 @@ impl Subdiagnostic for StableFeature { #[derive(Diagnostic)] #[diag(ast_passes_incompatible_features)] #[help] -pub struct IncompatibleFeatures { +pub(crate) struct IncompatibleFeatures { #[primary_span] pub spans: Vec, pub f1: Symbol, @@ -786,7 +786,7 @@ pub struct IncompatibleFeatures { #[derive(Diagnostic)] #[diag(ast_passes_show_span)] -pub struct ShowSpan { +pub(crate) struct ShowSpan { #[primary_span] pub span: Span, pub msg: &'static str, @@ -794,28 +794,28 @@ pub struct ShowSpan { #[derive(Diagnostic)] #[diag(ast_passes_negative_bound_not_supported)] -pub struct NegativeBoundUnsupported { +pub(crate) struct NegativeBoundUnsupported { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_passes_constraint_on_negative_bound)] -pub struct ConstraintOnNegativeBound { +pub(crate) struct ConstraintOnNegativeBound { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_passes_negative_bound_with_parenthetical_notation)] -pub struct NegativeBoundWithParentheticalNotation { +pub(crate) struct NegativeBoundWithParentheticalNotation { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_passes_invalid_unnamed_field_ty)] -pub struct InvalidUnnamedFieldTy { +pub(crate) struct InvalidUnnamedFieldTy { #[primary_span] pub span: Span, #[label] @@ -824,7 +824,7 @@ pub struct InvalidUnnamedFieldTy { #[derive(Diagnostic)] #[diag(ast_passes_invalid_unnamed_field)] -pub struct InvalidUnnamedField { +pub(crate) struct InvalidUnnamedField { #[primary_span] pub span: Span, #[label] @@ -833,7 +833,7 @@ pub struct InvalidUnnamedField { #[derive(Diagnostic)] #[diag(ast_passes_anon_struct_or_union_not_allowed)] -pub struct AnonStructOrUnionNotAllowed { +pub(crate) struct AnonStructOrUnionNotAllowed { #[primary_span] #[label] pub span: Span, @@ -842,7 +842,7 @@ pub struct AnonStructOrUnionNotAllowed { #[derive(Diagnostic)] #[diag(ast_passes_match_arm_with_no_body)] -pub struct MatchArmWithNoBody { +pub(crate) struct MatchArmWithNoBody { #[primary_span] pub span: Span, #[suggestion(code = " => todo!(),", applicability = "has-placeholders")] @@ -851,7 +851,7 @@ pub struct MatchArmWithNoBody { #[derive(Diagnostic)] #[diag(ast_passes_precise_capturing_not_allowed_here)] -pub struct PreciseCapturingNotAllowedHere { +pub(crate) struct PreciseCapturingNotAllowedHere { #[primary_span] pub span: Span, pub loc: &'static str, @@ -859,7 +859,7 @@ pub struct PreciseCapturingNotAllowedHere { #[derive(Diagnostic)] #[diag(ast_passes_precise_capturing_duplicated)] -pub struct DuplicatePreciseCapturing { +pub(crate) struct DuplicatePreciseCapturing { #[primary_span] pub bound1: Span, #[label] diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 3ceb8e0711a..45e397a58c0 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -539,7 +539,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { } } gate_all!(gen_blocks, "gen blocks are experimental"); - gate_all!(raw_ref_op, "raw address of syntax is experimental"); gate_all!(const_trait_impl, "const trait impls are experimental"); gate_all!( half_open_range_patterns_in_slices, @@ -557,9 +556,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { gate_all!(fn_delegation, "functions delegation is not yet fully implemented"); gate_all!(postfix_match, "postfix match is experimental"); gate_all!(mut_ref, "mutable by-reference bindings are experimental"); - gate_all!(precise_capturing, "precise captures on `impl Trait` are experimental"); gate_all!(global_registration, "global registration is experimental"); - gate_all!(unsafe_attributes, "`#[unsafe()]` markers for attributes are experimental"); gate_all!(return_type_notation, "return type notation is experimental"); if !visitor.features.never_patterns { diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs index 1f4bcd59afa..88c6bde3106 100644 --- a/compiler/rustc_ast_passes/src/lib.rs +++ b/compiler/rustc_ast_passes/src/lib.rs @@ -12,6 +12,7 @@ #![feature(iter_is_partitioned)] #![feature(let_chains)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end pub mod ast_validation; diff --git a/compiler/rustc_ast_pretty/src/lib.rs b/compiler/rustc_ast_pretty/src/lib.rs index 84d9ce278a2..602ab69ee5b 100644 --- a/compiler/rustc_ast_pretty/src/lib.rs +++ b/compiler/rustc_ast_pretty/src/lib.rs @@ -3,6 +3,7 @@ #![doc(rust_logo)] #![feature(box_patterns)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end mod helpers; diff --git a/compiler/rustc_ast_pretty/src/pp/convenience.rs b/compiler/rustc_ast_pretty/src/pp/convenience.rs index 6d46c26311b..7559b181f7d 100644 --- a/compiler/rustc_ast_pretty/src/pp/convenience.rs +++ b/compiler/rustc_ast_pretty/src/pp/convenience.rs @@ -89,7 +89,7 @@ impl Printer { } impl Token { - pub fn is_hardbreak_tok(&self) -> bool { + pub(crate) fn is_hardbreak_tok(&self) -> bool { *self == Printer::hardbreak_tok_offset(0) } } diff --git a/compiler/rustc_ast_pretty/src/pp/ring.rs b/compiler/rustc_ast_pretty/src/pp/ring.rs index 8187394fe30..003c0a999b5 100644 --- a/compiler/rustc_ast_pretty/src/pp/ring.rs +++ b/compiler/rustc_ast_pretty/src/pp/ring.rs @@ -11,54 +11,54 @@ use std::ops::{Index, IndexMut}; /// Holding a RingBuffer whose view is elements left..right gives the ability to /// use Index and IndexMut to access elements i in the infinitely long queue for /// which left <= i < right. -pub struct RingBuffer { +pub(super) struct RingBuffer { data: VecDeque, // Abstract index of data[0] in the infinitely sized queue. offset: usize, } impl RingBuffer { - pub fn new() -> Self { + pub(super) fn new() -> Self { RingBuffer { data: VecDeque::new(), offset: 0 } } - pub fn is_empty(&self) -> bool { + pub(super) fn is_empty(&self) -> bool { self.data.is_empty() } - pub fn push(&mut self, value: T) -> usize { + pub(super) fn push(&mut self, value: T) -> usize { let index = self.offset + self.data.len(); self.data.push_back(value); index } - pub fn clear(&mut self) { + pub(super) fn clear(&mut self) { self.data.clear(); } - pub fn index_of_first(&self) -> usize { + pub(super) fn index_of_first(&self) -> usize { self.offset } - pub fn first(&self) -> Option<&T> { + pub(super) fn first(&self) -> Option<&T> { self.data.front() } - pub fn first_mut(&mut self) -> Option<&mut T> { + pub(super) fn first_mut(&mut self) -> Option<&mut T> { self.data.front_mut() } - pub fn pop_first(&mut self) -> Option { + pub(super) fn pop_first(&mut self) -> Option { let first = self.data.pop_front()?; self.offset += 1; Some(first) } - pub fn last(&self) -> Option<&T> { + pub(super) fn last(&self) -> Option<&T> { self.data.back() } - pub fn last_mut(&mut self) -> Option<&mut T> { + pub(super) fn last_mut(&mut self) -> Option<&mut T> { self.data.back_mut() } } diff --git a/compiler/rustc_ast_pretty/src/pprust/state/fixup.rs b/compiler/rustc_ast_pretty/src/pprust/state/fixup.rs index 86d4796e9ce..c9baca72485 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/fixup.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/fixup.rs @@ -110,13 +110,13 @@ impl Default for FixupContext { impl FixupContext { /// Create the initial fixup for printing an expression in statement /// position. - pub fn new_stmt() -> Self { + pub(crate) fn new_stmt() -> Self { FixupContext { stmt: true, ..FixupContext::default() } } /// Create the initial fixup for printing an expression as the right-hand /// side of a match arm. - pub fn new_match_arm() -> Self { + pub(crate) fn new_match_arm() -> Self { FixupContext { match_arm: true, ..FixupContext::default() } } @@ -124,7 +124,7 @@ impl FixupContext { /// of an `if` or `while`. There are a few other positions which are /// grammatically equivalent and also use this, such as the iterator /// expression in `for` and the scrutinee in `match`. - pub fn new_cond() -> Self { + pub(crate) fn new_cond() -> Self { FixupContext { parenthesize_exterior_struct_lit: true, ..FixupContext::default() } } @@ -139,7 +139,7 @@ impl FixupContext { /// /// Not every expression has a leftmost subexpression. For example neither /// `-$a` nor `[$a]` have one. - pub fn leftmost_subexpression(self) -> Self { + pub(crate) fn leftmost_subexpression(self) -> Self { FixupContext { stmt: false, leftmost_subexpression_in_stmt: self.stmt || self.leftmost_subexpression_in_stmt, @@ -158,7 +158,7 @@ impl FixupContext { /// current expression, and is not surrounded by a paren/bracket/brace. For /// example the `$b` in `$a + $b` and `-$b`, but not the one in `[$b]` or /// `$a.f($b)`. - pub fn subsequent_subexpression(self) -> Self { + pub(crate) fn subsequent_subexpression(self) -> Self { FixupContext { stmt: false, leftmost_subexpression_in_stmt: false, @@ -173,7 +173,7 @@ impl FixupContext { /// /// The documentation on `FixupContext::leftmost_subexpression_in_stmt` has /// examples. - pub fn would_cause_statement_boundary(self, expr: &Expr) -> bool { + pub(crate) fn would_cause_statement_boundary(self, expr: &Expr) -> bool { (self.leftmost_subexpression_in_stmt && !classify::expr_requires_semi_to_be_stmt(expr)) || (self.leftmost_subexpression_in_match_arm && classify::expr_is_complete(expr)) } @@ -189,7 +189,7 @@ impl FixupContext { /// /// - `true && false`, because otherwise this would be misinterpreted as a /// "let chain". - pub fn needs_par_as_let_scrutinee(self, expr: &Expr) -> bool { + pub(crate) fn needs_par_as_let_scrutinee(self, expr: &Expr) -> bool { self.parenthesize_exterior_struct_lit && parser::contains_exterior_struct_lit(expr) || parser::needs_par_as_let_scrutinee(expr.precedence().order()) } diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index d057dcfdf9d..e46dabc7a6e 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -846,7 +846,7 @@ pub fn find_deprecation( sess.dcx().emit_err( session_diagnostics::DeprecatedItemSuggestion { span: mi.span, - is_nightly: sess.is_nightly_build().then_some(()), + is_nightly: sess.is_nightly_build(), details: (), }, ); diff --git a/compiler/rustc_attr/src/lib.rs b/compiler/rustc_attr/src/lib.rs index 1ecfc42ec1d..0dad6372389 100644 --- a/compiler/rustc_attr/src/lib.rs +++ b/compiler/rustc_attr/src/lib.rs @@ -9,6 +9,7 @@ #![doc(rust_logo)] #![feature(let_chains)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end mod builtin; diff --git a/compiler/rustc_attr/src/session_diagnostics.rs b/compiler/rustc_attr/src/session_diagnostics.rs index 92a3a385a74..234a0ef28a2 100644 --- a/compiler/rustc_attr/src/session_diagnostics.rs +++ b/compiler/rustc_attr/src/session_diagnostics.rs @@ -127,7 +127,7 @@ pub(crate) enum InvalidIssueStringCause { } impl InvalidIssueStringCause { - pub fn from_int_error_kind(span: Span, kind: &IntErrorKind) -> Option { + pub(crate) fn from_int_error_kind(span: Span, kind: &IntErrorKind) -> Option { match kind { IntErrorKind::Empty => Some(Self::Empty { span }), IntErrorKind::InvalidDigit => Some(Self::InvalidDigit { span }), @@ -303,7 +303,7 @@ pub(crate) enum IncorrectReprFormatGenericCause<'a> { } impl<'a> IncorrectReprFormatGenericCause<'a> { - pub fn from_lit_kind(span: Span, kind: &ast::LitKind, name: &'a str) -> Option { + pub(crate) fn from_lit_kind(span: Span, kind: &ast::LitKind, name: &'a str) -> Option { match kind { ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => { Some(Self::Int { span, name, int: int.get() }) @@ -342,7 +342,7 @@ pub(crate) struct DeprecatedItemSuggestion { pub span: Span, #[help] - pub is_nightly: Option<()>, + pub is_nightly: bool, #[note] pub details: (), diff --git a/compiler/rustc_baked_icu_data/src/lib.rs b/compiler/rustc_baked_icu_data/src/lib.rs index e964a709757..f86a9db61c6 100644 --- a/compiler/rustc_baked_icu_data/src/lib.rs +++ b/compiler/rustc_baked_icu_data/src/lib.rs @@ -25,6 +25,7 @@ #![allow(internal_features)] #![doc(rust_logo)] #![feature(rustdoc_internals)] +// #![warn(unreachable_pub)] // don't use because this crate is mostly generated code // tidy-alphabetical-end mod data { diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs index 76e39fe94af..2c672dbf8c4 100644 --- a/compiler/rustc_borrowck/src/borrowck_errors.rs +++ b/compiler/rustc_borrowck/src/borrowck_errors.rs @@ -9,7 +9,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::Span; impl<'infcx, 'tcx> crate::MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { - pub fn dcx(&self) -> DiagCtxtHandle<'infcx> { + pub(crate) fn dcx(&self) -> DiagCtxtHandle<'infcx> { self.infcx.dcx() } @@ -290,7 +290,7 @@ impl<'infcx, 'tcx> crate::MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { ty: Ty<'_>, is_index: Option, ) -> Diag<'infcx> { - let type_name = match (&ty.kind(), is_index) { + let type_name = match (ty.kind(), is_index) { (&ty::Array(_, _), Some(true)) | (&ty::Array(_, _), None) => "array", (&ty::Slice(_), _) => "slice", _ => span_bug!(move_from_span, "this path should not cause illegal move"), diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index 77794a8525f..2795bc7162f 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -14,7 +14,7 @@ use rustc_mir_dataflow::{Analysis, AnalysisDomain, GenKill, Results, ResultsVisi use crate::{places_conflict, BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext}; /// The results of the dataflow analyses used by the borrow checker. -pub struct BorrowckResults<'a, 'mir, 'tcx> { +pub(crate) struct BorrowckResults<'a, 'mir, 'tcx> { pub(crate) borrows: Results<'tcx, Borrows<'a, 'mir, 'tcx>>, pub(crate) uninits: Results<'tcx, MaybeUninitializedPlaces<'a, 'mir, 'tcx>>, pub(crate) ever_inits: Results<'tcx, EverInitializedPlaces<'a, 'mir, 'tcx>>, @@ -22,7 +22,7 @@ pub struct BorrowckResults<'a, 'mir, 'tcx> { /// The transient state of the dataflow analyses used by the borrow checker. #[derive(Debug)] -pub struct BorrowckFlowState<'a, 'mir, 'tcx> { +pub(crate) struct BorrowckFlowState<'a, 'mir, 'tcx> { pub(crate) borrows: as AnalysisDomain<'tcx>>::Domain, pub(crate) uninits: as AnalysisDomain<'tcx>>::Domain, pub(crate) ever_inits: as AnalysisDomain<'tcx>>::Domain, diff --git a/compiler/rustc_borrowck/src/def_use.rs b/compiler/rustc_borrowck/src/def_use.rs index 1f0b0981c8f..263f68d6a3d 100644 --- a/compiler/rustc_borrowck/src/def_use.rs +++ b/compiler/rustc_borrowck/src/def_use.rs @@ -4,13 +4,13 @@ use rustc_middle::mir::visit::{ }; #[derive(Eq, PartialEq, Clone)] -pub enum DefUse { +pub(crate) enum DefUse { Def, Use, Drop, } -pub fn categorize(context: PlaceContext) -> Option { +pub(crate) fn categorize(context: PlaceContext) -> Option { match context { /////////////////////////////////////////////////////////////////////////// // DEFS @@ -55,8 +55,8 @@ pub fn categorize(context: PlaceContext) -> Option { PlaceContext::NonMutatingUse(NonMutatingUseContext::PlaceMention) | PlaceContext::NonUse(NonUseContext::AscribeUserTy(_)) | - PlaceContext::MutatingUse(MutatingUseContext::AddressOf) | - PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf) | + PlaceContext::MutatingUse(MutatingUseContext::RawBorrow) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::RawBorrow) | PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect) | PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) | PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) | diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index a58c7c43246..aaeedde2bed 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -645,7 +645,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { } } - pub fn suggest_reborrow( + pub(crate) fn suggest_reborrow( &self, err: &mut Diag<'infcx>, span: Span, @@ -678,14 +678,15 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { let inits = &self.move_data.init_path_map[mpi]; let move_path = &self.move_data.move_paths[mpi]; let decl_span = self.body.local_decls[move_path.place.local].source_info.span; - let mut spans = vec![]; + let mut spans_set = FxIndexSet::default(); for init_idx in inits { let init = &self.move_data.inits[*init_idx]; let span = init.span(self.body); if !span.is_dummy() { - spans.push(span); + spans_set.insert(span); } } + let spans: Vec<_> = spans_set.into_iter().collect(); let (name, desc) = match self.describe_place_with_options( moved_place, @@ -1891,10 +1892,10 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { struct FindUselessClone<'tcx> { tcx: TyCtxt<'tcx>, typeck_results: &'tcx ty::TypeckResults<'tcx>, - pub clones: Vec<&'tcx hir::Expr<'tcx>>, + clones: Vec<&'tcx hir::Expr<'tcx>>, } impl<'tcx> FindUselessClone<'tcx> { - pub fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { + fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { Self { tcx, typeck_results: tcx.typeck(def_id), clones: vec![] } } } @@ -1916,7 +1917,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { let body = hir.body(body_id).value; expr_finder.visit_expr(body); - pub struct Holds<'tcx> { + struct Holds<'tcx> { ty: Ty<'tcx>, } @@ -3989,7 +3990,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { } else { let ty = self.infcx.tcx.type_of(self.mir_def_id()).instantiate_identity(); match ty.kind() { - ty::FnDef(_, _) | ty::FnPtr(_) => self.annotate_fn_sig( + ty::FnDef(_, _) | ty::FnPtr(..) => self.annotate_fn_sig( self.mir_def_id(), self.infcx.tcx.fn_sig(self.mir_def_id()).instantiate_identity(), ), diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index a2e5c7b8514..33f91d7ad30 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -58,11 +58,11 @@ pub(crate) use region_name::{RegionName, RegionNameSource}; pub(crate) use rustc_middle::util::CallKind; pub(super) struct DescribePlaceOpt { - pub including_downcast: bool, + including_downcast: bool, /// Enable/Disable tuple fields. /// For example `x` tuple. if it's `true` `x.0`. Otherwise `x` - pub including_tuple_field: bool, + including_tuple_field: bool, } pub(super) struct IncludingTupleField(pub(super) bool); diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 792f1548e08..42b1ffd58ad 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -16,7 +16,7 @@ use crate::prefixes::PrefixSet; use crate::MirBorrowckCtxt; #[derive(Debug)] -pub enum IllegalMoveOriginKind<'tcx> { +pub(crate) enum IllegalMoveOriginKind<'tcx> { /// Illegal move due to attempt to move from behind a reference. BorrowedContent { /// The place the reference refers to: if erroneous code was trying to diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 0303b80cace..7b791928689 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -1374,7 +1374,7 @@ impl<'tcx> Visitor<'tcx> for BindingFinder { } } -pub fn mut_borrow_of_mutable_ref(local_decl: &LocalDecl<'_>, local_name: Option) -> bool { +fn mut_borrow_of_mutable_ref(local_decl: &LocalDecl<'_>, local_name: Option) -> bool { debug!("local_info: {:?}, ty.kind(): {:?}", local_decl.local_info, local_decl.ty.kind()); match *local_decl.local_info() { diff --git a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs index de0df347429..a59b7b3cde9 100644 --- a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs +++ b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs @@ -31,7 +31,7 @@ enum SuggestedConstraint { /// /// Adds a help note suggesting adding a where clause with the needed constraints. #[derive(Default)] -pub struct OutlivesSuggestionBuilder { +pub(crate) struct OutlivesSuggestionBuilder { /// The list of outlives constraints that need to be added. Specifically, we map each free /// region to all other regions that it must outlive. I will use the shorthand `fr: /// outlived_frs`. Not all of these regions will already have names necessarily. Some could be diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 451e8bcb16d..ab48a09cfa4 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -72,22 +72,24 @@ impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> { pub(crate) struct RegionErrors<'tcx>(Vec<(RegionErrorKind<'tcx>, ErrorGuaranteed)>, TyCtxt<'tcx>); impl<'tcx> RegionErrors<'tcx> { - pub fn new(tcx: TyCtxt<'tcx>) -> Self { + pub(crate) fn new(tcx: TyCtxt<'tcx>) -> Self { Self(vec![], tcx) } #[track_caller] - pub fn push(&mut self, val: impl Into>) { + pub(crate) fn push(&mut self, val: impl Into>) { let val = val.into(); let guar = self.1.sess.dcx().delayed_bug(format!("{val:?}")); self.0.push((val, guar)); } - pub fn is_empty(&self) -> bool { + pub(crate) fn is_empty(&self) -> bool { self.0.is_empty() } - pub fn into_iter(self) -> impl Iterator, ErrorGuaranteed)> { + pub(crate) fn into_iter( + self, + ) -> impl Iterator, ErrorGuaranteed)> { self.0.into_iter() } - pub fn has_errors(&self) -> Option { + pub(crate) fn has_errors(&self) -> Option { self.0.get(0).map(|x| x.1) } } @@ -141,7 +143,7 @@ pub(crate) enum RegionErrorKind<'tcx> { /// Information about the various region constraints involved in a borrow checker error. #[derive(Clone, Debug)] -pub struct ErrorConstraintInfo<'tcx> { +pub(crate) struct ErrorConstraintInfo<'tcx> { // fr: outlived_fr pub(super) fr: RegionVid, pub(super) fr_is_local: bool, diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 9c2a0036bef..bb1aea14693 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -12,6 +12,7 @@ #![feature(rustdoc_internals)] #![feature(stmt_expr_attributes)] #![feature(try_blocks)] +#![warn(unreachable_pub)] // tidy-alphabetical-end #[macro_use] @@ -1242,7 +1243,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { ); } - &Rvalue::AddressOf(mutability, place) => { + &Rvalue::RawPtr(mutability, place) => { let access_kind = match mutability { Mutability::Mut => ( Deep, @@ -1644,7 +1645,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { | ty::Pat(_, _) | ty::Slice(_) | ty::FnDef(_, _) - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::Dynamic(_, _, _) | ty::Closure(_, _) | ty::CoroutineClosure(_, _) @@ -1689,7 +1690,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { | ty::RawPtr(_, _) | ty::Ref(_, _, _) | ty::FnDef(_, _) - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::Dynamic(_, _, _) | ty::CoroutineWitness(..) | ty::Never @@ -2444,7 +2445,7 @@ mod diags { } } - pub struct BorrowckDiags<'infcx, 'tcx> { + pub(crate) struct BorrowckDiags<'infcx, 'tcx> { /// This field keeps track of move errors that are to be reported for given move indices. /// /// There are situations where many errors can be reported for a single move out (see @@ -2468,7 +2469,7 @@ mod diags { } impl<'infcx, 'tcx> BorrowckDiags<'infcx, 'tcx> { - pub fn new() -> Self { + pub(crate) fn new() -> Self { BorrowckDiags { buffered_move_errors: BTreeMap::new(), buffered_mut_errors: Default::default(), @@ -2476,25 +2477,25 @@ mod diags { } } - pub fn buffer_error(&mut self, diag: Diag<'infcx>) { + pub(crate) fn buffer_error(&mut self, diag: Diag<'infcx>) { self.buffered_diags.push(BufferedDiag::Error(diag)); } - pub fn buffer_non_error(&mut self, diag: Diag<'infcx, ()>) { + pub(crate) fn buffer_non_error(&mut self, diag: Diag<'infcx, ()>) { self.buffered_diags.push(BufferedDiag::NonError(diag)); } } impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { - pub fn buffer_error(&mut self, diag: Diag<'infcx>) { + pub(crate) fn buffer_error(&mut self, diag: Diag<'infcx>) { self.diags.buffer_error(diag); } - pub fn buffer_non_error(&mut self, diag: Diag<'infcx, ()>) { + pub(crate) fn buffer_non_error(&mut self, diag: Diag<'infcx, ()>) { self.diags.buffer_non_error(diag); } - pub fn buffer_move_error( + pub(crate) fn buffer_move_error( &mut self, move_out_indices: Vec, place_and_err: (PlaceRef<'tcx>, Diag<'infcx>), @@ -2510,16 +2511,19 @@ mod diags { } } - pub fn get_buffered_mut_error(&mut self, span: Span) -> Option<(Diag<'infcx>, usize)> { + pub(crate) fn get_buffered_mut_error( + &mut self, + span: Span, + ) -> Option<(Diag<'infcx>, usize)> { // FIXME(#120456) - is `swap_remove` correct? self.diags.buffered_mut_errors.swap_remove(&span) } - pub fn buffer_mut_error(&mut self, span: Span, diag: Diag<'infcx>, count: usize) { + pub(crate) fn buffer_mut_error(&mut self, span: Span, diag: Diag<'infcx>, count: usize) { self.diags.buffered_mut_errors.insert(span, (diag, count)); } - pub fn emit_errors(&mut self) -> Option { + pub(crate) fn emit_errors(&mut self) -> Option { let mut res = None; // Buffer any move errors that we collected and de-duplicated. @@ -2553,7 +2557,7 @@ mod diags { self.diags.buffered_diags.is_empty() } - pub fn has_move_error( + pub(crate) fn has_move_error( &self, move_out_indices: &[MoveOutIndex], ) -> Option<&(PlaceRef<'tcx>, Diag<'infcx>)> { diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs index 42d0c2038f8..311f17f15b9 100644 --- a/compiler/rustc_borrowck/src/places_conflict.rs +++ b/compiler/rustc_borrowck/src/places_conflict.rs @@ -201,7 +201,7 @@ fn place_components_conflict<'tcx>( let base_ty = base.ty(body, tcx).ty; - match (elem, &base_ty.kind(), access) { + match (elem, base_ty.kind(), access) { (_, _, Shallow(Some(ArtificialField::ArrayLength))) | (_, _, Shallow(Some(ArtificialField::FakeBorrow))) => { // The array length is like additional fields on the diff --git a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs index f090da031a0..a57041cd04c 100644 --- a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs +++ b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs @@ -269,7 +269,7 @@ impl<'cx, 'tcx> LoanInvalidationsGenerator<'cx, 'tcx> { self.access_place(location, place, access_kind, LocalMutationIsAllowed::No); } - &Rvalue::AddressOf(mutability, place) => { + &Rvalue::RawPtr(mutability, place) => { let access_kind = match mutability { Mutability::Mut => ( Deep, diff --git a/compiler/rustc_borrowck/src/prefixes.rs b/compiler/rustc_borrowck/src/prefixes.rs index d3bfd1c418f..39d831378cd 100644 --- a/compiler/rustc_borrowck/src/prefixes.rs +++ b/compiler/rustc_borrowck/src/prefixes.rs @@ -8,7 +8,7 @@ use rustc_middle::mir::{PlaceRef, ProjectionElem}; use super::MirBorrowckCtxt; -pub trait IsPrefixOf<'tcx> { +pub(crate) trait IsPrefixOf<'tcx> { fn is_prefix_of(&self, other: PlaceRef<'tcx>) -> bool; } diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index c8dc012de4a..6cbdd890b5e 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -42,9 +42,9 @@ mod graphviz; mod opaque_types; mod reverse_sccs; -pub mod values; +pub(crate) mod values; -pub type ConstraintSccs = Sccs; +pub(crate) type ConstraintSccs = Sccs; /// An annotation for region graph SCCs that tracks /// the values of its elements. @@ -226,7 +226,7 @@ pub(crate) struct AppliedMemberConstraint { } #[derive(Debug)] -pub struct RegionDefinition<'tcx> { +pub(crate) struct RegionDefinition<'tcx> { /// What kind of variable is this -- a free region? existential /// variable? etc. (See the `NllRegionVariableOrigin` for more /// info.) @@ -288,7 +288,7 @@ pub(crate) enum Cause { /// `InferCtxt::process_registered_region_obligations` and /// `InferCtxt::type_must_outlive` in `rustc_infer::infer::InferCtxt`. #[derive(Clone, Debug)] -pub struct TypeTest<'tcx> { +pub(crate) struct TypeTest<'tcx> { /// The type `T` that must outlive the region. pub generic_kind: GenericKind<'tcx>, @@ -320,7 +320,7 @@ enum Trace<'tcx> { } #[derive(Clone, PartialEq, Eq, Debug)] -pub enum ExtraConstraintInfo { +pub(crate) enum ExtraConstraintInfo { PlaceholderFromPredicate(Span), } @@ -2259,7 +2259,7 @@ impl<'tcx> RegionDefinition<'tcx> { } #[derive(Clone, Debug)] -pub struct BlameConstraint<'tcx> { +pub(crate) struct BlameConstraint<'tcx> { pub category: ConstraintCategory<'tcx>, pub from_closure: bool, pub cause: ObligationCause<'tcx>, diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 1073ea40694..cd66acd0a8f 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -473,20 +473,20 @@ struct LazyOpaqueTyEnv<'tcx> { } impl<'tcx> LazyOpaqueTyEnv<'tcx> { - pub fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { + fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { Self { tcx, def_id, canonical_args: std::cell::OnceCell::new() } } - pub fn param_equal_static(&self, param_index: usize) -> bool { + fn param_equal_static(&self, param_index: usize) -> bool { self.get_canonical_args()[param_index].expect_region().is_static() } - pub fn params_equal(&self, param1: usize, param2: usize) -> bool { + fn params_equal(&self, param1: usize, param2: usize) -> bool { let canonical_args = self.get_canonical_args(); canonical_args[param1] == canonical_args[param2] } - pub fn param_is_error(&self, param_index: usize) -> Result<(), ErrorGuaranteed> { + fn param_is_error(&self, param_index: usize) -> Result<(), ErrorGuaranteed> { self.get_canonical_args()[param_index].error_reported() } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 6bab0f33c19..d8f74840eb5 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -86,7 +86,7 @@ macro_rules! span_mirbug_and_err { mod canonical; mod constraint_conversion; -pub mod free_region_relations; +pub(crate) mod free_region_relations; mod input_output; pub(crate) mod liveness; mod relate_tys; @@ -756,7 +756,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { PlaceContext::MutatingUse(_) => ty::Invariant, PlaceContext::NonUse(StorageDead | StorageLive | VarDebugInfo) => ty::Invariant, PlaceContext::NonMutatingUse( - Inspect | Copy | Move | PlaceMention | SharedBorrow | FakeBorrow | AddressOf + Inspect | Copy | Move | PlaceMention | SharedBorrow | FakeBorrow | RawBorrow | Projection, ) => ty::Covariant, PlaceContext::NonUse(AscribeUserTy(variance)) => variance, @@ -1364,7 +1364,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { debug!("func_ty.kind: {:?}", func_ty.kind()); let sig = match func_ty.kind() { - ty::FnDef(..) | ty::FnPtr(_) => func_ty.fn_sig(tcx), + ty::FnDef(..) | ty::FnPtr(..) => func_ty.fn_sig(tcx), _ => { span_mirbug!(self, term, "call to non-function {:?}", func_ty); return; @@ -1989,9 +1989,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let ty_fn_ptr_from = Ty::new_fn_ptr(tcx, fn_sig); - if let Err(terr) = self.eq_types( - *ty, + if let Err(terr) = self.sub_types( ty_fn_ptr_from, + *ty, location.to_locations(), ConstraintCategory::Cast { unsize_to: None }, ) { @@ -2014,9 +2014,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let ty_fn_ptr_from = Ty::new_fn_ptr(tcx, tcx.signature_unclosure(sig, *safety)); - if let Err(terr) = self.eq_types( - *ty, + if let Err(terr) = self.sub_types( ty_fn_ptr_from, + *ty, location.to_locations(), ConstraintCategory::Cast { unsize_to: None }, ) { @@ -2043,9 +2043,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let ty_fn_ptr_from = tcx.safe_to_unsafe_fn_ty(fn_sig); - if let Err(terr) = self.eq_types( - *ty, + if let Err(terr) = self.sub_types( ty_fn_ptr_from, + *ty, location.to_locations(), ConstraintCategory::Cast { unsize_to: None }, ) { @@ -2411,7 +2411,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let ty_left = left.ty(body, tcx); match ty_left.kind() { // Types with regions are comparable if they have a common super-type. - ty::RawPtr(_, _) | ty::FnPtr(_) => { + ty::RawPtr(_, _) | ty::FnPtr(..) => { let ty_right = right.ty(body, tcx); let common_ty = self.infcx.next_ty_var(body.source_info(location).span); self.sub_types( @@ -2468,7 +2468,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.check_operand(right, location); } - Rvalue::AddressOf(..) + Rvalue::RawPtr(..) | Rvalue::ThreadLocalRef(..) | Rvalue::Len(..) | Rvalue::Discriminant(..) @@ -2485,7 +2485,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { | Rvalue::ThreadLocalRef(_) | Rvalue::Repeat(..) | Rvalue::Ref(..) - | Rvalue::AddressOf(..) + | Rvalue::RawPtr(..) | Rvalue::Len(..) | Rvalue::Cast(..) | Rvalue::ShallowInitBox(..) diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index 8da4d80badf..35d8e2573fe 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -57,7 +57,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } -pub struct NllTypeRelating<'me, 'bccx, 'tcx> { +struct NllTypeRelating<'me, 'bccx, 'tcx> { type_checker: &'me mut TypeChecker<'bccx, 'tcx>, /// Where (and why) is this relation taking place? @@ -82,7 +82,7 @@ pub struct NllTypeRelating<'me, 'bccx, 'tcx> { } impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> { - pub fn new( + fn new( type_checker: &'me mut TypeChecker<'bccx, 'tcx>, locations: Locations, category: ConstraintCategory<'tcx>, diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 1ad80cb122a..2e41c918774 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -39,7 +39,7 @@ use crate::renumber::RegionCtxt; use crate::BorrowckInferCtxt; #[derive(Debug)] -pub struct UniversalRegions<'tcx> { +pub(crate) struct UniversalRegions<'tcx> { indices: UniversalRegionIndices<'tcx>, /// The vid assigned to `'static` @@ -95,7 +95,7 @@ pub struct UniversalRegions<'tcx> { /// regions appear free in the defining type and late-bound regions /// appear bound in the signature. #[derive(Copy, Clone, Debug)] -pub enum DefiningTy<'tcx> { +pub(crate) enum DefiningTy<'tcx> { /// The MIR is a closure. The signature is found via /// `ClosureArgs::closure_sig_ty`. Closure(DefId, GenericArgsRef<'tcx>), @@ -131,7 +131,7 @@ impl<'tcx> DefiningTy<'tcx> { /// not a closure or coroutine, there are no upvars, and hence it /// will be an empty list. The order of types in this list will /// match up with the upvar order in the HIR, typesystem, and MIR. - pub fn upvar_tys(self) -> &'tcx ty::List> { + pub(crate) fn upvar_tys(self) -> &'tcx ty::List> { match self { DefiningTy::Closure(_, args) => args.as_closure().upvar_tys(), DefiningTy::CoroutineClosure(_, args) => args.as_coroutine_closure().upvar_tys(), @@ -145,7 +145,7 @@ impl<'tcx> DefiningTy<'tcx> { /// Number of implicit inputs -- notably the "environment" /// parameter for closures -- that appear in MIR but not in the /// user's code. - pub fn implicit_inputs(self) -> usize { + pub(crate) fn implicit_inputs(self) -> usize { match self { DefiningTy::Closure(..) | DefiningTy::CoroutineClosure(..) @@ -154,15 +154,15 @@ impl<'tcx> DefiningTy<'tcx> { } } - pub fn is_fn_def(&self) -> bool { + pub(crate) fn is_fn_def(&self) -> bool { matches!(*self, DefiningTy::FnDef(..)) } - pub fn is_const(&self) -> bool { + pub(crate) fn is_const(&self) -> bool { matches!(*self, DefiningTy::Const(..) | DefiningTy::InlineConst(..)) } - pub fn def_id(&self) -> DefId { + pub(crate) fn def_id(&self) -> DefId { match *self { DefiningTy::Closure(def_id, ..) | DefiningTy::CoroutineClosure(def_id, ..) @@ -196,7 +196,7 @@ struct UniversalRegionIndices<'tcx> { } #[derive(Debug, PartialEq)] -pub enum RegionClassification { +pub(crate) enum RegionClassification { /// A **global** region is one that can be named from /// anywhere. There is only one, `'static`. Global, @@ -246,7 +246,7 @@ impl<'tcx> UniversalRegions<'tcx> { /// MIR -- that is, all the regions that appear in the function's /// signature. This will also compute the relationships that are /// known between those regions. - pub fn new( + pub(crate) fn new( infcx: &BorrowckInferCtxt<'tcx>, mir_def: LocalDefId, param_env: ty::ParamEnv<'tcx>, @@ -263,7 +263,7 @@ impl<'tcx> UniversalRegions<'tcx> { /// if the `ClosureRegionRequirements` contains something like /// `'1: '2`, then the caller would impose the constraint that /// `V[1]: V[2]`. - pub fn closure_mapping( + pub(crate) fn closure_mapping( tcx: TyCtxt<'tcx>, closure_args: GenericArgsRef<'tcx>, expected_num_vars: usize, @@ -289,13 +289,13 @@ impl<'tcx> UniversalRegions<'tcx> { } /// Returns `true` if `r` is a member of this set of universal regions. - pub fn is_universal_region(&self, r: RegionVid) -> bool { + pub(crate) fn is_universal_region(&self, r: RegionVid) -> bool { (FIRST_GLOBAL_INDEX..self.num_universals).contains(&r.index()) } /// Classifies `r` as a universal region, returning `None` if this /// is not a member of this set of universal regions. - pub fn region_classification(&self, r: RegionVid) -> Option { + pub(crate) fn region_classification(&self, r: RegionVid) -> Option { let index = r.index(); if (FIRST_GLOBAL_INDEX..self.first_extern_index).contains(&index) { Some(RegionClassification::Global) @@ -310,17 +310,17 @@ impl<'tcx> UniversalRegions<'tcx> { /// Returns an iterator over all the RegionVids corresponding to /// universally quantified free regions. - pub fn universal_regions(&self) -> impl Iterator { + pub(crate) fn universal_regions(&self) -> impl Iterator { (FIRST_GLOBAL_INDEX..self.num_universals).map(RegionVid::from_usize) } /// Returns `true` if `r` is classified as a local region. - pub fn is_local_free_region(&self, r: RegionVid) -> bool { + pub(crate) fn is_local_free_region(&self, r: RegionVid) -> bool { self.region_classification(r) == Some(RegionClassification::Local) } /// Returns the number of universal regions created in any category. - pub fn len(&self) -> usize { + pub(crate) fn len(&self) -> usize { self.num_universals } @@ -329,19 +329,19 @@ impl<'tcx> UniversalRegions<'tcx> { /// closure type (versus those bound in the closure /// signature). They are therefore the regions between which the /// closure may impose constraints that its creator must verify. - pub fn num_global_and_external_regions(&self) -> usize { + pub(crate) fn num_global_and_external_regions(&self) -> usize { self.first_local_index } /// Gets an iterator over all the early-bound regions that have names. - pub fn named_universal_regions<'s>( + pub(crate) fn named_universal_regions<'s>( &'s self, ) -> impl Iterator, ty::RegionVid)> + 's { self.indices.indices.iter().map(|(&r, &v)| (r, v)) } /// See `UniversalRegionIndices::to_region_vid`. - pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid { + pub(crate) fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid { self.indices.to_region_vid(r) } @@ -416,7 +416,7 @@ impl<'tcx> UniversalRegions<'tcx> { } } - pub fn tainted_by_errors(&self) -> Option { + pub(crate) fn tainted_by_errors(&self) -> Option { self.indices.tainted_by_errors.get() } } @@ -880,7 +880,7 @@ impl<'tcx> UniversalRegionIndices<'tcx> { /// reference those regions from the `ParamEnv`. It is also used /// during initialization. Relies on the `indices` map having been /// fully initialized. - pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid { + fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid { if let ty::ReVar(..) = *r { r.as_var() } else if let ty::ReError(guar) = *r { @@ -899,7 +899,7 @@ impl<'tcx> UniversalRegionIndices<'tcx> { /// Replaces all free regions in `value` with region vids, as /// returned by `to_region_vid`. - pub fn fold_to_region_vids(&self, tcx: TyCtxt<'tcx>, value: T) -> T + fn fold_to_region_vids(&self, tcx: TyCtxt<'tcx>, value: T) -> T where T: TypeFoldable>, { diff --git a/compiler/rustc_borrowck/src/util/collect_writes.rs b/compiler/rustc_borrowck/src/util/collect_writes.rs index 93c7810b545..55f1073176a 100644 --- a/compiler/rustc_borrowck/src/util/collect_writes.rs +++ b/compiler/rustc_borrowck/src/util/collect_writes.rs @@ -1,7 +1,7 @@ use rustc_middle::mir::visit::{PlaceContext, Visitor}; use rustc_middle::mir::{Body, Local, Location}; -pub trait FindAssignments { +pub(crate) trait FindAssignments { // Finds all statements that assign directly to local (i.e., X = ...) // and returns their locations. fn find_assignments(&self, local: Local) -> Vec; diff --git a/compiler/rustc_borrowck/src/util/mod.rs b/compiler/rustc_borrowck/src/util/mod.rs index 7377d4de727..5f2960b768b 100644 --- a/compiler/rustc_borrowck/src/util/mod.rs +++ b/compiler/rustc_borrowck/src/util/mod.rs @@ -1,3 +1,3 @@ mod collect_writes; -pub use collect_writes::FindAssignments; +pub(crate) use collect_writes::FindAssignments; diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index ed54c0c8662..ae2627d6938 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -328,7 +328,7 @@ pub fn parse_asm_args<'a>( /// Otherwise, the suggestion will be incorrect. fn err_duplicate_option(p: &Parser<'_>, symbol: Symbol, span: Span) { // Tool-only output - let full_span = if p.token.kind == token::Comma { span.to(p.token.span) } else { span }; + let full_span = if p.token == token::Comma { span.to(p.token.span) } else { span }; p.dcx().emit_err(errors::AsmOptAlreadyprovided { span, symbol, full_span }); } @@ -338,7 +338,7 @@ fn err_duplicate_option(p: &Parser<'_>, symbol: Symbol, span: Span) { /// Otherwise, the suggestion will be incorrect. fn err_unsupported_option(p: &Parser<'_>, symbol: Symbol, span: Span) { // Tool-only output - let full_span = if p.token.kind == token::Comma { span.to(p.token.span) } else { span }; + let full_span = if p.token == token::Comma { span.to(p.token.span) } else { span }; p.dcx().emit_err(errors::GlobalAsmUnsupportedOption { span, symbol, full_span }); } diff --git a/compiler/rustc_builtin_macros/src/cfg_accessible.rs b/compiler/rustc_builtin_macros/src/cfg_accessible.rs index 006b6aa823f..3d3bd3aea05 100644 --- a/compiler/rustc_builtin_macros/src/cfg_accessible.rs +++ b/compiler/rustc_builtin_macros/src/cfg_accessible.rs @@ -47,7 +47,6 @@ impl MultiItemModifier for Expander { ) -> ExpandResult, Annotatable> { let template = AttributeTemplate { list: Some("path"), ..Default::default() }; validate_attr::check_builtin_meta_item( - &ecx.ecfg.features, &ecx.sess.psess, meta_item, ast::AttrStyle::Outer, diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs index 57bddf0ab60..e8704bc2f63 100644 --- a/compiler/rustc_builtin_macros/src/derive.rs +++ b/compiler/rustc_builtin_macros/src/derive.rs @@ -38,7 +38,6 @@ impl MultiItemModifier for Expander { let template = AttributeTemplate { list: Some("Trait1, Trait2, ..."), ..Default::default() }; validate_attr::check_builtin_meta_item( - features, &sess.psess, meta_item, ast::AttrStyle::Outer, diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index c90a9164886..289e92a69b2 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -351,15 +351,15 @@ struct TypeParameter { pub(crate) struct BlockOrExpr(ThinVec, Option>); impl BlockOrExpr { - pub fn new_stmts(stmts: ThinVec) -> BlockOrExpr { + pub(crate) fn new_stmts(stmts: ThinVec) -> BlockOrExpr { BlockOrExpr(stmts, None) } - pub fn new_expr(expr: P) -> BlockOrExpr { + pub(crate) fn new_expr(expr: P) -> BlockOrExpr { BlockOrExpr(ThinVec::new(), Some(expr)) } - pub fn new_mixed(stmts: ThinVec, expr: Option>) -> BlockOrExpr { + pub(crate) fn new_mixed(stmts: ThinVec, expr: Option>) -> BlockOrExpr { BlockOrExpr(stmts, expr) } @@ -461,7 +461,7 @@ fn find_type_parameters( } impl<'a> TraitDef<'a> { - pub fn expand( + pub(crate) fn expand( self, cx: &ExtCtxt<'_>, mitem: &ast::MetaItem, @@ -471,7 +471,7 @@ impl<'a> TraitDef<'a> { self.expand_ext(cx, mitem, item, push, false); } - pub fn expand_ext( + pub(crate) fn expand_ext( self, cx: &ExtCtxt<'_>, mitem: &ast::MetaItem, diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs index 747da2ee43b..42855e255a8 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs @@ -27,17 +27,17 @@ pub(crate) enum PathKind { } impl Path { - pub fn new(path: Vec) -> Path { + pub(crate) fn new(path: Vec) -> Path { Path::new_(path, Vec::new(), PathKind::Std) } - pub fn new_local(path: Symbol) -> Path { + pub(crate) fn new_local(path: Symbol) -> Path { Path::new_(vec![path], Vec::new(), PathKind::Local) } - pub fn new_(path: Vec, params: Vec>, kind: PathKind) -> Path { + pub(crate) fn new_(path: Vec, params: Vec>, kind: PathKind) -> Path { Path { path, params, kind } } - pub fn to_ty( + pub(crate) fn to_ty( &self, cx: &ExtCtxt<'_>, span: Span, @@ -46,7 +46,7 @@ impl Path { ) -> P { cx.ty_path(self.to_path(cx, span, self_ty, self_generics)) } - pub fn to_path( + pub(crate) fn to_path( &self, cx: &ExtCtxt<'_>, span: Span, @@ -87,7 +87,7 @@ pub(crate) fn self_ref() -> Ty { } impl Ty { - pub fn to_ty( + pub(crate) fn to_ty( &self, cx: &ExtCtxt<'_>, span: Span, @@ -108,7 +108,7 @@ impl Ty { } } - pub fn to_path( + pub(crate) fn to_path( &self, cx: &ExtCtxt<'_>, span: Span, @@ -167,10 +167,10 @@ pub(crate) struct Bounds { } impl Bounds { - pub fn empty() -> Bounds { + pub(crate) fn empty() -> Bounds { Bounds { bounds: Vec::new() } } - pub fn to_generics( + pub(crate) fn to_generics( &self, cx: &ExtCtxt<'_>, span: Span, diff --git a/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs b/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs index 7eb1f17a59c..bc41d33a609 100644 --- a/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs +++ b/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs @@ -11,14 +11,13 @@ use rustc_data_structures::flat_map_in_place::FlatMapInPlace; use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_span::symbol::{sym, Ident}; use rustc_span::{Span, Symbol}; -use smallvec::{smallvec, SmallVec}; use thin_vec::{thin_vec, ThinVec}; macro_rules! path { ($span:expr, $($part:ident)::*) => { vec![$(Ident::new(sym::$part, $span),)*] } } -pub fn expand_deriving_smart_ptr( +pub(crate) fn expand_deriving_smart_ptr( cx: &ExtCtxt<'_>, span: Span, _mitem: &MetaItem, @@ -68,43 +67,63 @@ pub fn expand_deriving_smart_ptr( }; // Convert generic parameters (from the struct) into generic args. - let mut pointee_param = None; - let mut multiple_pointee_diag: SmallVec<[_; 2]> = smallvec![]; - let self_params = generics + let self_params: Vec<_> = generics + .params + .iter() + .map(|p| match p.kind { + GenericParamKind::Lifetime => GenericArg::Lifetime(cx.lifetime(p.span(), p.ident)), + GenericParamKind::Type { .. } => GenericArg::Type(cx.ty_ident(p.span(), p.ident)), + GenericParamKind::Const { .. } => GenericArg::Const(cx.const_ident(p.span(), p.ident)), + }) + .collect(); + let type_params: Vec<_> = generics .params .iter() .enumerate() - .map(|(idx, p)| match p.kind { - GenericParamKind::Lifetime => GenericArg::Lifetime(cx.lifetime(p.span(), p.ident)), - GenericParamKind::Type { .. } => { - if p.attrs().iter().any(|attr| attr.has_name(sym::pointee)) { - if pointee_param.is_some() { - multiple_pointee_diag.push(cx.dcx().struct_span_err( - p.span(), - "`SmartPointer` can only admit one type as pointee", - )); - } else { - pointee_param = Some(idx); - } - } - GenericArg::Type(cx.ty_ident(p.span(), p.ident)) + .filter_map(|(idx, p)| { + if let GenericParamKind::Type { .. } = p.kind { + Some((idx, p.span(), p.attrs().iter().any(|attr| attr.has_name(sym::pointee)))) + } else { + None } - GenericParamKind::Const { .. } => GenericArg::Const(cx.const_ident(p.span(), p.ident)), }) - .collect::>(); - let Some(pointee_param_idx) = pointee_param else { + .collect(); + + let pointee_param_idx = if type_params.is_empty() { + // `#[derive(SmartPointer)]` requires at least one generic type on the target `struct` cx.dcx().struct_span_err( span, - "At least one generic type should be designated as `#[pointee]` in order to derive `SmartPointer` traits", + "`SmartPointer` can only be derived on `struct`s that are generic over at least one type", ).emit(); return; - }; - if !multiple_pointee_diag.is_empty() { - for diag in multiple_pointee_diag { - diag.emit(); + } else if type_params.len() == 1 { + // Regardless of the only type param being designed as `#[pointee]` or not, we can just use it as such + type_params[0].0 + } else { + let mut pointees = type_params + .iter() + .filter_map(|&(idx, span, is_pointee)| is_pointee.then_some((idx, span))) + .fuse(); + match (pointees.next(), pointees.next()) { + (Some((idx, _span)), None) => idx, + (None, _) => { + cx.dcx().struct_span_err( + span, + "exactly one generic type parameter must be marked as #[pointee] to derive SmartPointer traits", + ).emit(); + return; + } + (Some((_, one)), Some((_, another))) => { + cx.dcx() + .struct_span_err( + vec![one, another], + "only one type parameter can be marked as `#[pointee]` when deriving SmartPointer traits", + ) + .emit(); + return; + } } - return; - } + }; // Create the type of `self`. let path = cx.path_all(span, false, vec![name_ident], self_params.clone()); diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index 6ca43441e05..4fffffb91c8 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -930,7 +930,7 @@ pub(crate) struct ExpectedItem<'a> { #[derive(Diagnostic)] #[diag(builtin_macros_naked_functions_testing_attribute, code = E0736)] -pub struct NakedFunctionTestingAttribute { +pub(crate) struct NakedFunctionTestingAttribute { #[primary_span] #[label(builtin_macros_naked_attribute)] pub naked_span: Span, diff --git a/compiler/rustc_builtin_macros/src/format_foreign.rs b/compiler/rustc_builtin_macros/src/format_foreign.rs index b52f606f342..866ec72f116 100644 --- a/compiler/rustc_builtin_macros/src/format_foreign.rs +++ b/compiler/rustc_builtin_macros/src/format_foreign.rs @@ -5,7 +5,7 @@ pub(crate) mod printf { /// Represents a single `printf`-style substitution. #[derive(Clone, PartialEq, Debug)] - pub enum Substitution<'a> { + pub(crate) enum Substitution<'a> { /// A formatted output substitution with its internal byte offset. Format(Format<'a>), /// A literal `%%` escape, with its start and end indices. @@ -13,21 +13,21 @@ pub(crate) mod printf { } impl<'a> Substitution<'a> { - pub fn as_str(&self) -> &str { + pub(crate) fn as_str(&self) -> &str { match self { Substitution::Format(fmt) => fmt.span, Substitution::Escape(_) => "%%", } } - pub fn position(&self) -> InnerSpan { + pub(crate) fn position(&self) -> InnerSpan { match self { Substitution::Format(fmt) => fmt.position, &Substitution::Escape((start, end)) => InnerSpan::new(start, end), } } - pub fn set_position(&mut self, start: usize, end: usize) { + pub(crate) fn set_position(&mut self, start: usize, end: usize) { match self { Substitution::Format(fmt) => fmt.position = InnerSpan::new(start, end), Substitution::Escape(pos) => *pos = (start, end), @@ -38,7 +38,7 @@ pub(crate) mod printf { /// /// This ignores cases where the substitution does not have an exact equivalent, or where /// the substitution would be unnecessary. - pub fn translate(&self) -> Result> { + pub(crate) fn translate(&self) -> Result> { match self { Substitution::Format(fmt) => fmt.translate(), Substitution::Escape(_) => Err(None), @@ -48,23 +48,23 @@ pub(crate) mod printf { #[derive(Clone, PartialEq, Debug)] /// A single `printf`-style formatting directive. - pub struct Format<'a> { + pub(crate) struct Format<'a> { /// The entire original formatting directive. - pub span: &'a str, + span: &'a str, /// The (1-based) parameter to be converted. - pub parameter: Option, + parameter: Option, /// Formatting flags. - pub flags: &'a str, + flags: &'a str, /// Minimum width of the output. - pub width: Option, + width: Option, /// Precision of the conversion. - pub precision: Option, + precision: Option, /// Length modifier for the conversion. - pub length: Option<&'a str>, + length: Option<&'a str>, /// Type of parameter being converted. - pub type_: &'a str, + type_: &'a str, /// Byte offset for the start and end of this formatting directive. - pub position: InnerSpan, + position: InnerSpan, } impl Format<'_> { @@ -72,7 +72,7 @@ pub(crate) mod printf { /// /// Returns `Err` in cases where the `printf` directive does not have an exact Rust /// equivalent, rather than guessing. - pub fn translate(&self) -> Result> { + pub(crate) fn translate(&self) -> Result> { use std::fmt::Write; let (c_alt, c_zero, c_left, c_plus) = { @@ -249,7 +249,7 @@ pub(crate) mod printf { /// A general number used in a `printf` formatting directive. #[derive(Copy, Clone, PartialEq, Debug)] - pub enum Num { + enum Num { // The range of these values is technically bounded by `NL_ARGMAX`... but, at least for GNU // libc, it apparently has no real fixed limit. A `u16` is used here on the basis that it // is *vanishingly* unlikely that *anyone* is going to try formatting something wider, or @@ -288,12 +288,12 @@ pub(crate) mod printf { } /// Returns an iterator over all substitutions in a given string. - pub fn iter_subs(s: &str, start_pos: usize) -> Substitutions<'_> { + pub(crate) fn iter_subs(s: &str, start_pos: usize) -> Substitutions<'_> { Substitutions { s, pos: start_pos } } /// Iterator over substitutions in a string. - pub struct Substitutions<'a> { + pub(crate) struct Substitutions<'a> { s: &'a str, pos: usize, } @@ -327,7 +327,7 @@ pub(crate) mod printf { } /// Parse the next substitution from the input string. - pub fn parse_next_substitution(s: &str) -> Option<(Substitution<'_>, &str)> { + fn parse_next_substitution(s: &str) -> Option<(Substitution<'_>, &str)> { use self::State::*; let at = { @@ -615,20 +615,20 @@ pub(crate) mod printf { mod tests; } -pub mod shell { +pub(crate) mod shell { use rustc_span::InnerSpan; use super::strcursor::StrCursor as Cur; #[derive(Clone, PartialEq, Debug)] - pub enum Substitution<'a> { + pub(crate) enum Substitution<'a> { Ordinal(u8, (usize, usize)), Name(&'a str, (usize, usize)), Escape((usize, usize)), } impl Substitution<'_> { - pub fn as_str(&self) -> String { + pub(crate) fn as_str(&self) -> String { match self { Substitution::Ordinal(n, _) => format!("${n}"), Substitution::Name(n, _) => format!("${n}"), @@ -636,17 +636,17 @@ pub mod shell { } } - pub fn position(&self) -> InnerSpan { + pub(crate) fn position(&self) -> InnerSpan { let (Self::Ordinal(_, pos) | Self::Name(_, pos) | Self::Escape(pos)) = self; InnerSpan::new(pos.0, pos.1) } - pub fn set_position(&mut self, start: usize, end: usize) { + fn set_position(&mut self, start: usize, end: usize) { let (Self::Ordinal(_, pos) | Self::Name(_, pos) | Self::Escape(pos)) = self; *pos = (start, end); } - pub fn translate(&self) -> Result> { + pub(crate) fn translate(&self) -> Result> { match self { Substitution::Ordinal(n, _) => Ok(format!("{{{}}}", n)), Substitution::Name(n, _) => Ok(format!("{{{}}}", n)), @@ -656,12 +656,12 @@ pub mod shell { } /// Returns an iterator over all substitutions in a given string. - pub fn iter_subs(s: &str, start_pos: usize) -> Substitutions<'_> { + pub(crate) fn iter_subs(s: &str, start_pos: usize) -> Substitutions<'_> { Substitutions { s, pos: start_pos } } /// Iterator over substitutions in a string. - pub struct Substitutions<'a> { + pub(crate) struct Substitutions<'a> { s: &'a str, pos: usize, } @@ -683,7 +683,7 @@ pub mod shell { } /// Parse the next substitution from the input string. - pub fn parse_next_substitution(s: &str) -> Option<(Substitution<'_>, &str)> { + fn parse_next_substitution(s: &str) -> Option<(Substitution<'_>, &str)> { let at = { let start = s.find('$')?; match s[start + 1..].chars().next()? { @@ -743,24 +743,24 @@ pub mod shell { } mod strcursor { - pub struct StrCursor<'a> { + pub(crate) struct StrCursor<'a> { s: &'a str, pub at: usize, } impl<'a> StrCursor<'a> { - pub fn new_at(s: &'a str, at: usize) -> StrCursor<'a> { + pub(crate) fn new_at(s: &'a str, at: usize) -> StrCursor<'a> { StrCursor { s, at } } - pub fn at_next_cp(mut self) -> Option> { + pub(crate) fn at_next_cp(mut self) -> Option> { match self.try_seek_right_cp() { true => Some(self), false => None, } } - pub fn next_cp(mut self) -> Option<(char, StrCursor<'a>)> { + pub(crate) fn next_cp(mut self) -> Option<(char, StrCursor<'a>)> { let cp = self.cp_after()?; self.seek_right(cp.len_utf8()); Some((cp, self)) @@ -770,11 +770,11 @@ mod strcursor { &self.s[0..self.at] } - pub fn slice_after(&self) -> &'a str { + pub(crate) fn slice_after(&self) -> &'a str { &self.s[self.at..] } - pub fn slice_between(&self, until: StrCursor<'a>) -> Option<&'a str> { + pub(crate) fn slice_between(&self, until: StrCursor<'a>) -> Option<&'a str> { if !str_eq_literal(self.s, until.s) { None } else { diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index a9ba7334d93..30e1c8d2622 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -16,6 +16,7 @@ #![feature(proc_macro_quote)] #![feature(rustdoc_internals)] #![feature(try_blocks)] +#![warn(unreachable_pub)] // tidy-alphabetical-end extern crate proc_macro; diff --git a/compiler/rustc_builtin_macros/src/util.rs b/compiler/rustc_builtin_macros/src/util.rs index 73cc8ff547d..0bcd5aef28b 100644 --- a/compiler/rustc_builtin_macros/src/util.rs +++ b/compiler/rustc_builtin_macros/src/util.rs @@ -17,7 +17,6 @@ pub(crate) fn check_builtin_macro_attribute(ecx: &ExtCtxt<'_>, meta_item: &MetaI // All the built-in macro attributes are "words" at the moment. let template = AttributeTemplate { word: true, ..Default::default() }; validate_attr::check_builtin_meta_item( - &ecx.ecfg.features, &ecx.sess.psess, meta_item, AttrStyle::Outer, diff --git a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs index e603ac566f4..ccbd5a78485 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs @@ -6,8 +6,7 @@ extern_types, naked_functions, thread_local, - repr_simd, - raw_ref_op + repr_simd )] #![no_core] #![allow(dead_code, non_camel_case_types, internal_features)] diff --git a/compiler/rustc_codegen_cranelift/src/analyze.rs b/compiler/rustc_codegen_cranelift/src/analyze.rs index c5762638a6b..72380f50385 100644 --- a/compiler/rustc_codegen_cranelift/src/analyze.rs +++ b/compiler/rustc_codegen_cranelift/src/analyze.rs @@ -25,7 +25,7 @@ pub(crate) fn analyze(fx: &FunctionCx<'_, '_, '_>) -> IndexVec { for stmt in bb.statements.iter() { match &stmt.kind { Assign(place_and_rval) => match &place_and_rval.1 { - Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => { + Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) => { flag_map[place.local] = SsaKind::NotSsa; } _ => {} diff --git a/compiler/rustc_codegen_cranelift/src/archive.rs b/compiler/rustc_codegen_cranelift/src/archive.rs index 5eedab4f2cb..c7725e49c94 100644 --- a/compiler/rustc_codegen_cranelift/src/archive.rs +++ b/compiler/rustc_codegen_cranelift/src/archive.rs @@ -1,13 +1,6 @@ -use std::borrow::Borrow; -use std::fs; -use std::path::Path; - -use ar_archive_writer::{COFFShortExport, MachineTypes}; use rustc_codegen_ssa::back::archive::{ - create_mingw_dll_import_lib, ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, - DEFAULT_OBJECT_READER, + ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, DEFAULT_OBJECT_READER, }; -use rustc_codegen_ssa::common::is_mingw_gnu_toolchain; use rustc_session::Session; pub(crate) struct ArArchiveBuilderBuilder; @@ -16,78 +9,4 @@ 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, - import_name_and_ordinal_vector: Vec<(String, Option)>, - output_path: &Path, - ) { - if is_mingw_gnu_toolchain(&sess.target) { - // The binutils linker used on -windows-gnu targets cannot read the import - // libraries generated by LLVM: in our attempts, the linker produced an .EXE - // that loaded but crashed with an AV upon calling one of the imported - // functions. Therefore, use binutils to create the import library instead, - // by writing a .DEF file to the temp dir and calling binutils's dlltool. - create_mingw_dll_import_lib( - sess, - lib_name, - import_name_and_ordinal_vector, - output_path, - ); - } else { - let mut file = - match fs::OpenOptions::new().write(true).create_new(true).open(&output_path) { - Ok(file) => file, - Err(error) => { - sess.dcx().fatal(format!( - "failed to create import library file `{path}`: {error}", - path = output_path.display(), - )); - } - }; - - let machine = match sess.target.arch.borrow() { - "x86" => MachineTypes::I386, - "x86_64" => MachineTypes::AMD64, - "arm" => MachineTypes::ARMNT, - "aarch64" => MachineTypes::ARM64, - _ => { - sess.dcx().fatal(format!( - "unsupported target architecture `{arch}`", - arch = sess.target.arch, - )); - } - }; - - let exports = import_name_and_ordinal_vector - .iter() - .map(|(name, ordinal)| COFFShortExport { - name: name.to_string(), - ext_name: None, - symbol_name: None, - alias_target: None, - ordinal: ordinal.unwrap_or(0), - noname: ordinal.is_some(), - data: false, - private: false, - constant: false, - }) - .collect::>(); - - if let Err(error) = ar_archive_writer::write_import_library( - &mut file, - lib_name, - &exports, - machine, - !sess.target.is_like_msvc, - ) { - sess.dcx().fatal(format!( - "failed to create import library `{path}`: `{error}`", - path = output_path.display(), - )); - } - } - } } diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 9bc7b57c537..f1d885bf1bc 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -595,7 +595,7 @@ fn codegen_stmt<'tcx>( let val = cplace.to_cvalue(fx); lval.write_cvalue(fx, val) } - Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => { + Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) => { let place = codegen_place(fx, place); let ref_ = place.place_ref(fx, lval.layout()); lval.write_cvalue(fx, ref_); diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index a1b29a42225..b9000a3874f 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -69,7 +69,7 @@ fn clif_type_from_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option types::F64, FloatTy::F128 => unimplemented!("f16_f128"), }, - ty::FnPtr(_) => pointer_ty(tcx), + ty::FnPtr(..) => pointer_ty(tcx), ty::RawPtr(pointee_ty, _) | ty::Ref(_, pointee_ty, _) => { if has_ptr_meta(tcx, *pointee_ty) { return None; diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index ca910dccb0d..604a88393fd 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -191,6 +191,14 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( }) .try_into() .unwrap(), + _ if idx_ty.is_simd() + && matches!( + idx_ty.simd_size_and_type(fx.tcx).1.kind(), + ty::Uint(ty::UintTy::U32) + ) => + { + idx_ty.simd_size_and_type(fx.tcx).0.try_into().unwrap() + } _ => { fx.tcx.dcx().span_err( span, @@ -213,6 +221,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let total_len = lane_count * 2; + // FIXME: this is a terrible abstraction-breaking hack. + // Find a way to reuse `immediate_const_vector` from `codegen_ssa` instead. let indexes = { use rustc_middle::mir::interpret::*; let idx_const = match &idx.node { diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 21930fa2ddb..f737af25b62 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -12,7 +12,6 @@ #![warn(unused_lifetimes)] // tidy-alphabetical-end -extern crate ar_archive_writer; extern crate jobserver; #[macro_use] extern crate rustc_middle; diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs index 8eb2095e523..fd77502224e 100644 --- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs +++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs @@ -874,7 +874,7 @@ pub(crate) fn assert_assignable<'tcx>( (ty::Ref(_, a, _), ty::RawPtr(b, _)) | (ty::RawPtr(a, _), ty::Ref(_, b, _)) => { assert_assignable(fx, *a, *b, limit - 1); } - (ty::FnPtr(_), ty::FnPtr(_)) => { + (ty::FnPtr(..), ty::FnPtr(..)) => { let from_sig = fx.tcx.normalize_erasing_late_bound_regions( ParamEnv::reveal_all(), from_ty.fn_sig(fx.tcx), diff --git a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs index 9f096e90220..dcfa34cb729 100644 --- a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs +++ b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs @@ -2,7 +2,7 @@ #![feature( no_core, unboxed_closures, start, lang_items, never_type, linkage, - extern_types, thread_local, raw_ref_op + extern_types, thread_local )] #![no_core] #![allow(dead_code, internal_features, non_camel_case_types)] diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index 47b378cc1cd..6ba678e2e7c 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -1923,15 +1923,11 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { v2: RValue<'gcc>, mask: RValue<'gcc>, ) -> RValue<'gcc> { - let struct_type = mask.get_type().is_struct().expect("mask should be of struct type"); - // TODO(antoyo): use a recursive unqualified() here. let vector_type = v1.get_type().unqualified().dyncast_vector().expect("vector type"); let element_type = vector_type.get_element_type(); let vec_num_units = vector_type.get_num_units(); - let mask_num_units = struct_type.get_field_count(); - let mut vector_elements = vec![]; let mask_element_type = if element_type.is_integral() { element_type } else { @@ -1942,19 +1938,39 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { #[cfg(not(feature = "master"))] self.int_type }; - for i in 0..mask_num_units { - let field = struct_type.get_field(i as i32); - vector_elements.push(self.context.new_cast( - self.location, - mask.access_field(self.location, field).to_rvalue(), - mask_element_type, - )); - } + + let mut mask_elements = if let Some(vector_type) = mask.get_type().dyncast_vector() { + let mask_num_units = vector_type.get_num_units(); + let mut mask_elements = vec![]; + for i in 0..mask_num_units { + let index = self.context.new_rvalue_from_long(self.cx.type_u32(), i as _); + mask_elements.push(self.context.new_cast( + self.location, + self.extract_element(mask, index).to_rvalue(), + mask_element_type, + )); + } + mask_elements + } else { + let struct_type = mask.get_type().is_struct().expect("mask should be of struct type"); + let mask_num_units = struct_type.get_field_count(); + let mut mask_elements = vec![]; + for i in 0..mask_num_units { + let field = struct_type.get_field(i as i32); + mask_elements.push(self.context.new_cast( + self.location, + mask.access_field(self.location, field).to_rvalue(), + mask_element_type, + )); + } + mask_elements + }; + let mask_num_units = mask_elements.len(); // NOTE: the mask needs to be the same length as the input vectors, so add the missing // elements in the mask if needed. for _ in mask_num_units..vec_num_units { - vector_elements.push(self.context.new_rvalue_zero(mask_element_type)); + mask_elements.push(self.context.new_rvalue_zero(mask_element_type)); } let result_type = self.context.new_vector_type(element_type, mask_num_units as u64); @@ -1998,7 +2014,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let new_mask_num_units = std::cmp::max(mask_num_units, vec_num_units); let mask_type = self.context.new_vector_type(mask_element_type, new_mask_num_units as u64); - let mask = self.context.new_rvalue_from_vector(self.location, mask_type, &vector_elements); + let mask = self.context.new_rvalue_from_vector(self.location, mask_type, &mask_elements); let result = self.context.new_rvalue_vector_perm(self.location, v1, v2, mask); if vec_num_units != mask_num_units { diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs index 8da1df3be15..96a833ccaf2 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs @@ -353,19 +353,24 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( } if name == sym::simd_shuffle { - // Make sure this is actually an array, since typeck only checks the length-suffixed + // Make sure this is actually an array or SIMD vector, since typeck only checks the length-suffixed // version of this intrinsic. - let n: u64 = match *args[2].layout.ty.kind() { + let idx_ty = args[2].layout.ty; + let n: u64 = match idx_ty.kind() { ty::Array(ty, len) if matches!(*ty.kind(), ty::Uint(ty::UintTy::U32)) => { len.try_eval_target_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else( || span_bug!(span, "could not evaluate shuffle index array length"), ) } - _ => return_error!(InvalidMonomorphization::SimdShuffle { - span, - name, - ty: args[2].layout.ty - }), + _ if idx_ty.is_simd() + && matches!( + idx_ty.simd_size_and_type(bx.cx.tcx).1.kind(), + ty::Uint(ty::UintTy::U32) + ) => + { + idx_ty.simd_size_and_type(bx.cx.tcx).0 + } + _ => return_error!(InvalidMonomorphization::SimdShuffle { span, name, ty: idx_ty }), }; require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs index d85ed4f12ff..b7b1be5369c 100644 --- a/compiler/rustc_codegen_gcc/src/type_of.rs +++ b/compiler/rustc_codegen_gcc/src/type_of.rs @@ -213,9 +213,8 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { // NOTE: we cannot remove this match like in the LLVM codegen because the call // to fn_ptr_backend_type handle the on-stack attribute. // TODO(antoyo): find a less hackish way to hande the on-stack attribute. - ty::FnPtr(sig) => { - cx.fn_ptr_backend_type(cx.fn_abi_of_fn_ptr(sig, ty::List::empty())) - } + ty::FnPtr(sig_tys, hdr) => cx + .fn_ptr_backend_type(cx.fn_abi_of_fn_ptr(sig_tys.with(hdr), ty::List::empty())), _ => self.scalar_gcc_type_at(cx, scalar, Size::ZERO), }; cx.scalar_types.borrow_mut().insert(self.ty, ty); diff --git a/compiler/rustc_codegen_gcc/tests/run/asm.rs b/compiler/rustc_codegen_gcc/tests/run/asm.rs index 56f2aac3d0a..4e05d026868 100644 --- a/compiler/rustc_codegen_gcc/tests/run/asm.rs +++ b/compiler/rustc_codegen_gcc/tests/run/asm.rs @@ -3,12 +3,10 @@ // Run-time: // status: 0 -#![feature(asm_const)] - -#[cfg(target_arch="x86_64")] +#[cfg(target_arch = "x86_64")] use std::arch::{asm, global_asm}; -#[cfg(target_arch="x86_64")] +#[cfg(target_arch = "x86_64")] global_asm!( " .global add_asm @@ -22,7 +20,7 @@ extern "C" { fn add_asm(a: i64, b: i64) -> i64; } -#[cfg(target_arch="x86_64")] +#[cfg(target_arch = "x86_64")] pub unsafe fn mem_cpy(dst: *mut u8, src: *const u8, len: usize) { asm!( "rep movsb", @@ -33,7 +31,7 @@ pub unsafe fn mem_cpy(dst: *mut u8, src: *const u8, len: usize) { ); } -#[cfg(target_arch="x86_64")] +#[cfg(target_arch = "x86_64")] fn asm() { unsafe { asm!("nop"); @@ -178,9 +176,8 @@ fn asm() { assert_eq!(array1, array2); } -#[cfg(not(target_arch="x86_64"))] -fn asm() { -} +#[cfg(not(target_arch = "x86_64"))] +fn asm() {} fn main() { asm(); diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index dad4722d620..a93baf88413 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -12,7 +12,7 @@ bitflags = "2.4.1" itertools = "0.12" libc = "0.2" measureme = "11" -object = { version = "0.36.2", default-features = false, features = ["std", "read"] } +object = { version = "0.36.3", default-features = false, features = ["std", "read"] } rustc-demangle = "0.1.21" rustc_ast = { path = "../rustc_ast" } rustc_attr = { path = "../rustc_attr" } diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl index 267da9325c3..df2198df14b 100644 --- a/compiler/rustc_codegen_llvm/messages.ftl +++ b/compiler/rustc_codegen_llvm/messages.ftl @@ -5,9 +5,6 @@ codegen_llvm_dynamic_linking_with_lto = .note = only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO -codegen_llvm_error_creating_import_library = - Error creating import library for {$lib_name}: {$error} - codegen_llvm_fixed_x18_invalid_arch = the `-Zfixed-x18` flag is not supported on the `{$arch}` architecture codegen_llvm_from_llvm_diag = {$message} diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index 5ff580e295a..dea574a53cd 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -6,13 +6,13 @@ use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue}; use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::MemFlags; use rustc_middle::ty::layout::LayoutOf; -pub use rustc_middle::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA}; +pub(crate) use rustc_middle::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA}; use rustc_middle::ty::Ty; use rustc_middle::{bug, ty}; use rustc_session::config; -pub use rustc_target::abi::call::*; +pub(crate) use rustc_target::abi::call::*; use rustc_target::abi::{self, HasDataLayout, Int, Size}; -pub use rustc_target::spec::abi::Abi; +pub(crate) use rustc_target::spec::abi::Abi; use rustc_target::spec::SanitizerSet; use smallvec::SmallVec; @@ -25,7 +25,7 @@ use crate::type_of::LayoutLlvmExt; use crate::value::Value; use crate::{attributes, llvm_util}; -pub trait ArgAttributesExt { +trait ArgAttributesExt { fn apply_attrs_to_llfn(&self, idx: AttributePlace, cx: &CodegenCx<'_, '_>, llfn: &Value); fn apply_attrs_to_callsite( &self, @@ -111,7 +111,7 @@ impl ArgAttributesExt for ArgAttributes { } } -pub trait LlvmType { +pub(crate) trait LlvmType { fn llvm_type<'ll>(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type; } @@ -171,7 +171,7 @@ impl LlvmType for CastTarget { } } -pub trait ArgAbiExt<'ll, 'tcx> { +trait ArgAbiExt<'ll, 'tcx> { fn memory_ty(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type; fn store( &self, @@ -307,7 +307,7 @@ impl<'ll, 'tcx> ArgAbiMethods<'tcx> for Builder<'_, 'll, 'tcx> { } } -pub trait FnAbiLlvmExt<'ll, 'tcx> { +pub(crate) trait FnAbiLlvmExt<'ll, 'tcx> { fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type; fn ptr_to_llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type; fn llvm_cconv(&self) -> llvm::CallConv; diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs index 8fb31082793..b4f3784a31a 100644 --- a/compiler/rustc_codegen_llvm/src/allocator.rs +++ b/compiler/rustc_codegen_llvm/src/allocator.rs @@ -149,7 +149,7 @@ fn create_wrapper_function( } llvm::LLVMRustSetVisibility(callee, llvm::Visibility::Hidden); - let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, c"entry".as_ptr().cast()); + let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, c"entry".as_ptr()); let llbuilder = llvm::LLVMCreateBuilderInContext(llcx); llvm::LLVMPositionBuilderAtEnd(llbuilder, llbb); diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index f931698c38f..1d91c3fb17d 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -913,8 +913,10 @@ fn llvm_asm_scalar_type<'ll>(cx: &CodegenCx<'ll, '_>, scalar: Scalar) -> &'ll Ty Primitive::Int(Integer::I16, _) => cx.type_i16(), Primitive::Int(Integer::I32, _) => cx.type_i32(), Primitive::Int(Integer::I64, _) => cx.type_i64(), + Primitive::Float(Float::F16) => cx.type_f16(), Primitive::Float(Float::F32) => cx.type_f32(), Primitive::Float(Float::F64) => cx.type_f64(), + Primitive::Float(Float::F128) => cx.type_f128(), // FIXME(erikdesjardins): handle non-default addrspace ptr sizes Primitive::Pointer(_) => cx.type_from_integer(dl.ptr_sized_integer()), _ => unreachable!(), @@ -948,7 +950,9 @@ fn llvm_fixup_input<'ll, 'tcx>( value } } - (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16), Abi::Scalar(s)) => { + (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16), Abi::Scalar(s)) + if s.primitive() != Primitive::Float(Float::F128) => + { let elem_ty = llvm_asm_scalar_type(bx.cx, s); let count = 16 / layout.size.bytes(); let vec_ty = bx.cx.type_vector(elem_ty, count); @@ -1090,7 +1094,9 @@ fn llvm_fixup_output<'ll, 'tcx>( value } } - (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16), Abi::Scalar(s)) => { + (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16), Abi::Scalar(s)) + if s.primitive() != Primitive::Float(Float::F128) => + { value = bx.extract_element(value, bx.const_i32(0)); if let Primitive::Pointer(_) = s.primitive() { value = bx.inttoptr(value, layout.llvm_type(bx.cx)); @@ -1222,7 +1228,9 @@ fn llvm_fixup_output_type<'ll, 'tcx>( layout.llvm_type(cx) } } - (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16), Abi::Scalar(s)) => { + (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16), Abi::Scalar(s)) + if s.primitive() != Primitive::Float(Float::F128) => + { let elem_ty = llvm_asm_scalar_type(cx, s); let count = 16 / layout.size.bytes(); cx.type_vector(elem_ty, count) diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index fde95104093..92a857c2adc 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -1,6 +1,6 @@ //! Set and unset common attributes on LLVM values. -pub use rustc_attr::{InlineAttr, InstructionSetAttr, OptimizeAttr}; +use rustc_attr::{InlineAttr, InstructionSetAttr, OptimizeAttr}; use rustc_codegen_ssa::traits::*; use rustc_hir::def_id::DefId; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, PatchableFunctionEntry}; @@ -17,13 +17,13 @@ use crate::llvm::{self, AllocKindFlags, Attribute, AttributeKind, AttributePlace use crate::value::Value; use crate::{attributes, llvm_util}; -pub fn apply_to_llfn(llfn: &Value, idx: AttributePlace, attrs: &[&Attribute]) { +pub(crate) fn apply_to_llfn(llfn: &Value, idx: AttributePlace, attrs: &[&Attribute]) { if !attrs.is_empty() { llvm::AddFunctionAttributes(llfn, idx, attrs); } } -pub fn apply_to_callsite(callsite: &Value, idx: AttributePlace, attrs: &[&Attribute]) { +pub(crate) fn apply_to_callsite(callsite: &Value, idx: AttributePlace, attrs: &[&Attribute]) { if !attrs.is_empty() { llvm::AddCallSiteAttributes(callsite, idx, attrs); } @@ -80,7 +80,7 @@ fn patchable_function_entry_attrs<'ll>( /// Get LLVM sanitize attributes. #[inline] -pub fn sanitize_attrs<'ll>( +pub(crate) fn sanitize_attrs<'ll>( cx: &CodegenCx<'ll, '_>, no_sanitize: SanitizerSet, ) -> SmallVec<[&'ll Attribute; 4]> { @@ -120,7 +120,7 @@ pub fn sanitize_attrs<'ll>( /// Tell LLVM to emit or not emit the information necessary to unwind the stack for the function. #[inline] -pub fn uwtable_attr(llcx: &llvm::Context, use_sync_unwind: Option) -> &Attribute { +pub(crate) fn uwtable_attr(llcx: &llvm::Context, use_sync_unwind: Option) -> &Attribute { // NOTE: We should determine if we even need async unwind tables, as they // take have more overhead and if we can use sync unwind tables we // probably should. @@ -128,7 +128,7 @@ pub fn uwtable_attr(llcx: &llvm::Context, use_sync_unwind: Option) -> &Att llvm::CreateUWTableAttr(llcx, async_unwind) } -pub fn frame_pointer_type_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> { +pub(crate) fn frame_pointer_type_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> { let mut fp = cx.sess().target.frame_pointer; let opts = &cx.sess().opts; // "mcount" function relies on stack pointer. @@ -280,19 +280,19 @@ fn backchain_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> { if found_positive { Some(llvm::CreateAttrString(cx.llcx, "backchain")) } else { None } } -pub fn target_cpu_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> &'ll Attribute { +pub(crate) fn target_cpu_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> &'ll Attribute { let target_cpu = llvm_util::target_cpu(cx.tcx.sess); llvm::CreateAttrStringValue(cx.llcx, "target-cpu", target_cpu) } -pub fn tune_cpu_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> { +pub(crate) fn tune_cpu_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> { llvm_util::tune_cpu(cx.tcx.sess) .map(|tune_cpu| llvm::CreateAttrStringValue(cx.llcx, "tune-cpu", tune_cpu)) } /// Get the `NonLazyBind` LLVM attribute, /// if the codegen options allow skipping the PLT. -pub fn non_lazy_bind_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> { +pub(crate) fn non_lazy_bind_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> { // Don't generate calls through PLT if it's not necessary if !cx.sess().needs_plt() { Some(AttributeKind::NonLazyBind.create_attr(cx.llcx)) @@ -327,7 +327,7 @@ fn create_alloc_family_attr(llcx: &llvm::Context) -> &llvm::Attribute { /// Helper for `FnAbi::apply_attrs_llfn`: /// Composite function which sets LLVM attributes for function depending on its AST (`#[attribute]`) /// attributes. -pub fn llfn_attrs_from_instance<'ll, 'tcx>( +pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty::Instance<'tcx>, @@ -521,13 +521,20 @@ pub fn llfn_attrs_from_instance<'ll, 'tcx>( let function_features = function_features .iter() - .flat_map(|feat| { - llvm_util::to_llvm_features(cx.tcx.sess, feat).into_iter().map(|f| format!("+{f}")) - }) + // Convert to LLVMFeatures and filter out unavailable ones + .flat_map(|feat| llvm_util::to_llvm_features(cx.tcx.sess, feat)) + // Convert LLVMFeatures & dependencies to +s + .flat_map(|feat| feat.into_iter().map(|f| format!("+{f}"))) .chain(codegen_fn_attrs.instruction_set.iter().map(|x| match x { InstructionSetAttr::ArmA32 => "-thumb-mode".to_string(), InstructionSetAttr::ArmT32 => "+thumb-mode".to_string(), })) + // HACK: LLVM versions 19+ do not have the FPMR feature and treat it as always enabled + // It only exists as a feature in LLVM 18, cannot be passed down for any other version + .chain(match &*cx.tcx.sess.target.arch { + "aarch64" if llvm_util::get_version().0 == 18 => vec!["+fpmr".to_string()], + _ => vec![], + }) .collect::>(); if cx.tcx.sess.target.is_like_wasm { diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs index a2ab19ac800..4f2c83634a8 100644 --- a/compiler/rustc_codegen_llvm/src/back/archive.rs +++ b/compiler/rustc_codegen_llvm/src/back/archive.rs @@ -5,17 +5,13 @@ use std::path::{Path, PathBuf}; use std::{io, mem, ptr, str}; use rustc_codegen_ssa::back::archive::{ - create_mingw_dll_import_lib, try_extract_macho_fat_archive, ArArchiveBuilder, - ArchiveBuildFailure, ArchiveBuilder, ArchiveBuilderBuilder, ObjectReader, UnknownArchiveKind, - DEFAULT_OBJECT_READER, + try_extract_macho_fat_archive, ArArchiveBuilder, ArchiveBuildFailure, ArchiveBuilder, + ArchiveBuilderBuilder, ObjectReader, UnknownArchiveKind, DEFAULT_OBJECT_READER, }; -use rustc_codegen_ssa::common; use rustc_session::Session; -use tracing::trace; -use crate::errors::ErrorCreatingImportLibrary; use crate::llvm::archive_ro::{ArchiveRO, Child}; -use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport}; +use crate::llvm::{self, ArchiveKind}; /// Helper for adding many files to an archive. #[must_use = "must call build() to finish building the archive"] @@ -44,18 +40,6 @@ fn is_relevant_child(c: &Child<'_>) -> bool { } } -/// Map machine type strings to values of LLVM's MachineTypes enum. -fn llvm_machine_type(cpu: &str) -> LLVMMachineType { - match cpu { - "x86_64" => LLVMMachineType::AMD64, - "x86" => LLVMMachineType::I386, - "aarch64" => LLVMMachineType::ARM64, - "arm64ec" => LLVMMachineType::ARM64EC, - "arm" => LLVMMachineType::ARM, - _ => panic!("unsupported cpu type {cpu}"), - } -} - impl<'a> ArchiveBuilder for LlvmArchiveBuilder<'a> { fn add_archive( &mut self, @@ -102,90 +86,20 @@ impl<'a> ArchiveBuilder for LlvmArchiveBuilder<'a> { } } -pub struct LlvmArchiveBuilderBuilder; +pub(crate) struct LlvmArchiveBuilderBuilder; impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder { fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box { - // FIXME use ArArchiveBuilder on most targets again once reading thin archives is - // implemented - if true { + // Keeping LlvmArchiveBuilder around in case of a regression caused by using + // ArArchiveBuilder. + // FIXME(#128955) remove a couple of months after #128936 gets merged in case + // no regression is found. + if false { Box::new(LlvmArchiveBuilder { sess, additions: Vec::new() }) } else { Box::new(ArArchiveBuilder::new(sess, &LLVM_OBJECT_READER)) } } - - fn create_dll_import_lib( - &self, - sess: &Session, - lib_name: &str, - import_name_and_ordinal_vector: Vec<(String, Option)>, - output_path: &Path, - ) { - if common::is_mingw_gnu_toolchain(&sess.target) { - // The binutils linker used on -windows-gnu targets cannot read the import - // libraries generated by LLVM: in our attempts, the linker produced an .EXE - // that loaded but crashed with an AV upon calling one of the imported - // functions. Therefore, use binutils to create the import library instead, - // by writing a .DEF file to the temp dir and calling binutils's dlltool. - create_mingw_dll_import_lib( - sess, - lib_name, - import_name_and_ordinal_vector, - output_path, - ); - } else { - // we've checked for \0 characters in the library name already - let dll_name_z = CString::new(lib_name).unwrap(); - - let output_path_z = rustc_fs_util::path_to_c_string(&output_path); - - trace!("invoking LLVMRustWriteImportLibrary"); - trace!(" dll_name {:#?}", dll_name_z); - trace!(" output_path {}", output_path.display()); - trace!( - " import names: {}", - import_name_and_ordinal_vector - .iter() - .map(|(name, _ordinal)| name.clone()) - .collect::>() - .join(", "), - ); - - // All import names are Rust identifiers and therefore cannot contain \0 characters. - // FIXME: when support for #[link_name] is implemented, ensure that the import names - // still don't contain any \0 characters. Also need to check that the names don't - // contain substrings like " @" or "NONAME" that are keywords or otherwise reserved - // in definition files. - let cstring_import_name_and_ordinal_vector: Vec<(CString, Option)> = - import_name_and_ordinal_vector - .into_iter() - .map(|(name, ordinal)| (CString::new(name).unwrap(), ordinal)) - .collect(); - - let ffi_exports: Vec = cstring_import_name_and_ordinal_vector - .iter() - .map(|(name_z, ordinal)| LLVMRustCOFFShortExport::new(name_z.as_ptr(), *ordinal)) - .collect(); - let result = unsafe { - crate::llvm::LLVMRustWriteImportLibrary( - dll_name_z.as_ptr(), - output_path_z.as_ptr(), - ffi_exports.as_ptr(), - ffi_exports.len(), - llvm_machine_type(&sess.target.arch) as u16, - !sess.target.is_like_msvc, - ) - }; - - if result == crate::llvm::LLVMRustResult::Failure { - sess.dcx().emit_fatal(ErrorCreatingImportLibrary { - lib_name, - error: llvm::last_error().unwrap_or("unknown LLVM error".to_string()), - }); - } - } - } } // The object crate doesn't know how to get symbols for LLVM bitcode and COFF bigobj files. @@ -198,25 +112,11 @@ static LLVM_OBJECT_READER: ObjectReader = ObjectReader { get_xcoff_member_alignment: DEFAULT_OBJECT_READER.get_xcoff_member_alignment, }; -fn should_use_llvm_reader(buf: &[u8]) -> bool { - let is_bitcode = unsafe { llvm::LLVMRustIsBitcode(buf.as_ptr(), buf.len()) }; - - // COFF bigobj file, msvc LTO file or import library. See - // https://github.com/llvm/llvm-project/blob/453f27bc9/llvm/lib/BinaryFormat/Magic.cpp#L38-L51 - let is_unsupported_windows_obj_file = buf.get(0..4) == Some(b"\0\0\xFF\xFF"); - - is_bitcode || is_unsupported_windows_obj_file -} - #[deny(unsafe_op_in_unsafe_fn)] fn get_llvm_object_symbols( buf: &[u8], f: &mut dyn FnMut(&[u8]) -> io::Result<()>, ) -> io::Result { - if !should_use_llvm_reader(buf) { - return (DEFAULT_OBJECT_READER.get_symbols)(buf, f); - } - let mut state = Box::new(f); let err = unsafe { @@ -253,18 +153,10 @@ fn get_llvm_object_symbols( } fn llvm_is_64_bit_object_file(buf: &[u8]) -> bool { - if !should_use_llvm_reader(buf) { - return (DEFAULT_OBJECT_READER.is_64_bit_object_file)(buf); - } - unsafe { llvm::LLVMRustIs64BitSymbolicFile(buf.as_ptr(), buf.len()) } } fn llvm_is_ec_object_file(buf: &[u8]) -> bool { - if !should_use_llvm_reader(buf) { - return (DEFAULT_OBJECT_READER.is_ec_object_file)(buf); - } - unsafe { llvm::LLVMRustIsECObject(buf.as_ptr(), buf.len()) } } diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index f68155f523a..aa6842c75ce 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -33,9 +33,9 @@ use crate::{LlvmCodegenBackend, ModuleLlvm}; /// We keep track of the computed LTO cache keys from the previous /// session to determine which CGUs we can reuse. -pub const THIN_LTO_KEYS_INCR_COMP_FILE_NAME: &str = "thin-lto-past-keys.bin"; +const THIN_LTO_KEYS_INCR_COMP_FILE_NAME: &str = "thin-lto-past-keys.bin"; -pub fn crate_type_allows_lto(crate_type: CrateType) -> bool { +fn crate_type_allows_lto(crate_type: CrateType) -> bool { match crate_type { CrateType::Executable | CrateType::Dylib @@ -616,7 +616,7 @@ pub(crate) fn run_pass_manager( llvm::LLVMRustAddModuleFlagU32( module.module_llvm.llmod(), llvm::LLVMModFlagBehavior::Error, - c"LTOPostLink".as_ptr().cast(), + c"LTOPostLink".as_ptr(), 1, ); } @@ -710,7 +710,7 @@ impl Drop for ThinBuffer { } } -pub unsafe fn optimize_thin_module( +pub(crate) unsafe fn optimize_thin_module( thin_module: ThinModule, cgcx: &CodegenContext, ) -> Result, FatalError> { @@ -806,7 +806,7 @@ pub unsafe fn optimize_thin_module( /// Maps LLVM module identifiers to their corresponding LLVM LTO cache keys #[derive(Debug, Default)] -pub struct ThinLTOKeysMap { +struct ThinLTOKeysMap { // key = llvm name of importing module, value = LLVM cache key keys: BTreeMap, } @@ -863,7 +863,7 @@ fn module_name_to_str(c_str: &CStr) -> &str { }) } -pub fn parse_module<'a>( +pub(crate) fn parse_module<'a>( cx: &'a llvm::Context, name: &CStr, data: &[u8], diff --git a/compiler/rustc_codegen_llvm/src/back/profiling.rs b/compiler/rustc_codegen_llvm/src/back/profiling.rs index 26fb4a96f84..79794775b7b 100644 --- a/compiler/rustc_codegen_llvm/src/back/profiling.rs +++ b/compiler/rustc_codegen_llvm/src/back/profiling.rs @@ -21,14 +21,14 @@ fn llvm_args_to_string_id(profiler: &SelfProfiler, pass_name: &str, ir_name: &st EventId::from_label(profiler.alloc_string(components.as_slice())) } -pub struct LlvmSelfProfiler<'a> { +pub(crate) struct LlvmSelfProfiler<'a> { profiler: Arc, stack: Vec>, llvm_pass_event_kind: StringId, } impl<'a> LlvmSelfProfiler<'a> { - pub fn new(profiler: Arc) -> Self { + pub(crate) fn new(profiler: Arc) -> Self { let llvm_pass_event_kind = profiler.alloc_string("LLVM Pass"); Self { profiler, stack: Vec::default(), llvm_pass_event_kind } } @@ -43,7 +43,7 @@ impl<'a> LlvmSelfProfiler<'a> { } } -pub unsafe extern "C" fn selfprofile_before_pass_callback( +pub(crate) unsafe extern "C" fn selfprofile_before_pass_callback( llvm_self_profiler: *mut c_void, pass_name: *const c_char, ir_name: *const c_char, @@ -56,7 +56,7 @@ pub unsafe extern "C" fn selfprofile_before_pass_callback( } } -pub unsafe extern "C" fn selfprofile_after_pass_callback(llvm_self_profiler: *mut c_void) { +pub(crate) unsafe extern "C" fn selfprofile_after_pass_callback(llvm_self_profiler: *mut c_void) { let llvm_self_profiler = unsafe { &mut *(llvm_self_profiler as *mut LlvmSelfProfiler<'_>) }; llvm_self_profiler.after_pass_callback(); } diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index a1f2433ab6f..adf7e933f43 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -43,14 +43,14 @@ use crate::llvm::{self, DiagnosticInfo, PassManager}; use crate::type_::Type; use crate::{base, common, llvm_util, LlvmCodegenBackend, ModuleLlvm}; -pub fn llvm_err<'a>(dcx: DiagCtxtHandle<'_>, err: LlvmError<'a>) -> FatalError { +pub(crate) fn llvm_err<'a>(dcx: DiagCtxtHandle<'_>, err: LlvmError<'a>) -> FatalError { match llvm::last_error() { Some(llvm_err) => dcx.emit_almost_fatal(WithLlvmError(err, llvm_err)), None => dcx.emit_almost_fatal(err), } } -pub fn write_output_file<'ll>( +fn write_output_file<'ll>( dcx: DiagCtxtHandle<'_>, target: &'ll llvm::TargetMachine, pm: &llvm::PassManager<'ll>, @@ -95,7 +95,7 @@ pub fn write_output_file<'ll>( } } -pub fn create_informational_target_machine( +pub(crate) fn create_informational_target_machine( sess: &Session, only_base_features: bool, ) -> OwnedTargetMachine { @@ -107,7 +107,7 @@ pub fn create_informational_target_machine( .unwrap_or_else(|err| llvm_err(sess.dcx(), err).raise()) } -pub fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> OwnedTargetMachine { +pub(crate) fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> OwnedTargetMachine { let split_dwarf_file = if tcx.sess.target_can_use_split_dwarf() { tcx.output_filenames(()).split_dwarf_path( tcx.sess.split_debuginfo(), @@ -130,9 +130,7 @@ pub fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> OwnedTargetMach .unwrap_or_else(|err| llvm_err(tcx.dcx(), err).raise()) } -pub fn to_llvm_opt_settings( - cfg: config::OptLevel, -) -> (llvm::CodeGenOptLevel, llvm::CodeGenOptSize) { +fn to_llvm_opt_settings(cfg: config::OptLevel) -> (llvm::CodeGenOptLevel, llvm::CodeGenOptSize) { use self::config::OptLevel::*; match cfg { No => (llvm::CodeGenOptLevel::None, llvm::CodeGenOptSizeNone), @@ -179,7 +177,7 @@ pub(crate) fn to_llvm_code_model(code_model: Option) -> llvm::CodeMod } } -pub fn target_machine_factory( +pub(crate) fn target_machine_factory( sess: &Session, optlvl: config::OptLevel, target_features: &[String], @@ -320,7 +318,7 @@ pub(crate) fn save_temp_bitcode( } /// In what context is a dignostic handler being attached to a codegen unit? -pub enum CodegenDiagnosticsStage { +pub(crate) enum CodegenDiagnosticsStage { /// Prelink optimization stage. Opt, /// LTO/ThinLTO postlink optimization stage. @@ -329,14 +327,14 @@ pub enum CodegenDiagnosticsStage { Codegen, } -pub struct DiagnosticHandlers<'a> { +pub(crate) struct DiagnosticHandlers<'a> { data: *mut (&'a CodegenContext, DiagCtxtHandle<'a>), llcx: &'a llvm::Context, old_handler: Option<&'a llvm::DiagnosticHandler>, } impl<'a> DiagnosticHandlers<'a> { - pub fn new( + pub(crate) fn new( cgcx: &'a CodegenContext, dcx: DiagCtxtHandle<'a>, llcx: &'a llvm::Context, @@ -1031,7 +1029,7 @@ unsafe fn embed_bitcode( let llglobal = llvm::LLVMAddGlobal( llmod, common::val_ty(llconst), - c"rustc.embedded.module".as_ptr().cast(), + c"rustc.embedded.module".as_ptr(), ); llvm::LLVMSetInitializer(llglobal, llconst); @@ -1044,7 +1042,7 @@ unsafe fn embed_bitcode( let llglobal = llvm::LLVMAddGlobal( llmod, common::val_ty(llconst), - c"rustc.embedded.cmdline".as_ptr().cast(), + c"rustc.embedded.cmdline".as_ptr(), ); llvm::LLVMSetInitializer(llglobal, llconst); let section = if is_apple { @@ -1054,7 +1052,7 @@ unsafe fn embed_bitcode( } else { c".llvmcmd" }; - llvm::LLVMSetSection(llglobal, section.as_ptr().cast()); + llvm::LLVMSetSection(llglobal, section.as_ptr()); llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage); } else { // We need custom section flags, so emit module-level inline assembly. @@ -1107,7 +1105,7 @@ fn create_msvc_imps( .collect::>(); for (imp_name, val) in globals { - let imp = llvm::LLVMAddGlobal(llmod, ptr_ty, imp_name.as_ptr().cast()); + let imp = llvm::LLVMAddGlobal(llmod, ptr_ty, imp_name.as_ptr()); llvm::LLVMSetInitializer(imp, val); llvm::LLVMRustSetLinkage(imp, llvm::Linkage::ExternalLinkage); } diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs index e8236b45c89..0ba8d82406a 100644 --- a/compiler/rustc_codegen_llvm/src/base.rs +++ b/compiler/rustc_codegen_llvm/src/base.rs @@ -32,7 +32,7 @@ use crate::context::CodegenCx; use crate::value::Value; use crate::{attributes, llvm}; -pub struct ValueIter<'ll> { +pub(crate) struct ValueIter<'ll> { cur: Option<&'ll Value>, step: unsafe extern "C" fn(&'ll Value) -> Option<&'ll Value>, } @@ -49,11 +49,14 @@ impl<'ll> Iterator for ValueIter<'ll> { } } -pub fn iter_globals(llmod: &llvm::Module) -> ValueIter<'_> { +pub(crate) fn iter_globals(llmod: &llvm::Module) -> ValueIter<'_> { unsafe { ValueIter { cur: llvm::LLVMGetFirstGlobal(llmod), step: llvm::LLVMGetNextGlobal } } } -pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol) -> (ModuleCodegen, u64) { +pub(crate) fn compile_codegen_unit( + tcx: TyCtxt<'_>, + cgu_name: Symbol, +) -> (ModuleCodegen, u64) { let start_time = Instant::now(); let dep_node = tcx.codegen_unit(cgu_name).codegen_dep_node(tcx); @@ -140,7 +143,7 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol) -> (ModuleCodegen (module, cost) } -pub fn set_link_section(llval: &Value, attrs: &CodegenFnAttrs) { +pub(crate) fn set_link_section(llval: &Value, attrs: &CodegenFnAttrs) { let Some(sect) = attrs.link_section else { return }; unsafe { let buf = SmallCStr::new(sect.as_str()); @@ -148,7 +151,7 @@ pub fn set_link_section(llval: &Value, attrs: &CodegenFnAttrs) { } } -pub fn linkage_to_llvm(linkage: Linkage) -> llvm::Linkage { +pub(crate) fn linkage_to_llvm(linkage: Linkage) -> llvm::Linkage { match linkage { Linkage::External => llvm::Linkage::ExternalLinkage, Linkage::AvailableExternally => llvm::Linkage::AvailableExternallyLinkage, @@ -164,7 +167,7 @@ pub fn linkage_to_llvm(linkage: Linkage) -> llvm::Linkage { } } -pub fn visibility_to_llvm(linkage: Visibility) -> llvm::Visibility { +pub(crate) fn visibility_to_llvm(linkage: Visibility) -> llvm::Visibility { match linkage { Visibility::Default => llvm::Visibility::Default, Visibility::Hidden => llvm::Visibility::Hidden, diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index cc081f29e12..40783825cae 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -36,7 +36,7 @@ use crate::{attributes, llvm_util}; // All Builders must have an llfn associated with them #[must_use] -pub struct Builder<'a, 'll, 'tcx> { +pub(crate) struct Builder<'a, 'll, 'tcx> { pub llbuilder: &'ll mut llvm::Builder<'ll>, pub cx: &'a CodegenCx<'ll, 'tcx>, } @@ -1343,7 +1343,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { Builder { llbuilder, cx } } - pub fn llfn(&self) -> &'ll Value { + pub(crate) fn llfn(&self) -> &'ll Value { unsafe { llvm::LLVMGetBasicBlockParent(self.llbb()) } } @@ -1375,7 +1375,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { } } - pub fn set_unpredictable(&mut self, inst: &'ll Value) { + pub(crate) fn set_unpredictable(&mut self, inst: &'ll Value) { unsafe { llvm::LLVMSetMetadata( inst, @@ -1385,15 +1385,15 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { } } - pub fn minnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { + pub(crate) fn minnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { unsafe { llvm::LLVMRustBuildMinNum(self.llbuilder, lhs, rhs) } } - pub fn maxnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { + pub(crate) fn maxnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { unsafe { llvm::LLVMRustBuildMaxNum(self.llbuilder, lhs, rhs) } } - pub fn insert_element( + pub(crate) fn insert_element( &mut self, vec: &'ll Value, elt: &'ll Value, @@ -1402,7 +1402,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { unsafe { llvm::LLVMBuildInsertElement(self.llbuilder, vec, elt, idx, UNNAMED) } } - pub fn shuffle_vector( + pub(crate) fn shuffle_vector( &mut self, v1: &'ll Value, v2: &'ll Value, @@ -1411,65 +1411,77 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { unsafe { llvm::LLVMBuildShuffleVector(self.llbuilder, v1, v2, mask, UNNAMED) } } - pub fn vector_reduce_fadd(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value { + pub(crate) fn vector_reduce_fadd(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value { unsafe { llvm::LLVMRustBuildVectorReduceFAdd(self.llbuilder, acc, src) } } - pub fn vector_reduce_fmul(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value { + pub(crate) fn vector_reduce_fmul(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value { unsafe { llvm::LLVMRustBuildVectorReduceFMul(self.llbuilder, acc, src) } } - pub fn vector_reduce_fadd_reassoc(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value { + pub(crate) fn vector_reduce_fadd_reassoc( + &mut self, + acc: &'ll Value, + src: &'ll Value, + ) -> &'ll Value { unsafe { let instr = llvm::LLVMRustBuildVectorReduceFAdd(self.llbuilder, acc, src); llvm::LLVMRustSetAllowReassoc(instr); instr } } - pub fn vector_reduce_fmul_reassoc(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value { + pub(crate) fn vector_reduce_fmul_reassoc( + &mut self, + acc: &'ll Value, + src: &'ll Value, + ) -> &'ll Value { unsafe { let instr = llvm::LLVMRustBuildVectorReduceFMul(self.llbuilder, acc, src); llvm::LLVMRustSetAllowReassoc(instr); instr } } - pub fn vector_reduce_add(&mut self, src: &'ll Value) -> &'ll Value { + pub(crate) fn vector_reduce_add(&mut self, src: &'ll Value) -> &'ll Value { unsafe { llvm::LLVMRustBuildVectorReduceAdd(self.llbuilder, src) } } - pub fn vector_reduce_mul(&mut self, src: &'ll Value) -> &'ll Value { + pub(crate) fn vector_reduce_mul(&mut self, src: &'ll Value) -> &'ll Value { unsafe { llvm::LLVMRustBuildVectorReduceMul(self.llbuilder, src) } } - pub fn vector_reduce_and(&mut self, src: &'ll Value) -> &'ll Value { + pub(crate) fn vector_reduce_and(&mut self, src: &'ll Value) -> &'ll Value { unsafe { llvm::LLVMRustBuildVectorReduceAnd(self.llbuilder, src) } } - pub fn vector_reduce_or(&mut self, src: &'ll Value) -> &'ll Value { + pub(crate) fn vector_reduce_or(&mut self, src: &'ll Value) -> &'ll Value { unsafe { llvm::LLVMRustBuildVectorReduceOr(self.llbuilder, src) } } - pub fn vector_reduce_xor(&mut self, src: &'ll Value) -> &'ll Value { + pub(crate) fn vector_reduce_xor(&mut self, src: &'ll Value) -> &'ll Value { unsafe { llvm::LLVMRustBuildVectorReduceXor(self.llbuilder, src) } } - pub fn vector_reduce_fmin(&mut self, src: &'ll Value) -> &'ll Value { + pub(crate) fn vector_reduce_fmin(&mut self, src: &'ll Value) -> &'ll Value { unsafe { llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ false) } } - pub fn vector_reduce_fmax(&mut self, src: &'ll Value) -> &'ll Value { + pub(crate) fn vector_reduce_fmax(&mut self, src: &'ll Value) -> &'ll Value { unsafe { llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ false) } } - pub fn vector_reduce_min(&mut self, src: &'ll Value, is_signed: bool) -> &'ll Value { + pub(crate) fn vector_reduce_min(&mut self, src: &'ll Value, is_signed: bool) -> &'ll Value { unsafe { llvm::LLVMRustBuildVectorReduceMin(self.llbuilder, src, is_signed) } } - pub fn vector_reduce_max(&mut self, src: &'ll Value, is_signed: bool) -> &'ll Value { + pub(crate) fn vector_reduce_max(&mut self, src: &'ll Value, is_signed: bool) -> &'ll Value { unsafe { llvm::LLVMRustBuildVectorReduceMax(self.llbuilder, src, is_signed) } } - pub fn add_clause(&mut self, landing_pad: &'ll Value, clause: &'ll Value) { + pub(crate) fn add_clause(&mut self, landing_pad: &'ll Value, clause: &'ll Value) { unsafe { llvm::LLVMAddClause(landing_pad, clause); } } - pub fn catch_ret(&mut self, funclet: &Funclet<'ll>, unwind: &'ll BasicBlock) -> &'ll Value { + pub(crate) fn catch_ret( + &mut self, + funclet: &Funclet<'ll>, + unwind: &'ll BasicBlock, + ) -> &'ll Value { let ret = unsafe { llvm::LLVMBuildCatchRet(self.llbuilder, funclet.cleanuppad(), unwind) }; ret.expect("LLVM does not have support for catchret") } @@ -1515,7 +1527,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { Cow::Owned(casted_args) } - pub fn va_arg(&mut self, list: &'ll Value, ty: &'ll Type) -> &'ll Value { + pub(crate) fn va_arg(&mut self, list: &'ll Value, ty: &'ll Type) -> &'ll Value { unsafe { llvm::LLVMBuildVAArg(self.llbuilder, list, ty, UNNAMED) } } diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs index 663c5be46e5..949fd1bc124 100644 --- a/compiler/rustc_codegen_llvm/src/callee.rs +++ b/compiler/rustc_codegen_llvm/src/callee.rs @@ -20,7 +20,7 @@ use crate::value::Value; /// /// - `cx`: the crate context /// - `instance`: the instance to be instantiated -pub fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> &'ll Value { +pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> &'ll Value { let tcx = cx.tcx(); debug!("get_fn(instance={:?})", instance); diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index a3997900184..ef6560ecbe5 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -13,7 +13,7 @@ use rustc_target::abi::{self, AddressSpace, HasDataLayout, Pointer}; use tracing::debug; use crate::consts::const_alloc_to_llvm; -pub use crate::context::CodegenCx; +pub(crate) use crate::context::CodegenCx; use crate::llvm::{self, BasicBlock, Bool, ConstantInt, False, OperandBundleDef, True}; use crate::type_::Type; use crate::value::Value; @@ -58,21 +58,21 @@ use crate::value::Value; /// When inside of a landing pad, each function call in LLVM IR needs to be /// annotated with which landing pad it's a part of. This is accomplished via /// the `OperandBundleDef` value created for MSVC landing pads. -pub struct Funclet<'ll> { +pub(crate) struct Funclet<'ll> { cleanuppad: &'ll Value, operand: OperandBundleDef<'ll>, } impl<'ll> Funclet<'ll> { - pub fn new(cleanuppad: &'ll Value) -> Self { + pub(crate) fn new(cleanuppad: &'ll Value) -> Self { Funclet { cleanuppad, operand: OperandBundleDef::new("funclet", &[cleanuppad]) } } - pub fn cleanuppad(&self) -> &'ll Value { + pub(crate) fn cleanuppad(&self) -> &'ll Value { self.cleanuppad } - pub fn bundle(&self) -> &OperandBundleDef<'ll> { + pub(crate) fn bundle(&self) -> &OperandBundleDef<'ll> { &self.operand } } @@ -92,16 +92,16 @@ impl<'ll> BackendTypes for CodegenCx<'ll, '_> { } impl<'ll> CodegenCx<'ll, '_> { - pub fn const_array(&self, ty: &'ll Type, elts: &[&'ll Value]) -> &'ll Value { + pub(crate) fn const_array(&self, ty: &'ll Type, elts: &[&'ll Value]) -> &'ll Value { let len = u64::try_from(elts.len()).expect("LLVMConstArray2 elements len overflow"); unsafe { llvm::LLVMConstArray2(ty, elts.as_ptr(), len) } } - pub fn const_bytes(&self, bytes: &[u8]) -> &'ll Value { + pub(crate) fn const_bytes(&self, bytes: &[u8]) -> &'ll Value { bytes_in_context(self.llcx, bytes) } - pub fn const_get_elt(&self, v: &'ll Value, idx: u64) -> &'ll Value { + pub(crate) fn const_get_elt(&self, v: &'ll Value, idx: u64) -> &'ll Value { unsafe { let idx = c_uint::try_from(idx).expect("LLVMGetAggregateElement index overflow"); let r = llvm::LLVMGetAggregateElement(v, idx).unwrap(); @@ -339,18 +339,18 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { } /// Get the [LLVM type][Type] of a [`Value`]. -pub fn val_ty(v: &Value) -> &Type { +pub(crate) fn val_ty(v: &Value) -> &Type { unsafe { llvm::LLVMTypeOf(v) } } -pub fn bytes_in_context<'ll>(llcx: &'ll llvm::Context, bytes: &[u8]) -> &'ll Value { +pub(crate) fn bytes_in_context<'ll>(llcx: &'ll llvm::Context, bytes: &[u8]) -> &'ll Value { unsafe { let ptr = bytes.as_ptr() as *const c_char; llvm::LLVMConstStringInContext2(llcx, ptr, bytes.len(), True) } } -pub fn struct_in_context<'ll>( +fn struct_in_context<'ll>( llcx: &'ll llvm::Context, elts: &[&'ll Value], packed: bool, diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 75b298f14ca..b143e28c5f9 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -29,7 +29,7 @@ use crate::type_of::LayoutLlvmExt; use crate::value::Value; use crate::{base, debuginfo}; -pub fn const_alloc_to_llvm<'ll>( +pub(crate) fn const_alloc_to_llvm<'ll>( cx: &CodegenCx<'ll, '_>, alloc: ConstAllocation<'_>, is_static: bool, @@ -525,7 +525,7 @@ impl<'ll> CodegenCx<'ll, '_> { let val = llvm::LLVMMetadataAsValue(self.llcx, meta); llvm::LLVMAddNamedMetadataOperand( self.llmod, - c"wasm.custom_sections".as_ptr().cast(), + c"wasm.custom_sections".as_ptr(), val, ); } diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index dd3f39ecead..01aae24ab56 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -11,6 +11,7 @@ use rustc_data_structures::base_n::{ToBaseN, ALPHANUMERIC_ONLY}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::small_c_str::SmallCStr; use rustc_hir::def_id::DefId; +use rustc_middle::middle::codegen_fn_attrs::PatchableFunctionEntry; use rustc_middle::mir::mono::CodegenUnit; use rustc_middle::ty::layout::{ FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, LayoutError, LayoutOfHelpers, @@ -39,7 +40,7 @@ use crate::{attributes, coverageinfo, debuginfo, llvm, llvm_util}; /// There is one `CodegenCx` per compilation unit. Each one has its own LLVM /// `llvm::Context` so that several compilation units may be optimized in parallel. /// All other LLVM data structures in the `CodegenCx` are tied to that `llvm::Context`. -pub struct CodegenCx<'ll, 'tcx> { +pub(crate) struct CodegenCx<'ll, 'tcx> { pub tcx: TyCtxt<'tcx>, pub use_dll_storage_attrs: bool, pub tls_model: llvm::ThreadLocalMode, @@ -110,7 +111,7 @@ fn to_llvm_tls_model(tls_model: TlsModel) -> llvm::ThreadLocalMode { } } -pub unsafe fn create_module<'ll>( +pub(crate) unsafe fn create_module<'ll>( tcx: TyCtxt<'_>, llcx: &'ll llvm::Context, mod_name: &str, @@ -207,7 +208,7 @@ pub unsafe fn create_module<'ll>( // If skipping the PLT is enabled, we need to add some module metadata // to ensure intrinsic calls don't use it. if !sess.needs_plt() { - let avoid_plt = c"RtLibUseGOT".as_ptr().cast(); + let avoid_plt = c"RtLibUseGOT".as_ptr(); unsafe { llvm::LLVMRustAddModuleFlagU32(llmod, llvm::LLVMModFlagBehavior::Warning, avoid_plt, 1); } @@ -215,7 +216,7 @@ pub unsafe fn create_module<'ll>( // Enable canonical jump tables if CFI is enabled. (See https://reviews.llvm.org/D65629.) if sess.is_sanitizer_cfi_canonical_jump_tables_enabled() && sess.is_sanitizer_cfi_enabled() { - let canonical_jump_tables = c"CFI Canonical Jump Tables".as_ptr().cast(); + let canonical_jump_tables = c"CFI Canonical Jump Tables".as_ptr(); unsafe { llvm::LLVMRustAddModuleFlagU32( llmod, @@ -226,9 +227,23 @@ pub unsafe fn create_module<'ll>( } } + // If we're normalizing integers with CFI, ensure LLVM generated functions do the same. + // See https://github.com/llvm/llvm-project/pull/104826 + if sess.is_sanitizer_cfi_normalize_integers_enabled() { + let cfi_normalize_integers = c"cfi-normalize-integers".as_ptr().cast(); + unsafe { + llvm::LLVMRustAddModuleFlagU32( + llmod, + llvm::LLVMModFlagBehavior::Override, + cfi_normalize_integers, + 1, + ); + } + } + // Enable LTO unit splitting if specified or if CFI is enabled. (See https://reviews.llvm.org/D53891.) if sess.is_split_lto_unit_enabled() || sess.is_sanitizer_cfi_enabled() { - let enable_split_lto_unit = c"EnableSplitLTOUnit".as_ptr().cast(); + let enable_split_lto_unit = c"EnableSplitLTOUnit".as_ptr(); unsafe { llvm::LLVMRustAddModuleFlagU32( llmod, @@ -241,10 +256,26 @@ pub unsafe fn create_module<'ll>( // Add "kcfi" module flag if KCFI is enabled. (See https://reviews.llvm.org/D119296.) if sess.is_sanitizer_kcfi_enabled() { - let kcfi = c"kcfi".as_ptr().cast(); + let kcfi = c"kcfi".as_ptr(); unsafe { llvm::LLVMRustAddModuleFlagU32(llmod, llvm::LLVMModFlagBehavior::Override, kcfi, 1); } + + // Add "kcfi-offset" module flag with -Z patchable-function-entry (See + // https://reviews.llvm.org/D141172). + let pfe = + PatchableFunctionEntry::from_config(sess.opts.unstable_opts.patchable_function_entry); + if pfe.prefix() > 0 { + let kcfi_offset = c"kcfi-offset".as_ptr().cast(); + unsafe { + llvm::LLVMRustAddModuleFlagU32( + llmod, + llvm::LLVMModFlagBehavior::Override, + kcfi_offset, + pfe.prefix().into(), + ); + } + } } // Control Flow Guard is currently only supported by the MSVC linker on Windows. @@ -280,26 +311,26 @@ pub unsafe fn create_module<'ll>( llvm::LLVMRustAddModuleFlagU32( llmod, llvm::LLVMModFlagBehavior::Min, - c"branch-target-enforcement".as_ptr().cast(), + c"branch-target-enforcement".as_ptr(), bti.into(), ); llvm::LLVMRustAddModuleFlagU32( llmod, llvm::LLVMModFlagBehavior::Min, - c"sign-return-address".as_ptr().cast(), + c"sign-return-address".as_ptr(), pac_ret.is_some().into(), ); let pac_opts = pac_ret.unwrap_or(PacRet { leaf: false, key: PAuthKey::A }); llvm::LLVMRustAddModuleFlagU32( llmod, llvm::LLVMModFlagBehavior::Min, - c"sign-return-address-all".as_ptr().cast(), + c"sign-return-address-all".as_ptr(), pac_opts.leaf.into(), ); llvm::LLVMRustAddModuleFlagU32( llmod, llvm::LLVMModFlagBehavior::Min, - c"sign-return-address-with-bkey".as_ptr().cast(), + c"sign-return-address-with-bkey".as_ptr(), u32::from(pac_opts.key == PAuthKey::B), ); } @@ -317,7 +348,7 @@ pub unsafe fn create_module<'ll>( llvm::LLVMRustAddModuleFlagU32( llmod, llvm::LLVMModFlagBehavior::Override, - c"cf-protection-branch".as_ptr().cast(), + c"cf-protection-branch".as_ptr(), 1, ); } @@ -327,7 +358,7 @@ pub unsafe fn create_module<'ll>( llvm::LLVMRustAddModuleFlagU32( llmod, llvm::LLVMModFlagBehavior::Override, - c"cf-protection-return".as_ptr().cast(), + c"cf-protection-return".as_ptr(), 1, ); } @@ -338,7 +369,7 @@ pub unsafe fn create_module<'ll>( llvm::LLVMRustAddModuleFlagU32( llmod, llvm::LLVMModFlagBehavior::Error, - c"Virtual Function Elim".as_ptr().cast(), + c"Virtual Function Elim".as_ptr(), 1, ); } @@ -531,7 +562,9 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { } #[inline] - pub fn coverage_context(&self) -> Option<&coverageinfo::CrateCoverageContext<'ll, 'tcx>> { + pub(crate) fn coverage_context( + &self, + ) -> Option<&coverageinfo::CrateCoverageContext<'ll, 'tcx>> { self.coverage_cx.as_ref() } @@ -1000,8 +1033,10 @@ impl<'ll> CodegenCx<'ll, '_> { ifn!("llvm.is.constant.i64", fn(t_i64) -> i1); ifn!("llvm.is.constant.i128", fn(t_i128) -> i1); ifn!("llvm.is.constant.isize", fn(t_isize) -> i1); + ifn!("llvm.is.constant.f16", fn(t_f16) -> i1); ifn!("llvm.is.constant.f32", fn(t_f32) -> i1); ifn!("llvm.is.constant.f64", fn(t_f64) -> i1); + ifn!("llvm.is.constant.f128", fn(t_f128) -> i1); ifn!("llvm.is.constant.ptr", fn(ptr) -> i1); ifn!("llvm.expect.i1", fn(i1, i1) -> i1); @@ -1064,7 +1099,7 @@ impl<'ll> CodegenCx<'ll, '_> { impl CodegenCx<'_, '_> { /// Generates a new symbol name with the given prefix. This symbol name must /// only be used for definitions with `internal` or `private` linkage. - pub fn generate_local_symbol_name(&self, prefix: &str) -> String { + pub(crate) fn generate_local_symbol_name(&self, prefix: &str) -> String { let idx = self.local_gen_sym_counter.get(); self.local_gen_sym_counter.set(idx + 1); // Include a '.' character, so there can be no accidental conflicts with diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs index 584d033d6bd..d7a4f105f3c 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs @@ -1,5 +1,5 @@ use rustc_middle::mir::coverage::{ - CodeRegion, ConditionInfo, CounterId, CovTerm, DecisionInfo, ExpressionId, MappingKind, + ConditionInfo, CounterId, CovTerm, DecisionInfo, ExpressionId, MappingKind, SourceRegion, }; /// Must match the layout of `LLVMRustCounterKind`. @@ -80,7 +80,7 @@ pub struct CounterExpression { /// Must match the layout of `LLVMRustCounterMappingRegionKind`. #[derive(Copy, Clone, Debug)] #[repr(C)] -pub enum RegionKind { +enum RegionKind { /// A CodeRegion associates some code with a counter CodeRegion = 0, @@ -110,13 +110,13 @@ pub enum RegionKind { MCDCBranchRegion = 6, } -pub mod mcdc { +mod mcdc { use rustc_middle::mir::coverage::{ConditionInfo, DecisionInfo}; /// Must match the layout of `LLVMRustMCDCDecisionParameters`. #[repr(C)] #[derive(Clone, Copy, Debug, Default)] - pub struct DecisionParameters { + pub(crate) struct DecisionParameters { bitmap_idx: u32, num_conditions: u16, } @@ -127,14 +127,14 @@ pub mod mcdc { /// Must match the layout of `LLVMRustMCDCBranchParameters`. #[repr(C)] #[derive(Clone, Copy, Debug, Default)] - pub struct BranchParameters { + pub(crate) struct BranchParameters { condition_id: LLVMConditionId, condition_ids: [LLVMConditionId; 2], } #[repr(C)] #[derive(Clone, Copy, Debug)] - pub enum ParameterTag { + enum ParameterTag { None = 0, Decision = 1, Branch = 2, @@ -142,24 +142,24 @@ pub mod mcdc { /// Same layout with `LLVMRustMCDCParameters` #[repr(C)] #[derive(Clone, Copy, Debug)] - pub struct Parameters { + pub(crate) struct Parameters { tag: ParameterTag, decision_params: DecisionParameters, branch_params: BranchParameters, } impl Parameters { - pub fn none() -> Self { + pub(crate) fn none() -> Self { Self { tag: ParameterTag::None, decision_params: Default::default(), branch_params: Default::default(), } } - pub fn decision(decision_params: DecisionParameters) -> Self { + pub(crate) fn decision(decision_params: DecisionParameters) -> Self { Self { tag: ParameterTag::Decision, decision_params, branch_params: Default::default() } } - pub fn branch(branch_params: BranchParameters) -> Self { + pub(crate) fn branch(branch_params: BranchParameters) -> Self { Self { tag: ParameterTag::Branch, decision_params: Default::default(), branch_params } } } @@ -236,9 +236,10 @@ impl CounterMappingRegion { pub(crate) fn from_mapping( mapping_kind: &MappingKind, local_file_id: u32, - code_region: &CodeRegion, + source_region: &SourceRegion, ) -> Self { - let &CodeRegion { file_name: _, start_line, start_col, end_line, end_col } = code_region; + let &SourceRegion { file_name: _, start_line, start_col, end_line, end_col } = + source_region; match *mapping_kind { MappingKind::Code(term) => Self::code_region( Counter::from_term(term), diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs index 9433385c23a..5ed640b840e 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs @@ -2,8 +2,8 @@ use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxIndexSet; use rustc_index::bit_set::BitSet; use rustc_middle::mir::coverage::{ - CodeRegion, CounterId, CovTerm, Expression, ExpressionId, FunctionCoverageInfo, Mapping, - MappingKind, Op, + CounterId, CovTerm, Expression, ExpressionId, FunctionCoverageInfo, Mapping, MappingKind, Op, + SourceRegion, }; use rustc_middle::ty::Instance; use rustc_span::Symbol; @@ -14,7 +14,7 @@ use crate::coverageinfo::ffi::{Counter, CounterExpression, ExprKind}; /// Holds all of the coverage mapping data associated with a function instance, /// collected during traversal of `Coverage` statements in the function's MIR. #[derive(Debug)] -pub struct FunctionCoverageCollector<'tcx> { +pub(crate) struct FunctionCoverageCollector<'tcx> { /// Coverage info that was attached to this function by the instrumentor. function_coverage_info: &'tcx FunctionCoverageInfo, is_used: bool, @@ -32,7 +32,7 @@ pub struct FunctionCoverageCollector<'tcx> { impl<'tcx> FunctionCoverageCollector<'tcx> { /// Creates a new set of coverage data for a used (called) function. - pub fn new( + pub(crate) fn new( instance: Instance<'tcx>, function_coverage_info: &'tcx FunctionCoverageInfo, ) -> Self { @@ -40,7 +40,7 @@ impl<'tcx> FunctionCoverageCollector<'tcx> { } /// Creates a new set of coverage data for an unused (never called) function. - pub fn unused( + pub(crate) fn unused( instance: Instance<'tcx>, function_coverage_info: &'tcx FunctionCoverageInfo, ) -> Self { @@ -195,13 +195,13 @@ impl<'tcx> FunctionCoverage<'tcx> { /// Return the source hash, generated from the HIR node structure, and used to indicate whether /// or not the source code structure changed between different compilations. - pub fn source_hash(&self) -> u64 { + pub(crate) fn source_hash(&self) -> u64 { 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.code_region.file_name) + 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 @@ -230,12 +230,12 @@ impl<'tcx> FunctionCoverage<'tcx> { /// that will be used by `mapgen` when preparing for FFI. pub(crate) fn counter_regions( &self, - ) -> impl Iterator + ExactSizeIterator { + ) -> impl Iterator + ExactSizeIterator { self.function_coverage_info.mappings.iter().map(move |mapping| { - let Mapping { kind, code_region } = mapping; + let Mapping { kind, source_region } = mapping; let kind = kind.map_terms(|term| if self.is_zero_term(term) { CovTerm::Zero } else { term }); - (kind, code_region) + (kind, source_region) }) } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index f8929a26011..069b62af5e7 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -27,7 +27,7 @@ use crate::{coverageinfo, llvm}; /// implementing this Rust version, and though the format documentation is very explicit and /// detailed, some undocumented details in Clang's implementation (that may or may not be important) /// were also replicated for Rust's Coverage Map. -pub fn finalize(cx: &CodegenCx<'_, '_>) { +pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { let tcx = cx.tcx; // Ensure that LLVM is using a version of the coverage mapping format that diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index 20a713b8564..69babc7c9cf 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -22,10 +22,10 @@ use crate::llvm; pub(crate) mod ffi; pub(crate) mod map_data; -pub mod mapgen; +mod mapgen; /// A context object for maintaining all state needed by the coverageinfo module. -pub struct CrateCoverageContext<'ll, 'tcx> { +pub(crate) struct CrateCoverageContext<'ll, 'tcx> { /// Coverage data for each instrumented function identified by DefId. pub(crate) function_coverage_map: RefCell, FunctionCoverageCollector<'tcx>>>, @@ -34,7 +34,7 @@ pub struct CrateCoverageContext<'ll, 'tcx> { } impl<'ll, 'tcx> CrateCoverageContext<'ll, 'tcx> { - pub fn new() -> Self { + pub(crate) fn new() -> Self { Self { function_coverage_map: Default::default(), pgo_func_name_var_map: Default::default(), @@ -42,7 +42,7 @@ impl<'ll, 'tcx> CrateCoverageContext<'ll, 'tcx> { } } - pub fn take_function_coverage_map( + fn take_function_coverage_map( &self, ) -> FxIndexMap, FunctionCoverageCollector<'tcx>> { self.function_coverage_map.replace(FxIndexMap::default()) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs index efe616838bf..c3087d8ec30 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs @@ -15,7 +15,7 @@ use crate::llvm::debuginfo::{DILocation, DIScope}; /// Produces DIScope DIEs for each MIR Scope which has variables defined in it. // FIXME(eddyb) almost all of this should be in `rustc_codegen_ssa::mir::debuginfo`. -pub fn compute_mir_scopes<'ll, 'tcx>( +pub(crate) fn compute_mir_scopes<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>, mir: &Body<'tcx>, @@ -88,7 +88,7 @@ fn make_mir_scope<'ll, 'tcx>( let loc = cx.lookup_debug_loc(scope_data.span.lo()); let file_metadata = file_metadata(cx, &loc.file); - let parent_dbg_scope = match scope_data.inlined { + let dbg_scope = match scope_data.inlined { Some((callee, _)) => { // FIXME(eddyb) this would be `self.monomorphize(&callee)` // if this is moved to `rustc_codegen_ssa::mir::debuginfo`. @@ -102,17 +102,15 @@ fn make_mir_scope<'ll, 'tcx>( cx.dbg_scope_fn(callee, callee_fn_abi, None) }) } - None => parent_scope.dbg_scope, - }; - - let dbg_scope = unsafe { - llvm::LLVMRustDIBuilderCreateLexicalBlock( - DIB(cx), - parent_dbg_scope, - file_metadata, - loc.line, - loc.col, - ) + None => unsafe { + llvm::LLVMRustDIBuilderCreateLexicalBlock( + DIB(cx), + parent_scope.dbg_scope, + file_metadata, + loc.line, + loc.col, + ) + }, }; let inlined_at = scope_data.inlined.map(|(_, callsite_span)| { diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs index 5a08f2f00e5..dc228e94811 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs @@ -16,7 +16,7 @@ use crate::value::Value; /// Inserts a side-effect free instruction sequence that makes sure that the /// .debug_gdb_scripts global is referenced, so it isn't removed by the linker. -pub fn insert_reference_to_gdb_debug_scripts_section_global(bx: &mut Builder<'_, '_, '_>) { +pub(crate) fn insert_reference_to_gdb_debug_scripts_section_global(bx: &mut Builder<'_, '_, '_>) { if needs_gdb_debug_scripts_section(bx) { let gdb_debug_scripts_section = get_or_insert_gdb_debug_scripts_section_global(bx); // Load just the first byte as that's all that's necessary to force @@ -30,12 +30,13 @@ pub fn insert_reference_to_gdb_debug_scripts_section_global(bx: &mut Builder<'_, /// Allocates the global variable responsible for the .debug_gdb_scripts binary /// section. -pub fn get_or_insert_gdb_debug_scripts_section_global<'ll>(cx: &CodegenCx<'ll, '_>) -> &'ll Value { +pub(crate) fn get_or_insert_gdb_debug_scripts_section_global<'ll>( + cx: &CodegenCx<'ll, '_>, +) -> &'ll Value { let c_section_var_name = c"__rustc_debug_gdb_scripts_section__"; let section_var_name = c_section_var_name.to_str().unwrap(); - let section_var = - unsafe { llvm::LLVMGetNamedGlobal(cx.llmod, c_section_var_name.as_ptr().cast()) }; + let section_var = unsafe { llvm::LLVMGetNamedGlobal(cx.llmod, c_section_var_name.as_ptr()) }; section_var.unwrap_or_else(|| { let mut section_contents = Vec::new(); @@ -70,7 +71,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global<'ll>(cx: &CodegenCx<'ll, ' let section_var = cx .define_global(section_var_name, llvm_type) .unwrap_or_else(|| bug!("symbol `{}` is already defined", section_var_name)); - llvm::LLVMSetSection(section_var, c".debug_gdb_scripts".as_ptr().cast()); + llvm::LLVMSetSection(section_var, c".debug_gdb_scripts".as_ptr()); llvm::LLVMSetInitializer(section_var, cx.const_bytes(section_contents)); llvm::LLVMSetGlobalConstant(section_var, llvm::True); llvm::LLVMSetUnnamedAddress(section_var, llvm::UnnamedAddr::Global); @@ -83,7 +84,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global<'ll>(cx: &CodegenCx<'ll, ' }) } -pub fn needs_gdb_debug_scripts_section(cx: &CodegenCx<'_, '_>) -> bool { +pub(crate) fn needs_gdb_debug_scripts_section(cx: &CodegenCx<'_, '_>) -> bool { let omit_gdb_pretty_printer_section = attr::contains_name(cx.tcx.hir().krate_attrs(), sym::omit_gdb_pretty_printer_section); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index ad638588612..dc59e9349b0 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -85,7 +85,7 @@ const NO_GENERICS: for<'ll> fn(&CodegenCx<'ll, '_>) -> SmallVec<&'ll DIType> = | // SmallVec is used quite a bit in this module, so create a shorthand. // The actual number of elements is not so important. -pub type SmallVec = smallvec::SmallVec<[T; 16]>; +type SmallVec = smallvec::SmallVec<[T; 16]>; mod enums; mod type_map; @@ -425,7 +425,7 @@ fn build_slice_type_di_node<'ll, 'tcx>( /// /// This function will look up the debuginfo node in the TypeMap. If it can't find it, it /// will create the node by dispatching to the corresponding `build_*_di_node()` function. -pub fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { +pub(crate) fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { let unique_type_id = UniqueTypeId::for_ty(cx.tcx, t); if let Some(existing_di_node) = debug_context(cx).type_map.di_node_for_unique_id(unique_type_id) @@ -456,7 +456,7 @@ pub fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll D { build_pointer_or_reference_di_node(cx, t, t.boxed_ty(), unique_type_id) } - ty::FnDef(..) | ty::FnPtr(_) => build_subroutine_type_di_node(cx, unique_type_id), + ty::FnDef(..) | ty::FnPtr(..) => build_subroutine_type_di_node(cx, unique_type_id), ty::Closure(..) => build_closure_env_di_node(cx, unique_type_id), ty::CoroutineClosure(..) => build_closure_env_di_node(cx, unique_type_id), ty::Coroutine(..) => enums::build_coroutine_di_node(cx, unique_type_id), @@ -531,7 +531,7 @@ fn hex_encode(data: &[u8]) -> String { hex_string } -pub fn file_metadata<'ll>(cx: &CodegenCx<'ll, '_>, source_file: &SourceFile) -> &'ll DIFile { +pub(crate) fn file_metadata<'ll>(cx: &CodegenCx<'ll, '_>, source_file: &SourceFile) -> &'ll DIFile { let cache_key = Some((source_file.stable_id, source_file.src_hash)); return debug_context(cx) .created_files @@ -629,6 +629,9 @@ pub fn file_metadata<'ll>(cx: &CodegenCx<'ll, '_>, source_file: &SourceFile) -> }; let hash_value = hex_encode(source_file.src_hash.hash_bytes()); + let source = + cx.sess().opts.unstable_opts.embed_source.then_some(()).and(source_file.src.as_ref()); + unsafe { llvm::LLVMRustDIBuilderCreateFile( DIB(cx), @@ -639,12 +642,14 @@ pub fn file_metadata<'ll>(cx: &CodegenCx<'ll, '_>, source_file: &SourceFile) -> hash_kind, hash_value.as_ptr().cast(), hash_value.len(), + source.map_or(ptr::null(), |x| x.as_ptr().cast()), + source.map_or(0, |x| x.len()), ) } } } -pub fn unknown_file_metadata<'ll>(cx: &CodegenCx<'ll, '_>) -> &'ll DIFile { +fn unknown_file_metadata<'ll>(cx: &CodegenCx<'ll, '_>) -> &'ll DIFile { debug_context(cx).created_files.borrow_mut().entry(None).or_insert_with(|| unsafe { let file_name = ""; let directory = ""; @@ -659,6 +664,8 @@ pub fn unknown_file_metadata<'ll>(cx: &CodegenCx<'ll, '_>) -> &'ll DIFile { llvm::ChecksumKind::None, hash_value.as_ptr().cast(), hash_value.len(), + ptr::null(), + 0, ) }) } @@ -859,7 +866,7 @@ fn build_param_type_di_node<'ll, 'tcx>( } } -pub fn build_compile_unit_di_node<'ll, 'tcx>( +pub(crate) fn build_compile_unit_di_node<'ll, 'tcx>( tcx: TyCtxt<'tcx>, codegen_unit_name: &str, debug_context: &CodegenUnitDebugContext<'ll, 'tcx>, @@ -943,6 +950,8 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>( llvm::ChecksumKind::None, ptr::null(), 0, + ptr::null(), + 0, ); let unit_metadata = llvm::LLVMRustDIBuilderCreateCompileUnit( @@ -952,7 +961,7 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>( producer.as_ptr().cast(), producer.len(), tcx.sess.opts.optimize != config::OptLevel::No, - c"".as_ptr().cast(), + c"".as_ptr(), 0, // NB: this doesn't actually have any perceptible effect, it seems. LLVM will instead // put the path supplied to `MCSplitDwarfFile` into the debug info of the final @@ -1319,7 +1328,11 @@ fn build_generic_type_param_di_nodes<'ll, 'tcx>( /// Creates debug information for the given global variable. /// /// Adds the created debuginfo nodes directly to the crate's IR. -pub fn build_global_var_di_node<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId, global: &'ll Value) { +pub(crate) fn build_global_var_di_node<'ll>( + cx: &CodegenCx<'ll, '_>, + def_id: DefId, + global: &'ll Value, +) { if cx.dbg_cx.is_none() { return; } @@ -1559,7 +1572,7 @@ pub(crate) fn apply_vcall_visibility_metadata<'ll, 'tcx>( /// given type. /// /// Adds the created metadata nodes directly to the crate's IR. -pub fn create_vtable_di_node<'ll, 'tcx>( +pub(crate) fn create_vtable_di_node<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>, poly_trait_ref: Option>, @@ -1604,7 +1617,7 @@ pub fn create_vtable_di_node<'ll, 'tcx>( } /// Creates an "extension" of an existing `DIScope` into another file. -pub fn extend_scope_to_file<'ll>( +pub(crate) fn extend_scope_to_file<'ll>( cx: &CodegenCx<'ll, '_>, scope_metadata: &'ll DIScope, file: &SourceFile, @@ -1613,7 +1626,7 @@ pub fn extend_scope_to_file<'ll>( unsafe { llvm::LLVMRustDIBuilderCreateLexicalBlockFile(DIB(cx), scope_metadata, file_metadata) } } -pub fn tuple_field_name(field_index: usize) -> Cow<'static, str> { +fn tuple_field_name(field_index: usize) -> Cow<'static, str> { const TUPLE_FIELD_NAMES: [&'static str; 16] = [ "__0", "__1", "__2", "__3", "__4", "__5", "__6", "__7", "__8", "__9", "__10", "__11", "__12", "__13", "__14", "__15", diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs index 13006638bb3..181022087f3 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use libc::c_uint; use rustc_codegen_ssa::debuginfo::type_names::compute_debuginfo_type_name; -use rustc_codegen_ssa::debuginfo::wants_c_like_enum_debuginfo; +use rustc_codegen_ssa::debuginfo::{tag_base_type, wants_c_like_enum_debuginfo}; use rustc_codegen_ssa::traits::ConstMethods; use rustc_index::IndexVec; use rustc_middle::bug; @@ -12,7 +12,7 @@ use rustc_target::abi::{Align, Endian, Size, TagEncoding, VariantIdx, Variants}; use smallvec::smallvec; use crate::common::CodegenCx; -use crate::debuginfo::metadata::enums::{tag_base_type, DiscrResult}; +use crate::debuginfo::metadata::enums::DiscrResult; use crate::debuginfo::metadata::type_map::{self, Stub, UniqueTypeId}; use crate::debuginfo::metadata::{ build_field_di_node, file_metadata, size_and_align_of, type_di_node, unknown_file_metadata, @@ -190,7 +190,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( let enum_type_and_layout = cx.layout_of(enum_type); let enum_type_name = compute_debuginfo_type_name(cx.tcx, enum_type, false); - assert!(!wants_c_like_enum_debuginfo(enum_type_and_layout)); + assert!(!wants_c_like_enum_debuginfo(cx.tcx, enum_type_and_layout)); type_map::build_type_with_children( cx, @@ -265,7 +265,7 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>( let coroutine_type_and_layout = cx.layout_of(coroutine_type); let coroutine_type_name = compute_debuginfo_type_name(cx.tcx, coroutine_type, false); - assert!(!wants_c_like_enum_debuginfo(coroutine_type_and_layout)); + assert!(!wants_c_like_enum_debuginfo(cx.tcx, coroutine_type_and_layout)); type_map::build_type_with_children( cx, @@ -381,7 +381,7 @@ fn build_union_fields_for_enum<'ll, 'tcx>( tag_field: usize, untagged_variant_index: Option, ) -> SmallVec<&'ll DIType> { - let tag_base_type = super::tag_base_type(cx, enum_type_and_layout); + let tag_base_type = tag_base_type(cx.tcx, enum_type_and_layout); let variant_names_type_di_node = build_variant_names_type_di_node( cx, @@ -676,7 +676,7 @@ fn build_union_fields_for_direct_tag_coroutine<'ll, 'tcx>( let variant_range = coroutine_args.variant_range(coroutine_def_id, cx.tcx); let variant_count = (variant_range.start.as_u32()..variant_range.end.as_u32()).len(); - let tag_base_type = tag_base_type(cx, coroutine_type_and_layout); + let tag_base_type = tag_base_type(cx.tcx, coroutine_type_and_layout); let variant_names_type_di_node = build_variant_names_type_di_node( cx, @@ -803,7 +803,7 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>( assert_eq!( cx.size_and_align_of(enum_type_and_layout.field(cx, tag_field).ty), - cx.size_and_align_of(super::tag_base_type(cx, enum_type_and_layout)) + cx.size_and_align_of(self::tag_base_type(cx.tcx, enum_type_and_layout)) ); // ... and a field for the tag. If the tag is 128 bits wide, this will actually diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs index fc3adaf0681..edaf73b74a2 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -1,17 +1,15 @@ use std::borrow::Cow; use rustc_codegen_ssa::debuginfo::type_names::{compute_debuginfo_type_name, cpp_like_debuginfo}; -use rustc_codegen_ssa::debuginfo::wants_c_like_enum_debuginfo; +use rustc_codegen_ssa::debuginfo::{tag_base_type, wants_c_like_enum_debuginfo}; use rustc_hir::def::CtorKind; use rustc_index::IndexSlice; use rustc_middle::bug; use rustc_middle::mir::CoroutineLayout; -use rustc_middle::ty::layout::{IntegerExt, LayoutOf, PrimitiveExt, TyAndLayout}; +use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, AdtDef, CoroutineArgs, CoroutineArgsExt, Ty, VariantDef}; use rustc_span::Symbol; -use rustc_target::abi::{ - FieldIdx, HasDataLayout, Integer, Primitive, TagEncoding, VariantIdx, Variants, -}; +use rustc_target::abi::{FieldIdx, TagEncoding, VariantIdx, Variants}; use super::type_map::{DINodeCreationResult, UniqueTypeId}; use super::{size_and_align_of, SmallVec}; @@ -39,7 +37,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( let enum_type_and_layout = cx.layout_of(enum_type); - if wants_c_like_enum_debuginfo(enum_type_and_layout) { + if wants_c_like_enum_debuginfo(cx.tcx, enum_type_and_layout) { return build_c_style_enum_di_node(cx, enum_adt_def, enum_type_and_layout); } @@ -74,7 +72,7 @@ fn build_c_style_enum_di_node<'ll, 'tcx>( di_node: build_enumeration_type_di_node( cx, &compute_debuginfo_type_name(cx.tcx, enum_type_and_layout.ty, false), - tag_base_type(cx, enum_type_and_layout), + tag_base_type(cx.tcx, enum_type_and_layout), enum_adt_def.discriminants(cx.tcx).map(|(variant_index, discr)| { let name = Cow::from(enum_adt_def.variant(variant_index).name.as_str()); (name, discr.val) @@ -85,48 +83,6 @@ fn build_c_style_enum_di_node<'ll, 'tcx>( } } -/// Extract the type with which we want to describe the tag of the given enum or coroutine. -fn tag_base_type<'ll, 'tcx>( - cx: &CodegenCx<'ll, 'tcx>, - enum_type_and_layout: TyAndLayout<'tcx>, -) -> Ty<'tcx> { - assert!(match enum_type_and_layout.ty.kind() { - ty::Coroutine(..) => true, - ty::Adt(adt_def, _) => adt_def.is_enum(), - _ => false, - }); - - match enum_type_and_layout.layout.variants() { - // A single-variant enum has no discriminant. - Variants::Single { .. } => { - bug!("tag_base_type() called for enum without tag: {:?}", enum_type_and_layout) - } - - Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, tag, .. } => { - // Niche tags are always normalized to unsized integers of the correct size. - match tag.primitive() { - Primitive::Int(t, _) => t, - Primitive::Float(f) => Integer::from_size(f.size()).unwrap(), - // FIXME(erikdesjardins): handle non-default addrspace ptr sizes - Primitive::Pointer(_) => { - // If the niche is the NULL value of a reference, then `discr_enum_ty` will be - // a RawPtr. CodeView doesn't know what to do with enums whose base type is a - // pointer so we fix this up to just be `usize`. - // DWARF might be able to deal with this but with an integer type we are on - // the safe side there too. - cx.data_layout().ptr_sized_integer() - } - } - .to_ty(cx.tcx, false) - } - - Variants::Multiple { tag_encoding: TagEncoding::Direct, tag, .. } => { - // Direct tags preserve the sign. - tag.primitive().to_ty(cx.tcx) - } - } -} - /// Build a DW_TAG_enumeration_type debuginfo node, with the given base type and variants. /// This is a helper function and does not register anything in the type map by itself. /// @@ -301,7 +257,7 @@ fn build_enum_variant_struct_type_di_node<'ll, 'tcx>( /// ---> DW_TAG_structure_type (type of variant 3) /// /// ``` -pub fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>( +fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, variant_index: VariantIdx, coroutine_type_and_layout: TyAndLayout<'tcx>, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs index d7e3b47e0bd..238fbad4dfd 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use libc::c_uint; use rustc_codegen_ssa::debuginfo::type_names::compute_debuginfo_type_name; -use rustc_codegen_ssa::debuginfo::wants_c_like_enum_debuginfo; +use rustc_codegen_ssa::debuginfo::{tag_base_type, wants_c_like_enum_debuginfo}; use rustc_codegen_ssa::traits::ConstMethods; use rustc_middle::bug; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; @@ -11,7 +11,6 @@ use rustc_target::abi::{Size, TagEncoding, VariantIdx, Variants}; use smallvec::smallvec; use crate::common::CodegenCx; -use crate::debuginfo::metadata::enums::tag_base_type; use crate::debuginfo::metadata::type_map::{self, Stub, StubInfo, UniqueTypeId}; use crate::debuginfo::metadata::{ file_metadata, size_and_align_of, type_di_node, unknown_file_metadata, visibility_di_flags, @@ -54,7 +53,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( let visibility_flags = visibility_di_flags(cx, enum_adt_def.did(), enum_adt_def.did()); - assert!(!wants_c_like_enum_debuginfo(enum_type_and_layout)); + assert!(!wants_c_like_enum_debuginfo(cx.tcx, enum_type_and_layout)); type_map::build_type_with_children( cx, @@ -131,7 +130,7 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>( let containing_scope = get_namespace_for_item(cx, coroutine_def_id); let coroutine_type_and_layout = cx.layout_of(coroutine_type); - assert!(!wants_c_like_enum_debuginfo(coroutine_type_and_layout)); + assert!(!wants_c_like_enum_debuginfo(cx.tcx, coroutine_type_and_layout)); let coroutine_type_name = compute_debuginfo_type_name(cx.tcx, coroutine_type, false); @@ -321,7 +320,7 @@ fn build_discr_member_di_node<'ll, 'tcx>( &Variants::Single { .. } => None, &Variants::Multiple { tag_field, .. } => { - let tag_base_type = tag_base_type(cx, enum_or_coroutine_type_and_layout); + let tag_base_type = tag_base_type(cx.tcx, enum_or_coroutine_type_and_layout); let (size, align) = cx.size_and_align_of(tag_base_type); unsafe { diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs index 25b2df9c52c..6d21f4204e3 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs @@ -22,7 +22,7 @@ mod private { // `UniqueTypeId` from being constructed directly, without asserting // the preconditions. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, HashStable)] - pub struct HiddenZst; + pub(crate) struct HiddenZst; } /// A unique identifier for anything that we create a debuginfo node for. @@ -48,17 +48,17 @@ pub(super) enum UniqueTypeId<'tcx> { } impl<'tcx> UniqueTypeId<'tcx> { - pub fn for_ty(tcx: TyCtxt<'tcx>, t: Ty<'tcx>) -> Self { + pub(crate) fn for_ty(tcx: TyCtxt<'tcx>, t: Ty<'tcx>) -> Self { assert_eq!(t, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t)); UniqueTypeId::Ty(t, private::HiddenZst) } - pub fn for_enum_variant_part(tcx: TyCtxt<'tcx>, enum_ty: Ty<'tcx>) -> Self { + pub(crate) fn for_enum_variant_part(tcx: TyCtxt<'tcx>, enum_ty: Ty<'tcx>) -> Self { assert_eq!(enum_ty, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), enum_ty)); UniqueTypeId::VariantPart(enum_ty, private::HiddenZst) } - pub fn for_enum_variant_struct_type( + pub(crate) fn for_enum_variant_struct_type( tcx: TyCtxt<'tcx>, enum_ty: Ty<'tcx>, variant_idx: VariantIdx, @@ -67,7 +67,7 @@ impl<'tcx> UniqueTypeId<'tcx> { UniqueTypeId::VariantStructType(enum_ty, variant_idx, private::HiddenZst) } - pub fn for_enum_variant_struct_type_wrapper( + pub(crate) fn for_enum_variant_struct_type_wrapper( tcx: TyCtxt<'tcx>, enum_ty: Ty<'tcx>, variant_idx: VariantIdx, @@ -76,7 +76,7 @@ impl<'tcx> UniqueTypeId<'tcx> { UniqueTypeId::VariantStructTypeCppLikeWrapper(enum_ty, variant_idx, private::HiddenZst) } - pub fn for_vtable_ty( + pub(crate) fn for_vtable_ty( tcx: TyCtxt<'tcx>, self_type: Ty<'tcx>, implemented_trait: Option>, @@ -93,7 +93,7 @@ impl<'tcx> UniqueTypeId<'tcx> { /// argument of the various `LLVMRustDIBuilderCreate*Type()` methods. /// /// Right now this takes the form of a hex-encoded opaque hash value. - pub fn generate_unique_id_string(self, tcx: TyCtxt<'tcx>) -> String { + fn generate_unique_id_string(self, tcx: TyCtxt<'tcx>) -> String { let mut hasher = StableHasher::new(); tcx.with_stable_hashing_context(|mut hcx| { hcx.while_hashing_spans(false, |hcx| self.hash_stable(hcx, &mut hasher)) @@ -101,7 +101,7 @@ impl<'tcx> UniqueTypeId<'tcx> { hasher.finish::().to_hex() } - pub fn expect_ty(self) -> Ty<'tcx> { + pub(crate) fn expect_ty(self) -> Ty<'tcx> { match self { UniqueTypeId::Ty(ty, _) => ty, _ => bug!("Expected `UniqueTypeId::Ty` but found `{:?}`", self), @@ -133,25 +133,25 @@ impl<'ll, 'tcx> TypeMap<'ll, 'tcx> { } } -pub struct DINodeCreationResult<'ll> { +pub(crate) struct DINodeCreationResult<'ll> { pub di_node: &'ll DIType, pub already_stored_in_typemap: bool, } impl<'ll> DINodeCreationResult<'ll> { - pub fn new(di_node: &'ll DIType, already_stored_in_typemap: bool) -> Self { + pub(crate) fn new(di_node: &'ll DIType, already_stored_in_typemap: bool) -> Self { DINodeCreationResult { di_node, already_stored_in_typemap } } } #[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub enum Stub<'ll> { +pub(crate) enum Stub<'ll> { Struct, Union, VTableTy { vtable_holder: &'ll DIType }, } -pub struct StubInfo<'ll, 'tcx> { +pub(crate) struct StubInfo<'ll, 'tcx> { metadata: &'ll DIType, unique_type_id: UniqueTypeId<'tcx>, } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index b23e05182ca..f5d6fc6f080 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -40,13 +40,13 @@ use crate::llvm::debuginfo::{ use crate::value::Value; mod create_scope_map; -pub mod gdb; -pub mod metadata; +mod gdb; +pub(crate) mod metadata; mod namespace; mod utils; -pub use self::create_scope_map::compute_mir_scopes; -pub use self::metadata::build_global_var_di_node; +use self::create_scope_map::compute_mir_scopes; +pub(crate) use self::metadata::build_global_var_di_node; #[allow(non_upper_case_globals)] const DW_TAG_auto_variable: c_uint = 0x100; @@ -54,7 +54,7 @@ const DW_TAG_auto_variable: c_uint = 0x100; const DW_TAG_arg_variable: c_uint = 0x101; /// A context object for maintaining all state needed by the debuginfo module. -pub struct CodegenUnitDebugContext<'ll, 'tcx> { +pub(crate) struct CodegenUnitDebugContext<'ll, 'tcx> { llcontext: &'ll llvm::Context, llmod: &'ll llvm::Module, builder: &'ll mut DIBuilder<'ll>, @@ -74,7 +74,7 @@ impl Drop for CodegenUnitDebugContext<'_, '_> { } impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> { - pub fn new(llmod: &'ll llvm::Module) -> Self { + pub(crate) fn new(llmod: &'ll llvm::Module) -> Self { debug!("CodegenUnitDebugContext::new"); let builder = unsafe { llvm::LLVMRustDIBuilderCreate(llmod) }; // DIBuilder inherits context from the module, so we'd better use the same one @@ -90,7 +90,7 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> { } } - pub fn finalize(&self, sess: &Session) { + pub(crate) fn finalize(&self, sess: &Session) { unsafe { llvm::LLVMRustDIBuilderFinalize(self.builder); @@ -109,7 +109,7 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> { llvm::LLVMRustAddModuleFlagU32( self.llmod, llvm::LLVMModFlagBehavior::Warning, - c"Dwarf Version".as_ptr().cast(), + c"Dwarf Version".as_ptr(), dwarf_version, ); } else { @@ -117,7 +117,7 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> { llvm::LLVMRustAddModuleFlagU32( self.llmod, llvm::LLVMModFlagBehavior::Warning, - c"CodeView".as_ptr().cast(), + c"CodeView".as_ptr(), 1, ) } @@ -126,7 +126,7 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> { llvm::LLVMRustAddModuleFlagU32( self.llmod, llvm::LLVMModFlagBehavior::Warning, - c"Debug Info Version".as_ptr().cast(), + c"Debug Info Version".as_ptr(), llvm::LLVMRustDebugMetadataVersion(), ); } @@ -134,7 +134,7 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> { } /// Creates any deferred debug metadata nodes -pub fn finalize(cx: &CodegenCx<'_, '_>) { +pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { if let Some(dbg_cx) = &cx.dbg_cx { debug!("finalize"); @@ -241,13 +241,13 @@ impl<'ll> DebugInfoBuilderMethods for Builder<'_, 'll, '_> { // FIXME(eddyb) rename this to better indicate it's a duplicate of // `rustc_span::Loc` rather than `DILocation`, perhaps by making // `lookup_char_pos` return the right information instead. -pub struct DebugLoc { +struct DebugLoc { /// Information about the original source file. - pub file: Lrc, + file: Lrc, /// The (1-based) line number. - pub line: u32, + line: u32, /// The (1-based) column number. - pub col: u32, + col: u32, } impl CodegenCx<'_, '_> { @@ -255,7 +255,7 @@ impl CodegenCx<'_, '_> { // FIXME(eddyb) rename this to better indicate it's a duplicate of // `lookup_char_pos` rather than `dbg_loc`, perhaps by making // `lookup_char_pos` return the right information instead. - pub fn lookup_debug_loc(&self, pos: BytePos) -> DebugLoc { + fn lookup_debug_loc(&self, pos: BytePos) -> DebugLoc { let (file, line, col) = match self.sess().source_map().lookup_line(pos) { Ok(SourceFileAndLine { sf: file, line }) => { let line_pos = file.lines()[line]; @@ -570,7 +570,17 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { inlined_at: Option<&'ll DILocation>, span: Span, ) -> &'ll DILocation { - let DebugLoc { line, col, .. } = self.lookup_debug_loc(span.lo()); + // When emitting debugging information, DWARF (i.e. everything but MSVC) + // treats line 0 as a magic value meaning that the code could not be + // attributed to any line in the source. That's also exactly what dummy + // spans are. Make that equivalence here, rather than passing dummy spans + // to lookup_debug_loc, which will return line 1 for them. + let (line, col) = if span.is_dummy() && !self.sess().target.is_like_msvc { + (0, 0) + } else { + let DebugLoc { line, col, .. } = self.lookup_debug_loc(span.lo()); + (line, col) + }; unsafe { llvm::LLVMRustDIBuilderCreateDebugLocation(line, col, scope, inlined_at) } } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs b/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs index 5c4f8fe99e3..83d7a82dadc 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs @@ -9,7 +9,7 @@ use crate::common::CodegenCx; use crate::llvm; use crate::llvm::debuginfo::DIScope; -pub fn mangled_name_of_instance<'a, 'tcx>( +pub(crate) fn mangled_name_of_instance<'a, 'tcx>( cx: &CodegenCx<'a, 'tcx>, instance: Instance<'tcx>, ) -> ty::SymbolName<'tcx> { @@ -17,7 +17,7 @@ pub fn mangled_name_of_instance<'a, 'tcx>( tcx.symbol_name(instance) } -pub fn item_namespace<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope { +pub(crate) fn item_namespace<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope { if let Some(&scope) = debug_context(cx).namespace_map.borrow().get(&def_id) { return scope; } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs index e542aa96e8a..321553a3df0 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs @@ -11,7 +11,7 @@ use crate::common::CodegenCx; use crate::llvm; use crate::llvm::debuginfo::{DIArray, DIBuilder, DIDescriptor, DIScope}; -pub fn is_node_local_to_unit(cx: &CodegenCx<'_, '_>, def_id: DefId) -> bool { +pub(crate) fn is_node_local_to_unit(cx: &CodegenCx<'_, '_>, def_id: DefId) -> bool { // The is_local_to_unit flag indicates whether a function is local to the // current compilation unit (i.e., if it is *static* in the C-sense). The // *reachable* set should provide a good approximation of this, as it @@ -24,7 +24,7 @@ pub fn is_node_local_to_unit(cx: &CodegenCx<'_, '_>, def_id: DefId) -> bool { } #[allow(non_snake_case)] -pub fn create_DIArray<'ll>( +pub(crate) fn create_DIArray<'ll>( builder: &DIBuilder<'ll>, arr: &[Option<&'ll DIDescriptor>], ) -> &'ll DIArray { @@ -32,7 +32,7 @@ pub fn create_DIArray<'ll>( } #[inline] -pub fn debug_context<'a, 'll, 'tcx>( +pub(crate) fn debug_context<'a, 'll, 'tcx>( cx: &'a CodegenCx<'ll, 'tcx>, ) -> &'a CodegenUnitDebugContext<'ll, 'tcx> { cx.dbg_cx.as_ref().unwrap() @@ -40,11 +40,11 @@ pub fn debug_context<'a, 'll, 'tcx>( #[inline] #[allow(non_snake_case)] -pub fn DIB<'a, 'll>(cx: &'a CodegenCx<'ll, '_>) -> &'a DIBuilder<'ll> { +pub(crate) fn DIB<'a, 'll>(cx: &'a CodegenCx<'ll, '_>) -> &'a DIBuilder<'ll> { cx.dbg_cx.as_ref().unwrap().builder } -pub fn get_namespace_for_item<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope { +pub(crate) fn get_namespace_for_item<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope { item_namespace(cx, cx.tcx.parent(def_id)) } diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs index 2aa349b2782..4e4500b6373 100644 --- a/compiler/rustc_codegen_llvm/src/declare.rs +++ b/compiler/rustc_codegen_llvm/src/declare.rs @@ -65,7 +65,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { /// /// If there’s a value with the same name already declared, the function will /// return its Value instead. - pub fn declare_global(&self, name: &str, ty: &'ll Type) -> &'ll Value { + pub(crate) fn declare_global(&self, name: &str, ty: &'ll Type) -> &'ll Value { debug!("declare_global(name={:?})", name); unsafe { llvm::LLVMRustGetOrInsertGlobal(self.llmod, name.as_ptr().cast(), name.len(), ty) } } @@ -77,7 +77,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { /// /// If there’s a value with the same name already declared, the function will /// update the declaration and return existing Value instead. - pub fn declare_cfn( + pub(crate) fn declare_cfn( &self, name: &str, unnamed: llvm::UnnamedAddr, @@ -100,7 +100,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { /// /// If there’s a value with the same name already declared, the function will /// update the declaration and return existing Value instead. - pub fn declare_entry_fn( + pub(crate) fn declare_entry_fn( &self, name: &str, callconv: llvm::CallConv, @@ -119,7 +119,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { /// /// If there’s a value with the same name already declared, the function will /// update the declaration and return existing Value instead. - pub fn declare_fn( + pub(crate) fn declare_fn( &self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, @@ -199,7 +199,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { /// return `None` if the name already has a definition associated with it. In that /// case an error should be reported to the user, because it usually happens due /// to user’s fault (e.g., misuse of `#[no_mangle]` or `#[export_name]` attributes). - pub fn define_global(&self, name: &str, ty: &'ll Type) -> Option<&'ll Value> { + pub(crate) fn define_global(&self, name: &str, ty: &'ll Type) -> Option<&'ll Value> { if self.get_defined_value(name).is_some() { None } else { @@ -210,19 +210,19 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { /// Declare a private global /// /// Use this function when you intend to define a global without a name. - pub fn define_private_global(&self, ty: &'ll Type) -> &'ll Value { + pub(crate) fn define_private_global(&self, ty: &'ll Type) -> &'ll Value { unsafe { llvm::LLVMRustInsertPrivateGlobal(self.llmod, ty) } } /// Gets declared value by name. - pub fn get_declared_value(&self, name: &str) -> Option<&'ll Value> { + pub(crate) fn get_declared_value(&self, name: &str) -> Option<&'ll Value> { debug!("get_declared_value(name={:?})", name); unsafe { llvm::LLVMRustGetNamedValue(self.llmod, name.as_ptr().cast(), name.len()) } } /// Gets defined or externally defined (AvailableExternally linkage) value by /// name. - pub fn get_defined_value(&self, name: &str) -> Option<&'ll Value> { + pub(crate) fn get_defined_value(&self, name: &str) -> Option<&'ll Value> { self.get_declared_value(name).and_then(|val| { let declaration = unsafe { llvm::LLVMIsDeclaration(val) != 0 }; if !declaration { Some(val) } else { None } diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 7e53d32ce8c..bb481d2a308 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -39,13 +39,6 @@ pub(crate) enum PossibleFeature<'a> { None, } -#[derive(Diagnostic)] -#[diag(codegen_llvm_error_creating_import_library)] -pub(crate) struct ErrorCreatingImportLibrary<'a> { - pub lib_name: &'a str, - pub error: String, -} - #[derive(Diagnostic)] #[diag(codegen_llvm_symbol_already_defined)] pub(crate) struct SymbolAlreadyDefined<'a> { @@ -214,13 +207,13 @@ pub(crate) struct CopyBitcode { #[derive(Diagnostic)] #[diag(codegen_llvm_unknown_debuginfo_compression)] -pub struct UnknownCompression { +pub(crate) struct UnknownCompression { pub algorithm: &'static str, } #[derive(Diagnostic)] #[diag(codegen_llvm_mismatch_data_layout)] -pub struct MismatchedDataLayout<'a> { +pub(crate) struct MismatchedDataLayout<'a> { pub rustc_target: &'a str, pub rustc_layout: &'a str, pub llvm_target: &'a str, diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index f5558723d11..a300f5f707a 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -192,14 +192,22 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> { } sym::is_val_statically_known => { let intrinsic_type = args[0].layout.immediate_llvm_type(self.cx); - match self.type_kind(intrinsic_type) { - TypeKind::Pointer | TypeKind::Integer | TypeKind::Float | TypeKind::Double => { - self.call_intrinsic( - &format!("llvm.is.constant.{:?}", intrinsic_type), - &[args[0].immediate()], - ) + let kind = self.type_kind(intrinsic_type); + let intrinsic_name = match kind { + TypeKind::Pointer | TypeKind::Integer => { + Some(format!("llvm.is.constant.{intrinsic_type:?}")) } - _ => self.const_bool(false), + // LLVM float types' intrinsic names differ from their type names. + TypeKind::Half => Some(format!("llvm.is.constant.f16")), + TypeKind::Float => Some(format!("llvm.is.constant.f32")), + TypeKind::Double => Some(format!("llvm.is.constant.f64")), + TypeKind::FP128 => Some(format!("llvm.is.constant.f128")), + _ => None, + }; + if let Some(intrinsic_name) = intrinsic_name { + self.call_intrinsic(&intrinsic_name, &[args[0].immediate()]) + } else { + self.const_bool(false) } } sym::unlikely => self @@ -1279,19 +1287,24 @@ fn generic_simd_intrinsic<'ll, 'tcx>( } if name == sym::simd_shuffle { - // Make sure this is actually an array, since typeck only checks the length-suffixed + // Make sure this is actually an array or SIMD vector, since typeck only checks the length-suffixed // version of this intrinsic. - let n: u64 = match args[2].layout.ty.kind() { + let idx_ty = args[2].layout.ty; + let n: u64 = match idx_ty.kind() { ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => { len.try_eval_target_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else( || span_bug!(span, "could not evaluate shuffle index array length"), ) } - _ => return_error!(InvalidMonomorphization::SimdShuffle { - span, - name, - ty: args[2].layout.ty - }), + _ if idx_ty.is_simd() + && matches!( + idx_ty.simd_size_and_type(bx.cx.tcx).1.kind(), + ty::Uint(ty::UintTy::U32) + ) => + { + idx_ty.simd_size_and_type(bx.cx.tcx).0 + } + _ => return_error!(InvalidMonomorphization::SimdShuffle { span, name, ty: idx_ty }), }; let (out_len, out_ty) = require_simd!(ret_ty, SimdReturn); diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 43164390a1c..6a303e1e602 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -6,6 +6,7 @@ // tidy-alphabetical-start #![allow(internal_features)] +#![cfg_attr(bootstrap, feature(unsafe_extern_blocks))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(assert_matches)] @@ -16,6 +17,7 @@ #![feature(iter_intersperse)] #![feature(let_chains)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use std::any::Any; @@ -45,11 +47,11 @@ use rustc_session::Session; use rustc_span::symbol::Symbol; mod back { - pub mod archive; - pub mod lto; - pub mod owned_target_machine; + pub(crate) mod archive; + pub(crate) mod lto; + pub(crate) mod owned_target_machine; mod profiling; - pub mod write; + pub(crate) mod write; } mod abi; diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index faabbcb020d..5e0d7418993 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -564,12 +564,12 @@ pub enum ArchiveKind { } // LLVMRustThinLTOData -extern "C" { +unsafe extern "C" { pub type ThinLTOData; } // LLVMRustThinLTOBuffer -extern "C" { +unsafe extern "C" { pub type ThinLTOBuffer; } @@ -621,7 +621,7 @@ pub enum MemoryEffects { InaccessibleMemOnly, } -extern "C" { +unsafe extern "C" { type Opaque; } #[repr(C)] @@ -631,54 +631,54 @@ struct InvariantOpaque<'a> { } // Opaque pointer types -extern "C" { +unsafe extern "C" { pub type Module; } -extern "C" { +unsafe extern "C" { pub type Context; } -extern "C" { +unsafe extern "C" { pub type Type; } -extern "C" { +unsafe extern "C" { pub type Value; } -extern "C" { +unsafe extern "C" { pub type ConstantInt; } -extern "C" { +unsafe extern "C" { pub type Attribute; } -extern "C" { +unsafe extern "C" { pub type Metadata; } -extern "C" { +unsafe extern "C" { pub type BasicBlock; } #[repr(C)] pub struct Builder<'a>(InvariantOpaque<'a>); #[repr(C)] pub struct PassManager<'a>(InvariantOpaque<'a>); -extern "C" { +unsafe extern "C" { pub type Pass; } -extern "C" { +unsafe extern "C" { pub type TargetMachine; } -extern "C" { +unsafe extern "C" { pub type Archive; } #[repr(C)] pub struct ArchiveIterator<'a>(InvariantOpaque<'a>); #[repr(C)] pub struct ArchiveChild<'a>(InvariantOpaque<'a>); -extern "C" { +unsafe extern "C" { pub type Twine; } -extern "C" { +unsafe extern "C" { pub type DiagnosticInfo; } -extern "C" { +unsafe extern "C" { pub type SMDiagnostic; } #[repr(C)] @@ -688,7 +688,7 @@ pub struct OperandBundleDef<'a>(InvariantOpaque<'a>); #[repr(C)] pub struct Linker<'a>(InvariantOpaque<'a>); -extern "C" { +unsafe extern "C" { pub type DiagnosticHandler; } @@ -823,7 +823,7 @@ bitflags! { } } -extern "C" { +unsafe extern "C" { pub type ModuleBuffer; } @@ -834,7 +834,7 @@ pub type SelfProfileAfterPassCallback = unsafe extern "C" fn(*mut c_void); pub type GetSymbolsCallback = unsafe extern "C" fn(*mut c_void, *const c_char) -> *mut c_void; pub type GetSymbolsErrorCallback = unsafe extern "C" fn(*const c_char) -> *mut c_void; -extern "C" { +unsafe extern "C" { // Create and destroy contexts. pub fn LLVMContextDispose(C: &'static mut Context); pub fn LLVMGetMDKindIDInContext(C: &Context, Name: *const c_char, SLen: c_uint) -> c_uint; @@ -1518,7 +1518,7 @@ extern "C" { } #[link(name = "llvm-wrapper", kind = "static")] -extern "C" { +unsafe extern "C" { pub fn LLVMRustInstallErrorHandlers(); pub fn LLVMRustDisableSystemDialogsOnCrash(); @@ -1860,6 +1860,8 @@ extern "C" { CSKind: ChecksumKind, Checksum: *const c_char, ChecksumLen: size_t, + Source: *const c_char, + SourceLen: size_t, ) -> &'a DIFile; pub fn LLVMRustDIBuilderCreateSubroutineType<'a>( diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 9fd8ca43789..618602ed70f 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -136,14 +136,14 @@ unsafe fn configure_llvm(sess: &Session) { unsafe { llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int, llvm_args.as_ptr()) }; } -pub fn time_trace_profiler_finish(file_name: &Path) { +pub(crate) fn time_trace_profiler_finish(file_name: &Path) { unsafe { let file_name = path_to_c_string(file_name); llvm::LLVMRustTimeTraceProfilerFinish(file_name.as_ptr()); } } -pub enum TargetFeatureFoldStrength<'a> { +enum TargetFeatureFoldStrength<'a> { // The feature is only tied when enabling the feature, disabling // this feature shouldn't disable the tied feature. EnableOnly(&'a str), @@ -160,28 +160,28 @@ impl<'a> TargetFeatureFoldStrength<'a> { } } -pub struct LLVMFeature<'a> { - pub llvm_feature_name: &'a str, - pub dependency: Option>, +pub(crate) struct LLVMFeature<'a> { + llvm_feature_name: &'a str, + dependency: Option>, } impl<'a> LLVMFeature<'a> { - pub fn new(llvm_feature_name: &'a str) -> Self { + fn new(llvm_feature_name: &'a str) -> Self { Self { llvm_feature_name, dependency: None } } - pub fn with_dependency( + fn with_dependency( llvm_feature_name: &'a str, dependency: TargetFeatureFoldStrength<'a>, ) -> Self { Self { llvm_feature_name, dependency: Some(dependency) } } - pub fn contains(&self, feat: &str) -> bool { + fn contains(&self, feat: &str) -> bool { self.iter().any(|dep| dep == feat) } - pub fn iter(&'a self) -> impl Iterator { + fn iter(&'a self) -> impl Iterator { let dependencies = self.dependency.iter().map(|feat| feat.as_str()); std::iter::once(self.llvm_feature_name).chain(dependencies) } @@ -209,7 +209,7 @@ impl<'a> IntoIterator for LLVMFeature<'a> { // Though note that Rust can also be build with an external precompiled version of LLVM // which might lead to failures if the oldest tested / supported LLVM version // doesn't yet support the relevant intrinsics -pub fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> LLVMFeature<'a> { +pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option> { let arch = if sess.target.arch == "x86_64" { "x86" } else if sess.target.arch == "arm64ec" { @@ -218,46 +218,65 @@ pub fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> LLVMFeature<'a> { &*sess.target.arch }; match (arch, s) { - ("x86", "sse4.2") => { - LLVMFeature::with_dependency("sse4.2", TargetFeatureFoldStrength::EnableOnly("crc32")) - } - ("x86", "pclmulqdq") => LLVMFeature::new("pclmul"), - ("x86", "rdrand") => LLVMFeature::new("rdrnd"), - ("x86", "bmi1") => LLVMFeature::new("bmi"), - ("x86", "cmpxchg16b") => LLVMFeature::new("cx16"), - ("x86", "lahfsahf") => LLVMFeature::new("sahf"), - ("aarch64", "rcpc2") => LLVMFeature::new("rcpc-immo"), - ("aarch64", "dpb") => LLVMFeature::new("ccpp"), - ("aarch64", "dpb2") => LLVMFeature::new("ccdp"), - ("aarch64", "frintts") => LLVMFeature::new("fptoint"), - ("aarch64", "fcma") => LLVMFeature::new("complxnum"), - ("aarch64", "pmuv3") => LLVMFeature::new("perfmon"), - ("aarch64", "paca") => LLVMFeature::new("pauth"), - ("aarch64", "pacg") => LLVMFeature::new("pauth"), + ("x86", "sse4.2") => Some(LLVMFeature::with_dependency( + "sse4.2", + TargetFeatureFoldStrength::EnableOnly("crc32"), + )), + ("x86", "pclmulqdq") => Some(LLVMFeature::new("pclmul")), + ("x86", "rdrand") => Some(LLVMFeature::new("rdrnd")), + ("x86", "bmi1") => Some(LLVMFeature::new("bmi")), + ("x86", "cmpxchg16b") => Some(LLVMFeature::new("cx16")), + ("x86", "lahfsahf") => Some(LLVMFeature::new("sahf")), + ("aarch64", "rcpc2") => Some(LLVMFeature::new("rcpc-immo")), + ("aarch64", "dpb") => Some(LLVMFeature::new("ccpp")), + ("aarch64", "dpb2") => Some(LLVMFeature::new("ccdp")), + ("aarch64", "frintts") => Some(LLVMFeature::new("fptoint")), + ("aarch64", "fcma") => Some(LLVMFeature::new("complxnum")), + ("aarch64", "pmuv3") => Some(LLVMFeature::new("perfmon")), + ("aarch64", "paca") => Some(LLVMFeature::new("pauth")), + ("aarch64", "pacg") => Some(LLVMFeature::new("pauth")), + ("aarch64", "sve-b16b16") => Some(LLVMFeature::new("b16b16")), + ("aarch64", "flagm2") => Some(LLVMFeature::new("altnzcv")), // Rust ties fp and neon together. ("aarch64", "neon") => { - LLVMFeature::with_dependency("neon", TargetFeatureFoldStrength::Both("fp-armv8")) + Some(LLVMFeature::with_dependency("neon", TargetFeatureFoldStrength::Both("fp-armv8"))) } // In LLVM neon implicitly enables fp, but we manually enable // neon when a feature only implicitly enables fp - ("aarch64", "fhm") => LLVMFeature::new("fp16fml"), - ("aarch64", "fp16") => LLVMFeature::new("fullfp16"), + ("aarch64", "fhm") => Some(LLVMFeature::new("fp16fml")), + ("aarch64", "fp16") => Some(LLVMFeature::new("fullfp16")), + // Filter out features that are not supported by the current LLVM version + ("aarch64", "faminmax") if get_version().0 < 18 => None, + ("aarch64", "fp8") if get_version().0 < 18 => None, + ("aarch64", "fp8dot2") if get_version().0 < 18 => None, + ("aarch64", "fp8dot4") if get_version().0 < 18 => None, + ("aarch64", "fp8fma") if get_version().0 < 18 => None, + ("aarch64", "fpmr") if get_version().0 != 18 => None, + ("aarch64", "lut") if get_version().0 < 18 => None, + ("aarch64", "sme-f8f16") if get_version().0 < 18 => None, + ("aarch64", "sme-f8f32") if get_version().0 < 18 => None, + ("aarch64", "sme-fa64") if get_version().0 < 18 => None, + ("aarch64", "sme-lutv2") if get_version().0 < 18 => None, + ("aarch64", "ssve-fp8dot2") if get_version().0 < 18 => None, + ("aarch64", "ssve-fp8dot4") if get_version().0 < 18 => None, + ("aarch64", "ssve-fp8fma") if get_version().0 < 18 => None, + ("aarch64", "v9.5a") if get_version().0 < 18 => None, // In LLVM 18, `unaligned-scalar-mem` was merged with `unaligned-vector-mem` into a single feature called // `fast-unaligned-access`. In LLVM 19, it was split back out. ("riscv32" | "riscv64", "unaligned-scalar-mem") if get_version().0 == 18 => { - LLVMFeature::new("fast-unaligned-access") + Some(LLVMFeature::new("fast-unaligned-access")) } // For LLVM 18, enable the evex512 target feature if a avx512 target feature is enabled. ("x86", s) if get_version().0 >= 18 && s.starts_with("avx512") => { - LLVMFeature::with_dependency(s, TargetFeatureFoldStrength::EnableOnly("evex512")) + Some(LLVMFeature::with_dependency(s, TargetFeatureFoldStrength::EnableOnly("evex512"))) } - (_, s) => LLVMFeature::new(s), + (_, s) => Some(LLVMFeature::new(s)), } } /// Given a map from target_features to whether they are enabled or disabled, /// ensure only valid combinations are allowed. -pub fn check_tied_features( +pub(crate) fn check_tied_features( sess: &Session, features: &FxHashMap<&str, bool>, ) -> Option<&'static [&'static str]> { @@ -291,13 +310,17 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec { return true; } // check that all features in a given smallvec are enabled - for llvm_feature in to_llvm_features(sess, feature) { - let cstr = SmallCStr::new(llvm_feature); - if !unsafe { llvm::LLVMRustHasFeature(&target_machine, cstr.as_ptr()) } { - return false; + if let Some(feat) = to_llvm_features(sess, feature) { + for llvm_feature in feat { + let cstr = SmallCStr::new(llvm_feature); + if !unsafe { llvm::LLVMRustHasFeature(&target_machine, cstr.as_ptr()) } { + return false; + } } + true + } else { + false } - true }) .map(|(feature, _, _)| Symbol::intern(feature)), ); @@ -337,19 +360,19 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec { .collect() } -pub fn print_version() { +pub(crate) fn print_version() { let (major, minor, patch) = get_version(); println!("LLVM version: {major}.{minor}.{patch}"); } -pub fn get_version() -> (u32, u32, u32) { +pub(crate) fn get_version() -> (u32, u32, u32) { // Can be called without initializing LLVM unsafe { (llvm::LLVMRustVersionMajor(), llvm::LLVMRustVersionMinor(), llvm::LLVMRustVersionPatch()) } } -pub fn print_passes() { +pub(crate) fn print_passes() { // Can be called without initializing LLVM unsafe { llvm::LLVMRustPrintPasses(); @@ -386,9 +409,9 @@ fn print_target_features(out: &mut String, sess: &Session, tm: &llvm::TargetMach .target .supported_target_features() .iter() - .map(|(feature, _gate, _implied)| { + .filter_map(|(feature, _gate, _implied)| { // LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these strings. - let llvm_feature = to_llvm_features(sess, *feature).llvm_feature_name; + let llvm_feature = to_llvm_features(sess, *feature)?.llvm_feature_name; let desc = match llvm_target_features.binary_search_by_key(&llvm_feature, |(f, _d)| f).ok() { Some(index) => { @@ -398,7 +421,7 @@ fn print_target_features(out: &mut String, sess: &Session, tm: &llvm::TargetMach None => "", }; - (*feature, desc) + Some((*feature, desc)) }) .collect::>(); @@ -479,7 +502,7 @@ fn handle_native(name: &str) -> &str { } } -pub fn target_cpu(sess: &Session) -> &str { +pub(crate) fn target_cpu(sess: &Session) -> &str { match sess.opts.cg.target_cpu { Some(ref name) => handle_native(name), None => handle_native(sess.target.cpu.as_ref()), @@ -595,7 +618,7 @@ pub(crate) fn global_llvm_features( if feature_state.is_none() { let rust_feature = supported_features.iter().find_map(|&(rust_feature, _, _)| { - let llvm_features = to_llvm_features(sess, rust_feature); + let llvm_features = to_llvm_features(sess, rust_feature)?; if llvm_features.contains(feature) && !llvm_features.contains(rust_feature) { @@ -641,7 +664,7 @@ pub(crate) fn global_llvm_features( // passing requests down to LLVM. This means that all in-language // features also work on the command line instead of having two // different names when the LLVM name and the Rust name differ. - let llvm_feature = to_llvm_features(sess, feature); + let llvm_feature = to_llvm_features(sess, feature)?; Some( std::iter::once(format!( @@ -691,6 +714,9 @@ fn backend_feature_name<'a>(sess: &Session, s: &'a str) -> Option<&'a str> { let feature = s .strip_prefix(&['+', '-'][..]) .unwrap_or_else(|| sess.dcx().emit_fatal(InvalidTargetFeaturePrefix { feature: s })); + if s.is_empty() { + return None; + } // Rustc-specific feature requests like `+crt-static` or `-crt-static` // are not passed down to LLVM. if RUSTC_SPECIFIC_FEATURES.contains(&feature) { @@ -699,7 +725,7 @@ fn backend_feature_name<'a>(sess: &Session, s: &'a str) -> Option<&'a str> { Some(feature) } -pub fn tune_cpu(sess: &Session) -> Option<&str> { +pub(crate) fn tune_cpu(sess: &Session) -> Option<&str> { let name = sess.opts.unstable_opts.tune_cpu.as_ref()?; Some(handle_native(name)) } diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs index 7e3ab19898d..ec1e2cb8094 100644 --- a/compiler/rustc_codegen_llvm/src/type_.rs +++ b/compiler/rustc_codegen_llvm/src/type_.rs @@ -12,7 +12,7 @@ use rustc_target::abi::{AddressSpace, Align, Integer, Size}; use crate::abi::{FnAbiLlvmExt, LlvmType}; use crate::context::CodegenCx; -pub use crate::llvm::Type; +pub(crate) use crate::llvm::Type; use crate::llvm::{Bool, False, True}; use crate::type_of::LayoutLlvmExt; use crate::value::Value; diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs index 4755fa08afb..6e429a1674a 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs @@ -139,21 +139,21 @@ fn struct_llfields<'a, 'tcx>( } impl<'a, 'tcx> CodegenCx<'a, 'tcx> { - pub fn align_of(&self, ty: Ty<'tcx>) -> Align { + pub(crate) fn align_of(&self, ty: Ty<'tcx>) -> Align { self.layout_of(ty).align.abi } - pub fn size_of(&self, ty: Ty<'tcx>) -> Size { + pub(crate) fn size_of(&self, ty: Ty<'tcx>) -> Size { self.layout_of(ty).size } - pub fn size_and_align_of(&self, ty: Ty<'tcx>) -> (Size, Align) { + pub(crate) fn size_and_align_of(&self, ty: Ty<'tcx>) -> (Size, Align) { let layout = self.layout_of(ty); (layout.size, layout.align.abi) } } -pub trait LayoutLlvmExt<'tcx> { +pub(crate) trait LayoutLlvmExt<'tcx> { fn is_llvm_immediate(&self) -> bool; fn is_llvm_scalar_pair(&self) -> bool; fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type; diff --git a/compiler/rustc_codegen_llvm/src/value.rs b/compiler/rustc_codegen_llvm/src/value.rs index 6295b0de356..2eabac3be8c 100644 --- a/compiler/rustc_codegen_llvm/src/value.rs +++ b/compiler/rustc_codegen_llvm/src/value.rs @@ -2,7 +2,7 @@ use std::hash::{Hash, Hasher}; use std::{fmt, ptr}; use crate::llvm; -pub use crate::llvm::Value; +pub(crate) use crate::llvm::Value; impl PartialEq for Value { fn eq(&self, other: &Self) -> bool { diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 6e1c323cbd0..e78039bafd8 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -5,10 +5,10 @@ edition = "2021" [dependencies] # tidy-alphabetical-start -ar_archive_writer = "0.3.3" +ar_archive_writer = "0.4.2" arrayvec = { version = "0.7", default-features = false } bitflags = "2.4.1" -cc = "1.0.90" +cc = "=1.0.105" # FIXME(cc): pinned to keep support for VS2013 either = "1.5.0" itertools = "0.12" jobserver = "0.1.28" @@ -41,7 +41,7 @@ tempfile = "3.2" thin-vec = "0.2.12" thorin-dwp = "0.7" tracing = "0.1" -wasm-encoder = "0.210.0" +wasm-encoder = "0.215.0" # tidy-alphabetical-end [target.'cfg(unix)'.dependencies] diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index 80f25d42a08..8a6a2acd87d 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -32,6 +32,9 @@ codegen_ssa_dlltool_fail_import_library = codegen_ssa_error_calling_dlltool = Error calling dlltool '{$dlltool_path}': {$error} +codegen_ssa_error_creating_import_library = + Error creating import library for {$lib_name}: {$error} + codegen_ssa_error_creating_remark_dir = failed to create remark directory: {$error} codegen_ssa_error_writing_def_file = diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index ce55d99f506..76a94de5433 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -5,7 +5,9 @@ use std::fs::{self, File}; use std::io::{self, Write}; use std::path::{Path, PathBuf}; -use ar_archive_writer::{write_archive_to_stream, ArchiveKind, NewArchiveMember}; +use ar_archive_writer::{ + write_archive_to_stream, ArchiveKind, COFFShortExport, MachineTypes, NewArchiveMember, +}; pub use ar_archive_writer::{ObjectReader, DEFAULT_OBJECT_READER}; use object::read::archive::ArchiveFile; use object::read::macho::FatArch; @@ -14,11 +16,15 @@ use rustc_data_structures::memmap::Mmap; use rustc_session::Session; use rustc_span::symbol::Symbol; use tempfile::Builder as TempFileBuilder; +use tracing::trace; use super::metadata::search_for_section; +use crate::common; // Re-exporting for rustc_codegen_llvm::back::archive pub use crate::errors::{ArchiveBuildFailure, ExtractBundledLibsError, UnknownArchiveKind}; -use crate::errors::{DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorWritingDEFFile}; +use crate::errors::{ + DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorCreatingImportLibrary, ErrorWritingDEFFile, +}; pub trait ArchiveBuilderBuilder { fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box; @@ -34,14 +40,92 @@ pub trait ArchiveBuilderBuilder { lib_name: &str, import_name_and_ordinal_vector: Vec<(String, Option)>, output_path: &Path, - ); + ) { + if common::is_mingw_gnu_toolchain(&sess.target) { + // The binutils linker used on -windows-gnu targets cannot read the import + // libraries generated by LLVM: in our attempts, the linker produced an .EXE + // that loaded but crashed with an AV upon calling one of the imported + // functions. Therefore, use binutils to create the import library instead, + // by writing a .DEF file to the temp dir and calling binutils's dlltool. + create_mingw_dll_import_lib( + sess, + lib_name, + import_name_and_ordinal_vector, + output_path, + ); + } else { + trace!("creating import library"); + trace!(" dll_name {:#?}", lib_name); + trace!(" output_path {}", output_path.display()); + trace!( + " import names: {}", + import_name_and_ordinal_vector + .iter() + .map(|(name, _ordinal)| name.clone()) + .collect::>() + .join(", "), + ); + + // All import names are Rust identifiers and therefore cannot contain \0 characters. + // FIXME: when support for #[link_name] is implemented, ensure that the import names + // still don't contain any \0 characters. Also need to check that the names don't + // contain substrings like " @" or "NONAME" that are keywords or otherwise reserved + // in definition files. + + let mut file = match fs::File::create_new(&output_path) { + Ok(file) => file, + Err(error) => sess + .dcx() + .emit_fatal(ErrorCreatingImportLibrary { lib_name, error: error.to_string() }), + }; + + let exports = import_name_and_ordinal_vector + .iter() + .map(|(name, ordinal)| COFFShortExport { + name: name.to_string(), + ext_name: None, + symbol_name: None, + alias_target: None, + ordinal: ordinal.unwrap_or(0), + noname: ordinal.is_some(), + data: false, + private: false, + constant: false, + }) + .collect::>(); + let machine = match &*sess.target.arch { + "x86_64" => MachineTypes::AMD64, + "x86" => MachineTypes::I386, + "aarch64" => MachineTypes::ARM64, + "arm64ec" => MachineTypes::ARM64EC, + "arm" => MachineTypes::ARMNT, + cpu => panic!("unsupported cpu type {cpu}"), + }; + + if let Err(error) = ar_archive_writer::write_import_library( + &mut file, + lib_name, + &exports, + machine, + !sess.target.is_like_msvc, + // Enable compatibility with MSVC's `/WHOLEARCHIVE` flag. + // Without this flag a duplicate symbol error would be emitted + // when linking a rust staticlib using `/WHOLEARCHIVE`. + // See #129020 + true, + ) { + sess.dcx() + .emit_fatal(ErrorCreatingImportLibrary { lib_name, error: error.to_string() }); + } + } + } fn extract_bundled_libs<'a>( &'a self, rlib: &'a Path, outdir: &Path, bundled_lib_file_names: &FxIndexSet, - ) -> Result<(), ExtractBundledLibsError<'_>> { + ) -> Result<(), ExtractBundledLibsError<'a>> { let archive_map = unsafe { Mmap::map( File::open(rlib) @@ -307,10 +391,15 @@ impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> { let file_name = String::from_utf8(entry.name().to_vec()) .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?; if !skip(&file_name) { - self.entries.push(( - file_name.into_bytes(), - ArchiveEntry::FromArchive { archive_index, file_range: entry.file_range() }, - )); + if entry.is_thin() { + let member_path = archive_path.parent().unwrap().join(Path::new(&file_name)); + self.entries.push((file_name.into_bytes(), ArchiveEntry::File(member_path))); + } else { + self.entries.push(( + file_name.into_bytes(), + ArchiveEntry::FromArchive { archive_index, file_range: entry.file_range() }, + )); + } } } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 7bad9d33e7d..4d19425255f 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1207,7 +1207,7 @@ mod win { /// Get the Windows system OEM code page. This is most notably the code page /// used for link.exe's output. - pub fn oem_code_page() -> u32 { + pub(super) fn oem_code_page() -> u32 { unsafe { let mut cp: u32 = 0; // We're using the `LOCALE_RETURN_NUMBER` flag to return a u32. @@ -1230,7 +1230,7 @@ mod win { /// /// It will fail if the multi-byte string is longer than `i32::MAX` or if it contains /// any invalid bytes for the expected encoding. - pub fn locale_byte_str_to_string(s: &[u8], code_page: u32) -> Option { + pub(super) fn locale_byte_str_to_string(s: &[u8], code_page: u32) -> Option { // `MultiByteToWideChar` requires a length to be a "positive integer". if s.len() > isize::MAX as usize { return None; @@ -1317,11 +1317,9 @@ fn link_sanitizer_runtime( name: &str, ) { fn find_sanitizer_runtime(sess: &Session, filename: &str) -> PathBuf { - let session_tlib = - filesearch::make_target_lib_path(&sess.sysroot, sess.opts.target_triple.triple()); - let path = session_tlib.join(filename); + let path = sess.target_tlib_path.dir.join(filename); if path.exists() { - return session_tlib; + return sess.target_tlib_path.dir.clone(); } else { let default_sysroot = filesearch::get_or_default_sysroot().expect("Failed finding sysroot"); @@ -1612,19 +1610,18 @@ fn print_native_static_libs( } fn get_object_file_path(sess: &Session, name: &str, self_contained: bool) -> PathBuf { - let fs = sess.target_filesearch(PathKind::Native); - let file_path = fs.get_lib_path().join(name); + let file_path = sess.target_tlib_path.dir.join(name); if file_path.exists() { return file_path; } // Special directory with objects used only in self-contained linkage mode if self_contained { - let file_path = fs.get_self_contained_lib_path().join(name); + let file_path = sess.target_tlib_path.dir.join("self-contained").join(name); if file_path.exists() { return file_path; } } - for search_path in fs.search_paths() { + for search_path in sess.target_filesearch(PathKind::Native).search_paths() { let file_path = search_path.dir.join(name); if file_path.exists() { return file_path; @@ -2131,7 +2128,7 @@ fn add_library_search_dirs( | LinkSelfContainedComponents::UNWIND | LinkSelfContainedComponents::MINGW, ) { - let lib_path = sess.target_filesearch(PathKind::Native).get_self_contained_lib_path(); + let lib_path = sess.target_tlib_path.dir.join("self-contained"); cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path)); } @@ -2146,8 +2143,7 @@ fn add_library_search_dirs( || sess.target.os == "fuchsia" || sess.target.is_like_osx && !sess.opts.unstable_opts.sanitizer.is_empty() { - let lib_path = sess.target_filesearch(PathKind::Native).get_lib_path(); - cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path)); + cmd.include_path(&fix_windows_verbatim_for_gcc(&sess.target_tlib_path.dir)); } // Mac Catalyst uses the macOS SDK, but to link to iOS-specific frameworks @@ -2859,15 +2855,14 @@ fn add_upstream_native_libraries( // // The returned path will always have `fix_windows_verbatim_for_gcc()` applied to it. fn rehome_sysroot_lib_dir(sess: &Session, lib_dir: &Path) -> PathBuf { - let sysroot_lib_path = sess.target_filesearch(PathKind::All).get_lib_path(); + let sysroot_lib_path = &sess.target_tlib_path.dir; let canonical_sysroot_lib_path = - { try_canonicalize(&sysroot_lib_path).unwrap_or_else(|_| sysroot_lib_path.clone()) }; + { try_canonicalize(sysroot_lib_path).unwrap_or_else(|_| sysroot_lib_path.clone()) }; let canonical_lib_dir = try_canonicalize(lib_dir).unwrap_or_else(|_| lib_dir.to_path_buf()); if canonical_lib_dir == canonical_sysroot_lib_path { - // This path, returned by `target_filesearch().get_lib_path()`, has - // already had `fix_windows_verbatim_for_gcc()` applied if needed. - sysroot_lib_path + // This path already had `fix_windows_verbatim_for_gcc()` applied if needed. + sysroot_lib_path.clone() } else { fix_windows_verbatim_for_gcc(lib_dir) } diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index febeb7093a3..fbab988a32b 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -1500,7 +1500,7 @@ impl<'a> Linker for L4Bender<'a> { impl<'a> L4Bender<'a> { pub fn new(cmd: Command, sess: &'a Session) -> L4Bender<'a> { - L4Bender { cmd, sess: sess, hinted_static: false } + L4Bender { cmd, sess, hinted_static: false } } fn hint_static(&mut self) { @@ -1520,7 +1520,7 @@ pub struct AixLinker<'a> { impl<'a> AixLinker<'a> { pub fn new(cmd: Command, sess: &'a Session) -> AixLinker<'a> { - AixLinker { cmd, sess: sess, hinted_static: None } + AixLinker { cmd, sess, hinted_static: None } } fn hint_static(&mut self) { diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 70b45a852ca..7ad31802454 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -754,7 +754,7 @@ pub(crate) enum WorkItem { } impl WorkItem { - pub fn module_kind(&self) -> ModuleKind { + fn module_kind(&self) -> ModuleKind { match *self { WorkItem::Optimize(ref m) => m.kind, WorkItem::CopyPostLtoArtifacts(_) | WorkItem::LTO(_) => ModuleKind::Regular, diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 4ab20c154cc..209750d6ba6 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -1,5 +1,6 @@ use rustc_ast::{ast, attr, MetaItemKind, NestedMetaItem}; use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr}; +use rustc_data_structures::fx::FxHashSet; use rustc_errors::codes::*; use rustc_errors::{struct_span_code_err, DiagMessage, SubdiagMessage}; use rustc_hir as hir; @@ -8,7 +9,7 @@ use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS; use rustc_hir::{lang_items, LangItem}; use rustc_middle::middle::codegen_fn_attrs::{ - CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, + CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, TargetFeature, }; use rustc_middle::mir::mono::Linkage; use rustc_middle::query::Providers; @@ -17,6 +18,7 @@ use rustc_session::lint; use rustc_session::parse::feature_err; use rustc_span::symbol::Ident; use rustc_span::{sym, Span}; +use rustc_target::abi::VariantIdx; use rustc_target::spec::{abi, SanitizerSet}; use crate::errors; @@ -78,6 +80,13 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { let mut link_ordinal_span = None; let mut no_sanitize_span = None; + let fn_sig_outer = || { + use DefKind::*; + + let def_kind = tcx.def_kind(did); + if let Fn | AssocFn | Variant | Ctor(..) = def_kind { Some(tcx.fn_sig(did)) } else { None } + }; + for attr in attrs.iter() { // In some cases, attribute are only valid on functions, but it's the `check_attr` // pass that check that they aren't used anywhere else, rather this module. @@ -85,16 +94,12 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { // functions (such as calling `fn_sig`, which ICEs if given a non-function). We also // report a delayed bug, just in case `check_attr` isn't doing its job. let fn_sig = || { - use DefKind::*; - - let def_kind = tcx.def_kind(did); - if let Fn | AssocFn | Variant | Ctor(..) = def_kind { - Some(tcx.fn_sig(did)) - } else { + let sig = fn_sig_outer(); + if sig.is_none() { tcx.dcx() .span_delayed_bug(attr.span, "this attribute can only be applied to functions"); - None } + sig }; let Some(Ident { name, .. }) = attr.ident() else { @@ -613,7 +618,93 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { } } - // If a function uses #[target_feature] it can't be inlined into general + if let Some(sig) = fn_sig_outer() { + // Collect target features from types reachable from arguments. + // We define a type as "reachable" if: + // - it is a function argument + // - it is a field of a reachable struct + // - there is a reachable reference to it + // FIXME(struct_target_features): we may want to cache the result of this computation. + let mut visited_types = FxHashSet::default(); + let mut reachable_types: Vec<_> = sig.skip_binder().inputs().skip_binder().to_owned(); + let mut additional_tf = vec![]; + + while let Some(ty) = reachable_types.pop() { + if visited_types.contains(&ty) { + continue; + } + visited_types.insert(ty); + match ty.kind() { + ty::Alias(..) => { + if let Ok(t) = + tcx.try_normalize_erasing_regions(tcx.param_env(did.to_def_id()), ty) + { + reachable_types.push(t) + } + } + + ty::Ref(_, inner, _) => reachable_types.push(*inner), + ty::Tuple(tys) => reachable_types.extend(tys.iter()), + ty::Adt(adt_def, args) => { + additional_tf.extend_from_slice(tcx.struct_target_features(adt_def.did())); + // This only recurses into structs as i.e. an Option is an ADT + // that doesn't actually always contain a TargetFeature. + if adt_def.is_struct() { + reachable_types.extend( + adt_def + .variant(VariantIdx::from_usize(0)) + .fields + .iter() + .map(|field| field.ty(tcx, args)), + ); + } + } + ty::Bool + | ty::Char + | ty::Int(..) + | ty::Uint(..) + | ty::Float(..) + | ty::Foreign(..) + | ty::Str + | ty::Array(..) + | ty::Pat(..) + | ty::Slice(..) + | ty::RawPtr(..) + | ty::FnDef(..) + | ty::FnPtr(..) + | ty::Dynamic(..) + | ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Coroutine(..) + | ty::CoroutineWitness(..) + | ty::Never + | ty::Param(..) + | ty::Bound(..) + | ty::Placeholder(..) + | ty::Infer(..) + | ty::Error(..) => (), + } + } + + // FIXME(struct_target_features): is this really necessary? + if !additional_tf.is_empty() && sig.skip_binder().abi() != abi::Abi::Rust { + tcx.dcx().span_err( + tcx.hir().span(tcx.local_def_id_to_hir_id(did)), + "cannot use a struct with target features in a function with non-Rust ABI", + ); + } + if !additional_tf.is_empty() && codegen_fn_attrs.inline == InlineAttr::Always { + tcx.dcx().span_err( + tcx.hir().span(tcx.local_def_id_to_hir_id(did)), + "cannot use a struct with target features in a #[inline(always)] function", + ); + } + codegen_fn_attrs + .target_features + .extend(additional_tf.iter().map(|tf| TargetFeature { implied: true, ..*tf })); + } + + // If a function uses non-default target_features it can't be inlined into general // purpose functions as they wouldn't have the right target features // enabled. For that reason we also forbid #[inline(always)] as it can't be // respected. @@ -758,6 +849,20 @@ fn check_link_name_xor_ordinal( } } -pub fn provide(providers: &mut Providers) { - *providers = Providers { codegen_fn_attrs, should_inherit_track_caller, ..*providers }; +fn struct_target_features(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &[TargetFeature] { + let mut features = vec![]; + let supported_features = tcx.supported_target_features(LOCAL_CRATE); + for attr in tcx.get_attrs(def_id, sym::target_feature) { + from_target_feature(tcx, attr, supported_features, &mut features); + } + tcx.arena.alloc_slice(&features) +} + +pub fn provide(providers: &mut Providers) { + *providers = Providers { + codegen_fn_attrs, + should_inherit_track_caller, + struct_target_features, + ..*providers + }; } diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/mod.rs b/compiler/rustc_codegen_ssa/src/debuginfo/mod.rs index 1eaf593a6d7..0918660e6be 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/mod.rs @@ -1,6 +1,7 @@ -use rustc_middle::ty::layout::TyAndLayout; -use rustc_middle::ty::{self}; -use rustc_target::abi::Size; +use rustc_middle::bug; +use rustc_middle::ty::layout::{IntegerExt, PrimitiveExt, TyAndLayout}; +use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_target::abi::{Integer, Primitive, Size, TagEncoding, Variants}; // FIXME(eddyb) find a place for this (or a way to replace it). pub mod type_names; @@ -11,13 +12,25 @@ pub mod type_names; /// NOTE: This is somewhat inconsistent right now: For empty enums and enums with a single /// fieldless variant, we generate DW_TAG_struct_type, although a /// DW_TAG_enumeration_type would be a better fit. -pub fn wants_c_like_enum_debuginfo(enum_type_and_layout: TyAndLayout<'_>) -> bool { +pub fn wants_c_like_enum_debuginfo<'tcx>( + tcx: TyCtxt<'tcx>, + enum_type_and_layout: TyAndLayout<'tcx>, +) -> bool { match enum_type_and_layout.ty.kind() { ty::Adt(adt_def, _) => { if !adt_def.is_enum() { return false; } + if type_names::cpp_like_debuginfo(tcx) + && tag_base_type_opt(tcx, enum_type_and_layout) + .map(|ty| ty.primitive_size(tcx).bits()) + == Some(128) + { + // C++-like debuginfo never uses the C-like representation for 128-bit enums. + return false; + } + match adt_def.variants().len() { 0 => false, 1 => { @@ -33,3 +46,51 @@ pub fn wants_c_like_enum_debuginfo(enum_type_and_layout: TyAndLayout<'_>) -> boo _ => false, } } + +/// Extract the type with which we want to describe the tag of the given enum or coroutine. +pub fn tag_base_type<'tcx>(tcx: TyCtxt<'tcx>, enum_type_and_layout: TyAndLayout<'tcx>) -> Ty<'tcx> { + tag_base_type_opt(tcx, enum_type_and_layout).unwrap_or_else(|| { + bug!("tag_base_type() called for enum without tag: {:?}", enum_type_and_layout) + }) +} + +pub fn tag_base_type_opt<'tcx>( + tcx: TyCtxt<'tcx>, + enum_type_and_layout: TyAndLayout<'tcx>, +) -> Option> { + assert!(match enum_type_and_layout.ty.kind() { + ty::Coroutine(..) => true, + ty::Adt(adt_def, _) => adt_def.is_enum(), + _ => false, + }); + + match enum_type_and_layout.layout.variants() { + // A single-variant enum has no discriminant. + Variants::Single { .. } => None, + + Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, tag, .. } => { + // Niche tags are always normalized to unsized integers of the correct size. + Some( + match tag.primitive() { + Primitive::Int(t, _) => t, + Primitive::Float(f) => Integer::from_size(f.size()).unwrap(), + // FIXME(erikdesjardins): handle non-default addrspace ptr sizes + Primitive::Pointer(_) => { + // If the niche is the NULL value of a reference, then `discr_enum_ty` will be + // a RawPtr. CodeView doesn't know what to do with enums whose base type is a + // pointer so we fix this up to just be `usize`. + // DWARF might be able to deal with this but with an integer type we are on + // the safe side there too. + tcx.data_layout.ptr_sized_integer() + } + } + .to_ty(tcx, false), + ) + } + + Variants::Multiple { tag_encoding: TagEncoding::Direct, tag, .. } => { + // Direct tags preserve the sign. + Some(tag.primitive().to_ty(tcx)) + } + } +} diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 27558038927..f0bc4354f9a 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -85,7 +85,7 @@ fn push_debuginfo_type_name<'tcx>( let layout_for_cpp_like_fallback = if cpp_like_debuginfo && def.is_enum() { match tcx.layout_of(ParamEnv::reveal_all().and(t)) { Ok(layout) => { - if !wants_c_like_enum_debuginfo(layout) { + if !wants_c_like_enum_debuginfo(tcx, layout) { Some(layout) } else { // This is a C-like enum so we don't want to use the fallback encoding @@ -106,6 +106,7 @@ fn push_debuginfo_type_name<'tcx>( if let Some(ty_and_layout) = layout_for_cpp_like_fallback { msvc_enum_fallback( + tcx, ty_and_layout, &|output, visited| { push_item_name(tcx, def.did(), true, output); @@ -331,7 +332,7 @@ fn push_debuginfo_type_name<'tcx>( output.push(')'); } } - ty::FnDef(..) | ty::FnPtr(_) => { + ty::FnDef(..) | ty::FnPtr(..) => { // We've encountered a weird 'recursive type' // Currently, the only way to generate such a type // is by using 'impl trait': @@ -421,6 +422,7 @@ fn push_debuginfo_type_name<'tcx>( if cpp_like_debuginfo && t.is_coroutine() { let ty_and_layout = tcx.layout_of(ParamEnv::reveal_all().and(t)).unwrap(); msvc_enum_fallback( + tcx, ty_and_layout, &|output, visited| { push_closure_or_coroutine_name(tcx, def_id, args, true, output, visited); @@ -455,12 +457,13 @@ fn push_debuginfo_type_name<'tcx>( // debugger. For more information, look in // rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs. fn msvc_enum_fallback<'tcx>( + tcx: TyCtxt<'tcx>, ty_and_layout: TyAndLayout<'tcx>, push_inner: &dyn Fn(/*output*/ &mut String, /*visited*/ &mut FxHashSet>), output: &mut String, visited: &mut FxHashSet>, ) { - assert!(!wants_c_like_enum_debuginfo(ty_and_layout)); + assert!(!wants_c_like_enum_debuginfo(tcx, ty_and_layout)); output.push_str("enum2$<"); push_inner(output, visited); push_close_angle_bracket(true, output); diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 94bf0ab34e2..573a8cf7cbe 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -1060,3 +1060,10 @@ pub struct CompilerBuiltinsCannotCall { pub caller: String, pub callee: String, } + +#[derive(Diagnostic)] +#[diag(codegen_ssa_error_creating_import_library)] +pub(crate) struct ErrorCreatingImportLibrary<'a> { + pub lib_name: &'a str, + pub error: String, +} diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index cb6d9d6f66e..c89bfca6687 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -12,6 +12,7 @@ #![feature(rustdoc_internals)] #![feature(strict_provenance)] #![feature(try_blocks)] +#![warn(unreachable_pub)] // tidy-alphabetical-end //! This crate contains codegen code that is used by all codegen backends (LLVM and others). diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs index 6794365c9be..386e1f91e7f 100644 --- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs +++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs @@ -13,7 +13,7 @@ use tracing::debug; use super::FunctionCx; use crate::traits::*; -pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( +pub(crate) fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( fx: &FunctionCx<'a, 'tcx, Bx>, ) -> BitSet { let mir = fx.mir; @@ -220,14 +220,14 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> | MutatingUseContext::SetDiscriminant | MutatingUseContext::AsmOutput | MutatingUseContext::Borrow - | MutatingUseContext::AddressOf + | MutatingUseContext::RawBorrow | MutatingUseContext::Projection, ) | PlaceContext::NonMutatingUse( NonMutatingUseContext::Inspect | NonMutatingUseContext::SharedBorrow | NonMutatingUseContext::FakeBorrow - | NonMutatingUseContext::AddressOf + | NonMutatingUseContext::RawBorrow | NonMutatingUseContext::Projection, ) => { self.locals[local] = LocalKind::Memory; @@ -251,14 +251,14 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> } #[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum CleanupKind { +pub(crate) enum CleanupKind { NotCleanup, Funclet, Internal { funclet: mir::BasicBlock }, } impl CleanupKind { - pub fn funclet_bb(self, for_bb: mir::BasicBlock) -> Option { + pub(crate) fn funclet_bb(self, for_bb: mir::BasicBlock) -> Option { match self { CleanupKind::NotCleanup => None, CleanupKind::Funclet => Some(for_bb), @@ -270,7 +270,7 @@ impl CleanupKind { /// MSVC requires unwinding code to be split to a tree of *funclets*, where each funclet can only /// branch to itself or to its parent. Luckily, the code we generates matches this pattern. /// Recover that structure in an analyze pass. -pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec { +pub(crate) fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec { fn discover_masters<'tcx>( result: &mut IndexSlice, mir: &mir::Body<'tcx>, diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 772adf13ff1..817e2ca72ec 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -846,7 +846,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ), None, ), - ty::FnPtr(_) => (None, Some(callee.immediate())), + ty::FnPtr(..) => (None, Some(callee.immediate())), _ => bug!("{} is not callable", callee.layout.ty), }; diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs index 0e495973a01..75692540c03 100644 --- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs @@ -1,3 +1,4 @@ +use std::collections::hash_map::Entry; use std::ops::Range; use rustc_data_structures::fx::FxHashMap; @@ -447,6 +448,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } let mut per_local = IndexVec::from_elem(vec![], &self.mir.local_decls); + let mut params_seen: FxHashMap<_, Bx::DIVariable> = Default::default(); for var in &self.mir.var_debug_info { let dbg_scope_and_span = if full_debug_info { self.adjusted_span_and_dbg_scope(var.source_info) @@ -491,7 +493,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { VariableKind::LocalVariable }; - self.cx.create_dbg_var(var.name, var_ty, dbg_scope, var_kind, span) + if let VariableKind::ArgumentVariable(arg_index) = var_kind { + match params_seen.entry((dbg_scope, arg_index)) { + Entry::Occupied(o) => o.get().clone(), + Entry::Vacant(v) => v + .insert( + self.cx.create_dbg_var(var.name, var_ty, dbg_scope, var_kind, span), + ) + .clone(), + } + } else { + self.cx.create_dbg_var(var.name, var_ty, dbg_scope, var_kind, span) + } }); let fragment = if let Some(ref fragment) = var.composite { diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 4ce07269cd2..de94d87bcea 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -106,7 +106,7 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { locals: locals::Locals<'tcx, Bx::Value>, /// All `VarDebugInfo` from the MIR body, partitioned by `Local`. - /// This is `None` if no var`#[non_exhaustive]`iable debuginfo/names are needed. + /// This is `None` if no variable debuginfo/names are needed. per_local_var_debug_info: Option>>>, diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 3c2c29ac7f7..d94c6f8ddce 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -584,7 +584,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::Rvalue::CopyForDeref(place) => { self.codegen_operand(bx, &mir::Operand::Copy(place)) } - mir::Rvalue::AddressOf(mutability, place) => { + mir::Rvalue::RawPtr(mutability, place) => { let mk_ptr = move |tcx: TyCtxt<'tcx>, ty: Ty<'tcx>| Ty::new_ptr(tcx, ty, mutability); self.codegen_place_to_pointer(bx, place, mk_ptr) @@ -813,7 +813,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { cg_value.len(bx.cx()) } - /// Codegen an `Rvalue::AddressOf` or `Rvalue::Ref` + /// Codegen an `Rvalue::RawPtr` or `Rvalue::Ref` fn codegen_place_to_pointer( &mut self, bx: &mut Bx, @@ -1085,7 +1085,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::Rvalue::Ref(..) | mir::Rvalue::CopyForDeref(..) | - mir::Rvalue::AddressOf(..) | + mir::Rvalue::RawPtr(..) | mir::Rvalue::Len(..) | mir::Rvalue::Cast(..) | // (*) mir::Rvalue::ShallowInitBox(..) | // (*) diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index 81e96413a9f..c5e2d55be83 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -1,4 +1,5 @@ use std::any::Any; +use std::hash::Hash; use rustc_ast::expand::allocator::AllocatorKind; use rustc_data_structures::fx::FxIndexMap; @@ -30,7 +31,7 @@ pub trait BackendTypes { // FIXME(eddyb) find a common convention for all of the debuginfo-related // names (choose between `Dbg`, `Debug`, `DebugInfo`, `DI` etc.). - type DIScope: Copy; + type DIScope: Copy + Hash + PartialEq + Eq; type DILocation: Copy; type DIVariable: Copy; } diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index 1442f1832b9..db788b6b151 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -402,9 +402,6 @@ const_eval_unallowed_mutable_refs = const_eval_unallowed_op_in_const_context = {$msg} -const_eval_unavailable_target_features_for_fn = - calling a function that requires unavailable target features: {$unavailable_feats} - const_eval_uninhabited_enum_variant_read = read discriminant of an uninhabited enum variant const_eval_uninhabited_enum_variant_written = @@ -419,7 +416,7 @@ const_eval_unstable_const_fn = `{$def_path}` is not yet stable as a const fn const_eval_unstable_in_stable = const-stable function cannot use `#[feature({$gate})]` .unstable_sugg = if it is not part of the public API, make this function unstably const - .bypass_sugg = otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks + .bypass_sugg = otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (but requires team approval) const_eval_unterminated_c_string = reading a null-terminated string starting at {$pointer} with no null found before end of allocation diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 844f3f3d611..6a086a3a7e5 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -1,6 +1,7 @@ //! The `Visitor` responsible for actually checking a `mir::Body` for invalid operations. use std::assert_matches::assert_matches; +use std::borrow::Cow; use std::mem; use std::ops::Deref; @@ -15,6 +16,8 @@ use rustc_middle::mir::*; use rustc_middle::span_bug; use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt, TypeVisitableExt}; +use rustc_mir_dataflow::impls::MaybeStorageLive; +use rustc_mir_dataflow::storage::always_storage_live_locals; use rustc_mir_dataflow::Analysis; use rustc_span::{sym, Span, Symbol, DUMMY_SP}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; @@ -171,7 +174,7 @@ struct LocalReturnTyVisitor<'ck, 'mir, 'tcx> { impl<'ck, 'mir, 'tcx> TypeVisitor> for LocalReturnTyVisitor<'ck, 'mir, 'tcx> { fn visit_ty(&mut self, t: Ty<'tcx>) { match t.kind() { - ty::FnPtr(_) => {} + ty::FnPtr(..) => {} ty::Ref(_, _, hir::Mutability::Mut) => { self.checker.check_op(ops::mut_ref::MutRef(self.kind)); t.super_visit_with(self) @@ -188,8 +191,9 @@ pub struct Checker<'mir, 'tcx> { /// The span of the current statement. span: Span, - /// A set that stores for each local whether it has a `StorageDead` for it somewhere. - local_has_storage_dead: Option>, + /// A set that stores for each local whether it is "transient", i.e. guaranteed to be dead + /// when this MIR body returns. + transient_locals: Option>, error_emitted: Option, secondary_errors: Vec>, @@ -209,7 +213,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { span: ccx.body.span, ccx, qualifs: Default::default(), - local_has_storage_dead: None, + transient_locals: None, error_emitted: None, secondary_errors: Vec::new(), } @@ -264,23 +268,33 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { } } - fn local_has_storage_dead(&mut self, local: Local) -> bool { + fn local_is_transient(&mut self, local: Local) -> bool { let ccx = self.ccx; - self.local_has_storage_dead + self.transient_locals .get_or_insert_with(|| { - struct StorageDeads { - locals: BitSet, - } - impl<'tcx> Visitor<'tcx> for StorageDeads { - fn visit_statement(&mut self, stmt: &Statement<'tcx>, _: Location) { - if let StatementKind::StorageDead(l) = stmt.kind { - self.locals.insert(l); - } + // A local is "transient" if it is guaranteed dead at all `Return`. + // So first compute the say of "maybe live" locals at each program point. + let always_live_locals = &always_storage_live_locals(&ccx.body); + let mut maybe_storage_live = + MaybeStorageLive::new(Cow::Borrowed(always_live_locals)) + .into_engine(ccx.tcx, &ccx.body) + .iterate_to_fixpoint() + .into_results_cursor(&ccx.body); + + // And then check all `Return` in the MIR, and if a local is "maybe live" at a + // `Return` then it is definitely not transient. + let mut transient = BitSet::new_filled(ccx.body.local_decls.len()); + // Make sure to only visit reachable blocks, the dataflow engine can ICE otherwise. + for (bb, data) in traversal::reachable(&ccx.body) { + if matches!(data.terminator().kind, TerminatorKind::Return) { + let location = ccx.body.terminator_loc(bb); + maybe_storage_live.seek_after_primary_effect(location); + // If a local may be live here, it is definitely not transient. + transient.subtract(maybe_storage_live.get()); } } - let mut v = StorageDeads { locals: BitSet::new_empty(ccx.body.local_decls.len()) }; - v.visit_body(ccx.body); - v.locals + + transient }) .contains(local) } @@ -375,7 +389,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { // `StorageDead` in every control flow path leading to a `return` terminator. // The good news is that interning will detect if any unexpected mutable // pointer slips through. - if place.is_indirect() || self.local_has_storage_dead(place.local) { + if place.is_indirect() || self.local_is_transient(place.local) { self.check_op(ops::TransientMutBorrow(kind)); } else { self.check_op(ops::MutBorrow(kind)); @@ -431,13 +445,13 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { return; } } - Rvalue::AddressOf(mutbl, place) => { + Rvalue::RawPtr(mutbl, place) => { if let Some(reborrowed_place_ref) = place_as_reborrow(self.tcx, self.body, place) { let ctx = match mutbl { Mutability::Not => { - PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf) + PlaceContext::NonMutatingUse(NonMutatingUseContext::RawBorrow) } - Mutability::Mut => PlaceContext::MutatingUse(MutatingUseContext::AddressOf), + Mutability::Mut => PlaceContext::MutatingUse(MutatingUseContext::RawBorrow), }; self.visit_local(reborrowed_place_ref.local, ctx, location); self.visit_projection(reborrowed_place_ref, ctx, location); @@ -472,7 +486,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { } Rvalue::Ref(_, BorrowKind::Mut { .. }, place) - | Rvalue::AddressOf(Mutability::Mut, place) => { + | Rvalue::RawPtr(Mutability::Mut, place) => { // Inside mutable statics, we allow arbitrary mutable references. // We've allowed `static mut FOO = &mut [elements];` for a long time (the exact // reasons why are lost to history), and there is no reason to restrict that to @@ -493,7 +507,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { } Rvalue::Ref(_, BorrowKind::Shared | BorrowKind::Fake(_), place) - | Rvalue::AddressOf(Mutability::Not, place) => { + | Rvalue::RawPtr(Mutability::Not, place) => { let borrowed_place_has_mut_interior = qualifs::in_place::( self.ccx, &mut |local| self.qualifs.has_mut_interior(self.ccx, local, location), @@ -526,7 +540,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { // `StorageDead` in every control flow path leading to a `return` terminator. // The good news is that interning will detect if any unexpected mutable // pointer slips through. - if self.local_has_storage_dead(place.local) { + if self.local_is_transient(place.local) { self.check_op(ops::TransientCellBorrow); } else { self.check_op(ops::CellBorrow); @@ -575,10 +589,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { Rvalue::UnaryOp(_, operand) => { let ty = operand.ty(self.body, self.tcx); - if is_int_bool_or_char(ty) { - // Int, bool, and char operations are fine. - } else if ty.is_floating_point() { - self.check_op(ops::FloatingPointOp); + if is_int_bool_float_or_char(ty) { + // Int, bool, float, and char operations are fine. } else { span_bug!(self.span, "non-primitive type in `Rvalue::UnaryOp`: {:?}", ty); } @@ -588,8 +600,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { let lhs_ty = lhs.ty(self.body, self.tcx); let rhs_ty = rhs.ty(self.body, self.tcx); - if is_int_bool_or_char(lhs_ty) && is_int_bool_or_char(rhs_ty) { - // Int, bool, and char operations are fine. + if is_int_bool_float_or_char(lhs_ty) && is_int_bool_float_or_char(rhs_ty) { + // Int, bool, float, and char operations are fine. } else if lhs_ty.is_fn_ptr() || lhs_ty.is_unsafe_ptr() { assert_matches!( op, @@ -603,8 +615,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { ); self.check_op(ops::RawPtrComparison); - } else if lhs_ty.is_floating_point() || rhs_ty.is_floating_point() { - self.check_op(ops::FloatingPointOp); } else { span_bug!( self.span, @@ -726,7 +736,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { let (mut callee, mut fn_args) = match *fn_ty.kind() { ty::FnDef(def_id, fn_args) => (def_id, fn_args), - ty::FnPtr(_) => { + ty::FnPtr(..) => { self.check_op(ops::FnCallIndirect); return; } @@ -1009,8 +1019,8 @@ fn place_as_reborrow<'tcx>( } } -fn is_int_bool_or_char(ty: Ty<'_>) -> bool { - ty.is_bool() || ty.is_integral() || ty.is_char() +fn is_int_bool_float_or_char(ty: Ty<'_>) -> bool { + ty.is_bool() || ty.is_integral() || ty.is_char() || ty.is_floating_point() } fn emit_unstable_in_stable_error(ccx: &ConstCx<'_, '_>, span: Span, gate: Symbol) { diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index c6361710ac9..93fafa60557 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -55,28 +55,6 @@ pub trait NonConstOp<'tcx>: std::fmt::Debug { fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx>; } -#[derive(Debug)] -pub struct FloatingPointOp; -impl<'tcx> NonConstOp<'tcx> for FloatingPointOp { - fn status_in_item(&self, ccx: &ConstCx<'_, 'tcx>) -> Status { - if ccx.const_kind() == hir::ConstContext::ConstFn { - Status::Unstable(sym::const_fn_floating_point_arithmetic) - } else { - Status::Allowed - } - } - - #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { - feature_err( - &ccx.tcx.sess, - sym::const_fn_floating_point_arithmetic, - span, - format!("floating point arithmetic is not allowed in {}s", ccx.const_kind()), - ) - } -} - /// A function call where the callee is a pointer. #[derive(Debug)] pub struct FnCallIndirect; @@ -384,7 +362,7 @@ impl<'tcx> NonConstOp<'tcx> for HeapAllocation { ccx.dcx().create_err(errors::UnallowedHeapAllocations { span, kind: ccx.const_kind(), - teach: ccx.tcx.sess.teach(E0010).then_some(()), + teach: ccx.tcx.sess.teach(E0010), }) } } @@ -440,22 +418,12 @@ impl<'tcx> NonConstOp<'tcx> for CellBorrow { DiagImportance::Secondary } fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { - // FIXME: Maybe a more elegant solution to this if else case - if let hir::ConstContext::Static(_) = ccx.const_kind() { - ccx.dcx().create_err(errors::InteriorMutableDataRefer { - span, - opt_help: Some(()), - kind: ccx.const_kind(), - teach: ccx.tcx.sess.teach(E0492).then_some(()), - }) - } else { - ccx.dcx().create_err(errors::InteriorMutableDataRefer { - span, - opt_help: None, - kind: ccx.const_kind(), - teach: ccx.tcx.sess.teach(E0492).then_some(()), - }) - } + ccx.dcx().create_err(errors::InteriorMutableDataRefer { + span, + opt_help: matches!(ccx.const_kind(), hir::ConstContext::Static(_)), + kind: ccx.const_kind(), + teach: ccx.tcx.sess.teach(E0492), + }) } } @@ -481,12 +449,12 @@ impl<'tcx> NonConstOp<'tcx> for MutBorrow { hir::BorrowKind::Raw => ccx.tcx.dcx().create_err(errors::UnallowedMutableRaw { span, kind: ccx.const_kind(), - teach: ccx.tcx.sess.teach(E0764).then_some(()), + teach: ccx.tcx.sess.teach(E0764), }), hir::BorrowKind::Ref => ccx.dcx().create_err(errors::UnallowedMutableRefs { span, kind: ccx.const_kind(), - teach: ccx.tcx.sess.teach(E0764).then_some(()), + teach: ccx.tcx.sess.teach(E0764), }), } } diff --git a/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs b/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs index c4f06e5af0b..f0998300dc8 100644 --- a/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs +++ b/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs @@ -9,13 +9,19 @@ use super::check::Qualifs; use super::ops::{self, NonConstOp}; use super::qualifs::{NeedsNonConstDrop, Qualif}; use super::ConstCx; +use crate::check_consts::rustc_allow_const_fn_unstable; /// Returns `true` if we should use the more precise live drop checker that runs after drop /// elaboration. pub fn checking_enabled(ccx: &ConstCx<'_, '_>) -> bool { - // Const-stable functions must always use the stable live drop checker. + // Const-stable functions must always use the stable live drop checker... if ccx.is_const_stable_const_fn() { - return false; + // ...except if they have the feature flag set via `rustc_allow_const_fn_unstable`. + return rustc_allow_const_fn_unstable( + ccx.tcx, + ccx.body.source.def_id().expect_local(), + sym::const_precise_live_drops, + ); } ccx.tcx.features().const_precise_live_drops diff --git a/compiler/rustc_const_eval/src/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs index c0f2d113c7e..c566dc7fa84 100644 --- a/compiler/rustc_const_eval/src/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs @@ -291,7 +291,7 @@ where in_operand::(cx, in_local, lhs) || in_operand::(cx, in_local, rhs) } - Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => { + Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) => { // Special-case reborrows to be more like a copy of the reference. if let Some((place_base, ProjectionElem::Deref)) = place.as_ref().last_projection() { let base_ty = place_base.ty(cx.body, cx.tcx).ty; diff --git a/compiler/rustc_const_eval/src/check_consts/resolver.rs b/compiler/rustc_const_eval/src/check_consts/resolver.rs index ea3a5264357..681184f7fbc 100644 --- a/compiler/rustc_const_eval/src/check_consts/resolver.rs +++ b/compiler/rustc_const_eval/src/check_consts/resolver.rs @@ -96,7 +96,7 @@ where } fn address_of_allows_mutation(&self) -> bool { - // Exact set of permissions granted by AddressOf is undecided. Conservatively assume that + // Exact set of permissions granted by RawPtr is undecided. Conservatively assume that // it might allow mutation until resolution of #56604. true } @@ -170,7 +170,7 @@ where self.super_rvalue(rvalue, location); match rvalue { - mir::Rvalue::AddressOf(_mt, borrowed_place) => { + mir::Rvalue::RawPtr(_mt, borrowed_place) => { if !borrowed_place.is_indirect() && self.address_of_allows_mutation() { let place_ty = borrowed_place.ty(self.ccx.body, self.ccx.tcx).ty; if Q::in_any_value_of_ty(self.ccx, place_ty) { diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs index 00bbd9337f7..25b32785b7d 100644 --- a/compiler/rustc_const_eval/src/const_eval/error.rs +++ b/compiler/rustc_const_eval/src/const_eval/error.rs @@ -22,6 +22,7 @@ pub enum ConstEvalErrKind { RecursiveStatic, AssertFailure(AssertKind), Panic { msg: Symbol, line: u32, col: u32, file: Symbol }, + WriteThroughImmutablePointer, } impl MachineStopType for ConstEvalErrKind { @@ -35,12 +36,16 @@ impl MachineStopType for ConstEvalErrKind { Panic { .. } => const_eval_panic, RecursiveStatic => const_eval_recursive_static, AssertFailure(x) => x.diagnostic_message(), + WriteThroughImmutablePointer => const_eval_write_through_immutable_pointer, } } fn add_args(self: Box, adder: &mut dyn FnMut(DiagArgName, DiagArgValue)) { use ConstEvalErrKind::*; match *self { - RecursiveStatic | ConstAccessesMutGlobal | ModifiedGlobal => {} + RecursiveStatic + | ConstAccessesMutGlobal + | ModifiedGlobal + | WriteThroughImmutablePointer => {} AssertFailure(kind) => kind.add_args(adder), Panic { msg, line, col, file } => { adder("msg".into(), msg.into_diag_arg()); @@ -159,6 +164,7 @@ where /// Emit a lint from a const-eval situation, with a backtrace. // Even if this is unused, please don't remove it -- chances are we will need to emit a lint during const-eval again in the future! +#[allow(unused)] pub(super) fn lint<'tcx, L>( tcx: TyCtxtAt<'tcx>, machine: &CompileTimeMachine<'tcx>, diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index a075bdc1911..9c1fef095f5 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -12,7 +12,6 @@ use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::layout::{FnAbiOf, TyAndLayout}; use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::{bug, mir}; -use rustc_session::lint::builtin::WRITES_THROUGH_IMMUTABLE_POINTER; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; use rustc_target::abi::{Align, Size}; @@ -40,7 +39,10 @@ const TINY_LINT_TERMINATOR_LIMIT: usize = 20; /// power of two of interpreted terminators. const PROGRESS_INDICATOR_START: usize = 4_000_000; -/// Extra machine state for CTFE, and the Machine instance +/// Extra machine state for CTFE, and the Machine instance. +// +// Should be public because out-of-tree rustc consumers need this +// if they want to interact with constant values. pub struct CompileTimeMachine<'tcx> { /// The number of terminators that have been evaluated. /// @@ -160,7 +162,7 @@ impl interpret::AllocMap for FxIndexMap { } } -pub(crate) type CompileTimeInterpCx<'tcx> = InterpCx<'tcx, CompileTimeMachine<'tcx>>; +pub type CompileTimeInterpCx<'tcx> = InterpCx<'tcx, CompileTimeMachine<'tcx>>; #[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum MemoryKind { @@ -729,8 +731,8 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { } fn before_memory_write( - tcx: TyCtxtAt<'tcx>, - machine: &mut Self, + _tcx: TyCtxtAt<'tcx>, + _machine: &mut Self, _alloc_extra: &mut Self::AllocExtra, (_alloc_id, immutable): (AllocId, bool), range: AllocRange, @@ -741,9 +743,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { } // Reject writes through immutable pointers. if immutable { - super::lint(tcx, machine, WRITES_THROUGH_IMMUTABLE_POINTER, |frames| { - crate::errors::WriteThroughImmutablePointer { frames } - }); + return Err(ConstEvalErrKind::WriteThroughImmutablePointer.into()); } // Everything else is fine. Ok(()) diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index 460c9797f36..c96296eddb8 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -132,7 +132,7 @@ fn const_to_valtree_inner<'tcx>( // Technically we could allow function pointers (represented as `ty::Instance`), but this is not guaranteed to // agree with runtime equality tests. - ty::FnPtr(_) => Err(ValTreeCreationError::NonSupportedType(ty)), + ty::FnPtr(..) => Err(ValTreeCreationError::NonSupportedType(ty)), ty::Ref(_, _, _) => { let derefd_place = ecx.deref_pointer(place)?; @@ -353,7 +353,7 @@ pub fn valtree_to_const_value<'tcx>( | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::Str | ty::Slice(_) | ty::Dynamic(..) => bug!("no ValTree should have been created for type {:?}", ty.kind()), diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 7afb92c08ec..0b366b43f95 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -151,7 +151,7 @@ pub(crate) struct UnallowedMutableRefs { pub span: Span, pub kind: ConstContext, #[note(const_eval_teach_note)] - pub teach: Option<()>, + pub teach: bool, } #[derive(Diagnostic)] @@ -161,7 +161,7 @@ pub(crate) struct UnallowedMutableRaw { pub span: Span, pub kind: ConstContext, #[note(const_eval_teach_note)] - pub teach: Option<()>, + pub teach: bool, } #[derive(Diagnostic)] #[diag(const_eval_non_const_fmt_macro_call, code = E0015)] @@ -196,7 +196,7 @@ pub(crate) struct UnallowedHeapAllocations { pub span: Span, pub kind: ConstContext, #[note(const_eval_teach_note)] - pub teach: Option<()>, + pub teach: bool, } #[derive(Diagnostic)] @@ -214,10 +214,10 @@ pub(crate) struct InteriorMutableDataRefer { #[label] pub span: Span, #[help] - pub opt_help: Option<()>, + pub opt_help: bool, pub kind: ConstContext, #[note(const_eval_teach_note)] - pub teach: Option<()>, + pub teach: bool, } #[derive(Diagnostic)] @@ -407,13 +407,6 @@ pub struct ConstEvalError { pub frame_notes: Vec, } -#[derive(LintDiagnostic)] -#[diag(const_eval_write_through_immutable_pointer)] -pub struct WriteThroughImmutablePointer { - #[subdiagnostic] - pub frames: Vec, -} - #[derive(Diagnostic)] #[diag(const_eval_nullary_intrinsic_fail)] pub struct NullaryIntrinsicError { diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index 917a2fa7c6d..61e8007e10e 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -311,34 +311,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { Ok(()) } - fn check_fn_target_features(&self, instance: ty::Instance<'tcx>) -> InterpResult<'tcx, ()> { - // Calling functions with `#[target_feature]` is not unsafe on WASM, see #84988 - let attrs = self.tcx.codegen_fn_attrs(instance.def_id()); - if !self.tcx.sess.target.is_like_wasm - && attrs - .target_features - .iter() - .any(|feature| !self.tcx.sess.target_features.contains(&feature.name)) - { - throw_ub_custom!( - fluent::const_eval_unavailable_target_features_for_fn, - unavailable_feats = attrs - .target_features - .iter() - .filter(|&feature| !feature.implied - && !self.tcx.sess.target_features.contains(&feature.name)) - .fold(String::new(), |mut s, feature| { - if !s.is_empty() { - s.push_str(", "); - } - s.push_str(feature.name.as_str()); - s - }), - ); - } - Ok(()) - } - /// The main entry point for creating a new stack frame: performs ABI checks and initializes /// arguments. #[instrument(skip(self), level = "trace")] @@ -360,20 +332,18 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { throw_unsup_format!("calling a c-variadic function is not supported"); } - if M::enforce_abi(self) { - if caller_fn_abi.conv != callee_fn_abi.conv { - throw_ub_custom!( - fluent::const_eval_incompatible_calling_conventions, - callee_conv = format!("{:?}", callee_fn_abi.conv), - caller_conv = format!("{:?}", caller_fn_abi.conv), - ) - } + if caller_fn_abi.conv != callee_fn_abi.conv { + throw_ub_custom!( + fluent::const_eval_incompatible_calling_conventions, + callee_conv = format!("{:?}", callee_fn_abi.conv), + caller_conv = format!("{:?}", caller_fn_abi.conv), + ) } // Check that all target features required by the callee (i.e., from // the attribute `#[target_feature(enable = ...)]`) are enabled at // compile time. - self.check_fn_target_features(instance)?; + M::check_fn_target_features(self, instance)?; if !callee_fn_abi.can_unwind { // The callee cannot unwind, so force the `Unreachable` unwind handling. @@ -576,7 +546,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { | ty::InstanceKind::ReifyShim(..) | ty::InstanceKind::ClosureOnceShim { .. } | ty::InstanceKind::ConstructCoroutineInClosureShim { .. } - | ty::InstanceKind::CoroutineKindShim { .. } | ty::InstanceKind::FnPtrShim(..) | ty::InstanceKind::DropGlue(..) | ty::InstanceKind::CloneShim(..) diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index 37bd6d6e530..e8c9f145eea 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -97,7 +97,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer) => { let src = self.read_immediate(src)?; match cast_ty.kind() { - ty::FnPtr(_) => { + ty::FnPtr(..) => { // No change to value self.write_immediate(*src, dest)?; } @@ -230,7 +230,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { src: &ImmTy<'tcx, M::Provenance>, cast_to: TyAndLayout<'tcx>, ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> { - assert_matches!(src.layout.ty.kind(), ty::RawPtr(_, _) | ty::FnPtr(_)); + assert_matches!(src.layout.ty.kind(), ty::RawPtr(_, _) | ty::FnPtr(..)); assert!(cast_to.ty.is_integral()); let scalar = src.to_scalar(); @@ -388,7 +388,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let (src_pointee_ty, dest_pointee_ty) = self.tcx.struct_lockstep_tails_for_codegen(source_ty, cast_ty, self.param_env); - match (&src_pointee_ty.kind(), &dest_pointee_ty.kind()) { + match (src_pointee_ty.kind(), dest_pointee_ty.kind()) { (&ty::Array(_, length), &ty::Slice(_)) => { let ptr = self.read_pointer(src)?; let val = Immediate::new_slice( @@ -478,9 +478,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { dest: &PlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { trace!("Unsizing {:?} of type {} into {}", *src, src.layout.ty, cast_ty.ty); - match (&src.layout.ty.kind(), &cast_ty.ty.kind()) { + match (src.layout.ty.kind(), cast_ty.ty.kind()) { (&ty::Ref(_, s, _), &ty::Ref(_, c, _) | &ty::RawPtr(c, _)) - | (&ty::RawPtr(s, _), &ty::RawPtr(c, _)) => self.unsize_into_ptr(src, dest, *s, *c), + | (&ty::RawPtr(s, _), &ty::RawPtr(c, _)) => self.unsize_into_ptr(src, dest, s, c), (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => { assert_eq!(def_a, def_b); // implies same number of fields diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 3be1b745d00..bedc56de0da 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -81,7 +81,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>( | ty::RawPtr(_, _) | ty::Ref(_, _, _) | ty::FnDef(_, _) - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::Dynamic(_, _, _) | ty::Closure(_, _) | ty::CoroutineClosure(_, _) @@ -684,19 +684,19 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { assert!(layout.is_sized()); let get_bytes = |this: &InterpCx<'tcx, M>, - op: &OpTy<'tcx, >::Provenance>, - size| + op: &OpTy<'tcx, >::Provenance>| -> InterpResult<'tcx, &[u8]> { let ptr = this.read_pointer(op)?; - let Some(alloc_ref) = self.get_ptr_alloc(ptr, size)? else { + this.check_ptr_align(ptr, layout.align.abi)?; + let Some(alloc_ref) = self.get_ptr_alloc(ptr, layout.size)? else { // zero-sized access return Ok(&[]); }; alloc_ref.get_bytes_strip_provenance() }; - let lhs_bytes = get_bytes(self, lhs, layout.size)?; - let rhs_bytes = get_bytes(self, rhs, layout.size)?; + let lhs_bytes = get_bytes(self, lhs)?; + let rhs_bytes = get_bytes(self, rhs)?; Ok(Scalar::from_bool(lhs_bytes == rhs_bytes)) } } diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 761ab81e228..88453245b84 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -173,11 +173,6 @@ pub trait Machine<'tcx>: Sized { false } - /// Whether function calls should be [ABI](CallAbi)-checked. - fn enforce_abi(_ecx: &InterpCx<'tcx, Self>) -> bool { - true - } - /// Whether Assert(OverflowNeg) and Assert(Overflow) MIR terminators should actually /// check for overflow. fn ignore_optional_overflow_checks(_ecx: &InterpCx<'tcx, Self>) -> bool; @@ -238,6 +233,13 @@ pub trait Machine<'tcx>: Sized { unwind: mir::UnwindAction, ) -> InterpResult<'tcx, Option>>; + /// Check whether the given function may be executed on the current machine, in terms of the + /// target features is requires. + fn check_fn_target_features( + _ecx: &InterpCx<'tcx, Self>, + _instance: ty::Instance<'tcx>, + ) -> InterpResult<'tcx>; + /// Called to evaluate `Assert` MIR terminators that trigger a panic. fn assert_panic( ecx: &mut InterpCx<'tcx, Self>, @@ -280,6 +282,9 @@ pub trait Machine<'tcx>: Sized { Ok(()) } + /// Determines the result of a `NullaryOp::UbChecks` invocation. + fn ub_checks(_ecx: &InterpCx<'tcx, Self>) -> InterpResult<'tcx, bool>; + /// Called when the interpreter encounters a `StatementKind::ConstEvalCounter` instruction. /// You can use this to detect long or endlessly running programs. #[inline] @@ -614,6 +619,16 @@ pub macro compile_time_machine(<$tcx: lifetime>) { unreachable!("unwinding cannot happen during compile-time evaluation") } + #[inline(always)] + fn check_fn_target_features( + _ecx: &InterpCx<$tcx, Self>, + _instance: ty::Instance<$tcx>, + ) -> InterpResult<$tcx> { + // For now we don't do any checking here. We can't use `tcx.sess` because that can differ + // between crates, and we need to ensure that const-eval always behaves the same. + Ok(()) + } + #[inline(always)] fn call_extra_fn( _ecx: &mut InterpCx<$tcx, Self>, @@ -627,6 +642,13 @@ pub macro compile_time_machine(<$tcx: lifetime>) { match fn_val {} } + #[inline(always)] + fn ub_checks(_ecx: &InterpCx<$tcx, Self>) -> InterpResult<$tcx, bool> { + // We can't look at `tcx.sess` here as that can differ across crates, which can lead to + // unsound differences in evaluating the same constant at different instantiation sites. + Ok(true) + } + #[inline(always)] fn adjust_global_allocation<'b>( _ecx: &InterpCx<$tcx, Self>, diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 910aec9b8e1..97326fe99a2 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -1014,7 +1014,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// /// We do this so Miri's allocation access tracking does not show the validation /// reads as spurious accesses. - pub(super) fn run_for_validation(&self, f: impl FnOnce() -> R) -> R { + pub fn run_for_validation(&self, f: impl FnOnce() -> R) -> R { // This deliberately uses `==` on `bool` to follow the pattern // `assert!(val.replace(new) == old)`. assert!( diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index ad87d6953d3..9a8ccaa7cc5 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -319,6 +319,7 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> { // some fieldless enum variants can have non-zero size but still `Aggregate` ABI... try // to detect those here and also give them no data _ if matches!(layout.abi, Abi::Aggregate { .. }) + && matches!(layout.variants, abi::Variants::Single { .. }) && matches!(&layout.fields, abi::FieldsShape::Arbitrary { offsets, .. } if offsets.len() == 0) => { Immediate::Uninit @@ -328,8 +329,9 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> { assert_eq!(offset.bytes(), 0); assert!( match (self.layout.abi, layout.abi) { - (Abi::Scalar(..), Abi::Scalar(..)) => true, - (Abi::ScalarPair(..), Abi::ScalarPair(..)) => true, + (Abi::Scalar(l), Abi::Scalar(r)) => l.size(cx) == r.size(cx), + (Abi::ScalarPair(l1, l2), Abi::ScalarPair(r1, r2)) => + l1.size(cx) == r1.size(cx) && l2.size(cx) == r2.size(cx), _ => false, }, "cannot project into {} immediate with equally-sized field {}\nouter ABI: {:#?}\nfield ABI: {:#?}", @@ -344,16 +346,23 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> { (Immediate::ScalarPair(a_val, b_val), Abi::ScalarPair(a, b)) => { assert_matches!(layout.abi, Abi::Scalar(..)); Immediate::from(if offset.bytes() == 0 { - debug_assert_eq!(layout.size, a.size(cx)); + // It is "okay" to transmute from `usize` to a pointer (GVN relies on that). + // So only compare the size. + assert_eq!(layout.size, a.size(cx)); a_val } else { - debug_assert_eq!(offset, a.size(cx).align_to(b.align(cx).abi)); - debug_assert_eq!(layout.size, b.size(cx)); + assert_eq!(offset, a.size(cx).align_to(b.align(cx).abi)); + assert_eq!(layout.size, b.size(cx)); b_val }) } // everything else is a bug - _ => bug!("invalid field access on immediate {}, layout {:#?}", self, self.layout), + _ => bug!( + "invalid field access on immediate {} at offset {}, original layout {:#?}", + self, + offset.bytes(), + self.layout + ), }; ImmTy::from_immediate(inner_val, layout) diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index 2f860f9f942..e9ba12dbcc4 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -512,7 +512,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { self.tcx.offset_of_subfield(self.param_env, layout, fields.iter()).bytes(); ImmTy::from_uint(val, usize_layout()) } - UbChecks => ImmTy::from_bool(self.tcx.sess.ub_checks(), *self.tcx), + UbChecks => ImmTy::from_bool(M::ub_checks(self)?, *self.tcx), }) } } diff --git a/compiler/rustc_const_eval/src/interpret/stack.rs b/compiler/rustc_const_eval/src/interpret/stack.rs index 50dbced6a2a..0f6bf5c0336 100644 --- a/compiler/rustc_const_eval/src/interpret/stack.rs +++ b/compiler/rustc_const_eval/src/interpret/stack.rs @@ -483,7 +483,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { | ty::Bool | ty::Float(_) | ty::FnDef(..) - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::RawPtr(..) | ty::Char | ty::Ref(..) diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 2527eca3446..70cfba1922c 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -234,7 +234,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { self.write_immediate(*val, &dest)?; } - AddressOf(_, place) => { + RawPtr(_, place) => { // Figure out whether this is an addr_of of an already raw place. let place_base_raw = if place.is_indirect_first_projection() { let ty = self.frame().body.local_decls[place.local].ty; @@ -424,7 +424,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { self.tcx.mk_type_list_from_iter(extra_args.iter().map(|arg| arg.layout().ty)); let (callee, fn_abi, with_caller_location) = match *func.layout.ty.kind() { - ty::FnPtr(_sig) => { + ty::FnPtr(..) => { let fn_ptr = self.read_pointer(&func)?; let fn_val = self.get_ptr_fn(fn_ptr)?; (fn_val, self.fn_abi_of_fn_ptr(fn_sig_binder, extra_args)?, false) diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index fadc4ee6c8a..26b7251f6db 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -616,7 +616,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { self.check_safe_pointer(value, PointerKind::Ref(*mutbl))?; Ok(true) } - ty::FnPtr(_sig) => { + ty::FnPtr(..) => { let value = self.read_scalar(value, ExpectedKind::FnPtr)?; // If we check references recursively, also check that this points to a function. diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 780404212c3..d825a47bfdf 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -6,7 +6,6 @@ #![feature(box_patterns)] #![feature(decl_macro)] #![feature(if_let_guard)] -#![feature(is_none_or)] #![feature(let_chains)] #![feature(never_type)] #![feature(rustdoc_internals)] diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs index 3aa3b3b74e0..36c7bed5c11 100644 --- a/compiler/rustc_const_eval/src/util/type_name.rs +++ b/compiler/rustc_const_eval/src/util/type_name.rs @@ -35,7 +35,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { | ty::Slice(_) | ty::RawPtr(_, _) | ty::Ref(_, _, _) - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::Never | ty::Tuple(_) | ty::Dynamic(_, _, _) => self.pretty_print_type(ty), diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml index 3794a6e043c..69cbf8c4161 100644 --- a/compiler/rustc_data_structures/Cargo.toml +++ b/compiler/rustc_data_structures/Cargo.toml @@ -10,7 +10,7 @@ bitflags = "2.4.1" either = "1.0" elsa = "=1.7.1" ena = "0.14.3" -indexmap = { version = "2.0.0" } +indexmap = { version = "2.4.0" } jobserver_crate = { version = "0.1.28", package = "jobserver" } measureme = "11" rustc-hash = "1.1.0" diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 2b7dc040f64..e49ae60e890 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -7,6 +7,7 @@ // tidy-alphabetical-start #![allow(internal_features)] #![allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable +#![cfg_attr(bootstrap, feature(unsafe_extern_blocks))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(decl_macro)] @@ -15,6 +16,7 @@ #![feature(panic_update_hook)] #![feature(result_flattening)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use std::cmp::max; @@ -391,13 +393,17 @@ fn run_compiler( let linker = compiler.enter(|queries| { let early_exit = || early_exit().map(|_| None); + + // Parse the crate root source code (doesn't parse submodules yet) + // Everything else is parsed during macro expansion. queries.parse()?; - if let Some(ppm) = &sess.opts.pretty { - if ppm.needs_ast_map() { + // If pretty printing is requested: Figure out the representation, print it and exit + if let Some(pp_mode) = sess.opts.pretty { + if pp_mode.needs_ast_map() { queries.global_ctxt()?.enter(|tcx| { tcx.ensure().early_lint_checks(()); - pretty::print(sess, *ppm, pretty::PrintExtra::NeedsAstMap { tcx }); + pretty::print(sess, pp_mode, pretty::PrintExtra::NeedsAstMap { tcx }); Ok(()) })?; @@ -408,7 +414,7 @@ fn run_compiler( let krate = queries.parse()?; pretty::print( sess, - *ppm, + pp_mode, pretty::PrintExtra::AfterParsing { krate: &*krate.borrow() }, ); } @@ -463,12 +469,8 @@ fn run_compiler( linker.link(sess, codegen_backend)? } - if sess.opts.unstable_opts.print_fuel.is_some() { - eprintln!( - "Fuel used by {}: {}", - sess.opts.unstable_opts.print_fuel.as_ref().unwrap(), - sess.print_fuel.load(Ordering::SeqCst) - ); + if let Some(fuel) = sess.opts.unstable_opts.print_fuel.as_deref() { + eprintln!("Fuel used by {}: {}", fuel, sess.print_fuel.load(Ordering::SeqCst)); } Ok(()) @@ -485,36 +487,43 @@ fn make_output(matches: &getopts::Matches) -> (Option, Option Result, ErrorGuaranteed> { - let [ifile] = free_matches else { return Ok(None) }; - if ifile == "-" { - let mut src = String::new(); - if io::stdin().read_to_string(&mut src).is_err() { - // Immediately stop compilation if there was an issue reading - // the input (for example if the input stream is not UTF-8). - let reported = - early_dcx.early_err("couldn't read from stdin, as it did not contain valid UTF-8"); - return Err(reported); - } - if let Ok(path) = env::var("UNSTABLE_RUSTDOC_TEST_PATH") { + let [input_file] = free_matches else { return Ok(None) }; + + if input_file != "-" { + // Normal `Input::File` + return Ok(Some(Input::File(PathBuf::from(input_file)))); + } + + // read from stdin as `Input::Str` + let mut input = String::new(); + if io::stdin().read_to_string(&mut input).is_err() { + // Immediately stop compilation if there was an issue reading + // the input (for example if the input stream is not UTF-8). + let reported = + early_dcx.early_err("couldn't read from stdin, as it did not contain valid UTF-8"); + return Err(reported); + } + + let name = match env::var("UNSTABLE_RUSTDOC_TEST_PATH") { + Ok(path) => { let line = env::var("UNSTABLE_RUSTDOC_TEST_LINE").expect( "when UNSTABLE_RUSTDOC_TEST_PATH is set \ UNSTABLE_RUSTDOC_TEST_LINE also needs to be set", ); let line = isize::from_str_radix(&line, 10) .expect("UNSTABLE_RUSTDOC_TEST_LINE needs to be an number"); - let file_name = FileName::doc_test_source_code(PathBuf::from(path), line); - Ok(Some(Input::Str { name: file_name, input: src })) - } else { - Ok(Some(Input::Str { name: FileName::anon_source_code(&src), input: src })) + FileName::doc_test_source_code(PathBuf::from(path), line) } - } else { - Ok(Some(Input::File(PathBuf::from(ifile)))) - } + Err(_) => FileName::anon_source_code(&input), + }; + + Ok(Some(Input::Str { name, input })) } /// Whether to stop or continue compilation. diff --git a/compiler/rustc_driver_impl/src/signal_handler.rs b/compiler/rustc_driver_impl/src/signal_handler.rs index 51f2a508cf9..e1f868c2522 100644 --- a/compiler/rustc_driver_impl/src/signal_handler.rs +++ b/compiler/rustc_driver_impl/src/signal_handler.rs @@ -6,7 +6,7 @@ use std::{fmt, mem, ptr}; use rustc_interface::util::{DEFAULT_STACK_SIZE, STACK_SIZE}; -extern "C" { +unsafe extern "C" { fn backtrace_symbols_fd(buffer: *const *mut libc::c_void, size: libc::c_int, fd: libc::c_int); } diff --git a/compiler/rustc_error_codes/src/error_codes/E0745.md b/compiler/rustc_error_codes/src/error_codes/E0745.md index 23ee7af30f4..32b28f3de94 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0745.md +++ b/compiler/rustc_error_codes/src/error_codes/E0745.md @@ -3,7 +3,6 @@ The address of temporary value was taken. Erroneous code example: ```compile_fail,E0745 -# #![feature(raw_ref_op)] fn temp_address() { let ptr = &raw const 2; // error! } @@ -15,7 +14,6 @@ In this example, `2` is destroyed right after the assignment, which means that To avoid this error, first bind the temporary to a named local variable: ``` -# #![feature(raw_ref_op)] fn temp_address() { let val = 2; let ptr = &raw const val; // ok! diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs index 2a7bc2501c0..150f99a3ee7 100644 --- a/compiler/rustc_error_codes/src/lib.rs +++ b/compiler/rustc_error_codes/src/lib.rs @@ -6,6 +6,7 @@ #![deny(rustdoc::invalid_codeblock_attributes)] #![doc(rust_logo)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end // This higher-order macro defines the error codes that are in use. It is used diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 87dee2898da..e84d7be45d7 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -4,6 +4,7 @@ #![feature(rustc_attrs)] #![feature(rustdoc_internals)] #![feature(type_alias_impl_trait)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use std::borrow::Cow; diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml index 2fff9f2de50..59cf4e5f210 100644 --- a/compiler/rustc_errors/Cargo.toml +++ b/compiler/rustc_errors/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start -annotate-snippets = "0.10" +annotate-snippets = "0.11" derive_setters = "0.1.6" rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index df4e9792f95..d71ae9d210d 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -5,7 +5,7 @@ //! //! [annotate_snippets]: https://docs.rs/crate/annotate-snippets/ -use annotate_snippets::{Annotation, AnnotationType, Renderer, Slice, Snippet, SourceAnnotation}; +use annotate_snippets::{Renderer, Snippet}; use rustc_data_structures::sync::Lrc; use rustc_error_messages::FluentArgs; use rustc_span::source_map::SourceMap; @@ -83,15 +83,17 @@ fn source_string(file: Lrc, line: &Line) -> String { file.get_line(line.line_index - 1).map(|a| a.to_string()).unwrap_or_default() } -/// Maps `diagnostic::Level` to `snippet::AnnotationType` -fn annotation_type_for_level(level: Level) -> AnnotationType { +/// Maps [`crate::Level`] to [`annotate_snippets::Level`] +fn annotation_level_for_level(level: Level) -> annotate_snippets::Level { match level { - Level::Bug | Level::Fatal | Level::Error | Level::DelayedBug => AnnotationType::Error, - Level::ForceWarning(_) | Level::Warning => AnnotationType::Warning, - Level::Note | Level::OnceNote => AnnotationType::Note, - Level::Help | Level::OnceHelp => AnnotationType::Help, + Level::Bug | Level::Fatal | Level::Error | Level::DelayedBug => { + annotate_snippets::Level::Error + } + Level::ForceWarning(_) | Level::Warning => annotate_snippets::Level::Warning, + Level::Note | Level::OnceNote => annotate_snippets::Level::Note, + Level::Help | Level::OnceHelp => annotate_snippets::Level::Help, // FIXME(#59346): Not sure how to map this level - Level::FailureNote => AnnotationType::Error, + Level::FailureNote => annotate_snippets::Level::Error, Level::Allow => panic!("Should not call with Allow"), Level::Expect(_) => panic!("Should not call with Expect"), } @@ -180,42 +182,29 @@ impl AnnotateSnippetEmitter { }) .collect(); let code = code.map(|code| code.to_string()); - let snippet = Snippet { - title: Some(Annotation { - label: Some(&message), - id: code.as_deref(), - annotation_type: annotation_type_for_level(*level), - }), - footer: vec![], - slices: annotated_files - .iter() - .map(|(file_name, source, line_index, annotations)| { - Slice { - source, - line_start: *line_index, - origin: Some(file_name), - // FIXME(#59346): Not really sure when `fold` should be true or false - fold: false, - annotations: annotations - .iter() - .map(|annotation| SourceAnnotation { - range: ( - annotation.start_col.display, - annotation.end_col.display, - ), - label: annotation.label.as_deref().unwrap_or_default(), - annotation_type: annotation_type_for_level(*level), - }) - .collect(), - } - }) - .collect(), - }; + + let snippets = + annotated_files.iter().map(|(file_name, source, line_index, annotations)| { + Snippet::source(source) + .line_start(*line_index) + .origin(file_name) + // FIXME(#59346): Not really sure when `fold` should be true or false + .fold(false) + .annotations(annotations.iter().map(|annotation| { + annotation_level_for_level(*level) + .span(annotation.start_col.display..annotation.end_col.display) + .label(annotation.label.as_deref().unwrap_or_default()) + })) + }); + let mut message = annotation_level_for_level(*level).title(&message).snippets(snippets); + if let Some(code) = code.as_deref() { + message = message.id(code) + } // FIXME(#59346): Figure out if we can _always_ print to stderr or not. // `emitter.rs` has the `Destination` enum that lists various possible output // destinations. let renderer = Renderer::plain().anonymized_line_numbers(self.ui_testing); - eprintln!("{}", renderer.render(snippet)) + eprintln!("{}", renderer.render(message)) } // FIXME(#59346): Is it ok to return None if there's no source_map? } diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index fae8b5647fc..3303e4ee752 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -204,7 +204,7 @@ pub trait LintDiagnostic<'a, G: EmissionGuarantee> { } #[derive(Clone, Debug, Encodable, Decodable)] -pub struct DiagLocation { +pub(crate) struct DiagLocation { file: Cow<'static, str>, line: u32, col: u32, diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 9ce5d77ef6c..2bc29dabd18 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -2387,7 +2387,7 @@ enum DisplaySuggestion { impl FileWithAnnotatedLines { /// Preprocess all the annotations so that they are grouped by file and by line number /// This helps us quickly iterate over the whole message (including secondary file spans) - pub fn collect_annotations( + pub(crate) fn collect_annotations( emitter: &dyn Emitter, args: &FluentArgs<'_>, msp: &MultiSpan, diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 3bc03a1e516..99ee8fb17d7 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -25,6 +25,7 @@ #![feature(trait_alias)] #![feature(try_blocks)] #![feature(yeet_expr)] +#![warn(unreachable_pub)] // tidy-alphabetical-end extern crate self as rustc_errors; @@ -1701,7 +1702,7 @@ impl DiagCtxtInner { } /// Translate `message` eagerly with `args` to `SubdiagMessage::Eager`. - pub fn eagerly_translate<'a>( + fn eagerly_translate<'a>( &self, message: DiagMessage, args: impl Iterator>, @@ -1710,7 +1711,7 @@ impl DiagCtxtInner { } /// Translate `message` eagerly with `args` to `String`. - pub fn eagerly_translate_to_string<'a>( + fn eagerly_translate_to_string<'a>( &self, message: DiagMessage, args: impl Iterator>, @@ -1837,23 +1838,23 @@ impl DelayedDiagInner { } } -/// Level is_error EmissionGuarantee Top-level Sub Used in lints? -/// ----- -------- ----------------- --------- --- -------------- -/// Bug yes BugAbort yes - - -/// Fatal yes FatalAbort/FatalError(*) yes - - -/// Error yes ErrorGuaranteed yes - yes -/// DelayedBug yes ErrorGuaranteed yes - - -/// ForceWarning - () yes - lint-only -/// Warning - () yes yes yes -/// Note - () rare yes - -/// OnceNote - () - yes lint-only -/// Help - () rare yes - -/// OnceHelp - () - yes lint-only -/// FailureNote - () rare - - -/// Allow - () yes - lint-only -/// Expect - () yes - lint-only +/// | Level | is_error | EmissionGuarantee | Top-level | Sub | Used in lints? +/// | ----- | -------- | ----------------- | --------- | --- | -------------- +/// | Bug | yes | BugAbort | yes | - | - +/// | Fatal | yes | FatalAbort/FatalError[^star] | yes | - | - +/// | Error | yes | ErrorGuaranteed | yes | - | yes +/// | DelayedBug | yes | ErrorGuaranteed | yes | - | - +/// | ForceWarning | - | () | yes | - | lint-only +/// | Warning | - | () | yes | yes | yes +/// | Note | - | () | rare | yes | - +/// | OnceNote | - | () | - | yes | lint-only +/// | Help | - | () | rare | yes | - +/// | OnceHelp | - | () | - | yes | lint-only +/// | FailureNote | - | () | rare | - | - +/// | Allow | - | () | yes | - | lint-only +/// | Expect | - | () | yes | - | lint-only /// -/// (*) `FatalAbort` normally, `FatalError` in the non-aborting "almost fatal" case that is +/// [^star]: `FatalAbort` normally, `FatalError` in the non-aborting "almost fatal" case that is /// occasionally used. /// #[derive(Copy, PartialEq, Eq, Clone, Hash, Debug, Encodable, Decodable)] diff --git a/compiler/rustc_errors/src/lock.rs b/compiler/rustc_errors/src/lock.rs index 915542c9092..7557969f374 100644 --- a/compiler/rustc_errors/src/lock.rs +++ b/compiler/rustc_errors/src/lock.rs @@ -12,7 +12,7 @@ use std::any::Any; #[cfg(windows)] -pub fn acquire_global_lock(name: &str) -> Box { +pub(crate) fn acquire_global_lock(name: &str) -> Box { use std::ffi::CString; use std::io; @@ -80,6 +80,6 @@ pub fn acquire_global_lock(name: &str) -> Box { } #[cfg(not(windows))] -pub fn acquire_global_lock(_name: &str) -> Box { +pub(crate) fn acquire_global_lock(_name: &str) -> Box { Box::new(()) } diff --git a/compiler/rustc_errors/src/markdown/parse.rs b/compiler/rustc_errors/src/markdown/parse.rs index c44f136120a..b1db44dd215 100644 --- a/compiler/rustc_errors/src/markdown/parse.rs +++ b/compiler/rustc_errors/src/markdown/parse.rs @@ -74,13 +74,13 @@ enum ParseOpt { } /// Parse a buffer -pub fn entrypoint(txt: &str) -> MdStream<'_> { +pub(crate) fn entrypoint(txt: &str) -> MdStream<'_> { let ctx = Context { top_block: true, prev: Prev::Newline }; normalize(parse_recursive(txt.trim().as_bytes(), ctx), &mut Vec::new()) } /// Parse a buffer with specified context -fn parse_recursive<'a>(buf: &'a [u8], ctx: Context) -> MdStream<'_> { +fn parse_recursive<'a>(buf: &'a [u8], ctx: Context) -> MdStream<'a> { use ParseOpt as Po; use Prev::{Escape, Newline, Whitespace}; diff --git a/compiler/rustc_errors/src/markdown/term.rs b/compiler/rustc_errors/src/markdown/term.rs index 06c1333d93d..579e00b8b85 100644 --- a/compiler/rustc_errors/src/markdown/term.rs +++ b/compiler/rustc_errors/src/markdown/term.rs @@ -15,7 +15,7 @@ thread_local! { } /// Print to terminal output to a buffer -pub fn entrypoint(stream: &MdStream<'_>, buf: &mut Buffer) -> io::Result<()> { +pub(crate) fn entrypoint(stream: &MdStream<'_>, buf: &mut Buffer) -> io::Result<()> { #[cfg(not(test))] if let Some((w, _)) = termize::dimensions() { WIDTH.with(|c| c.set(std::cmp::min(w, DEFAULT_COLUMN_WIDTH))); @@ -47,7 +47,7 @@ fn write_stream( Ok(()) } -pub fn write_tt(tt: &MdTree<'_>, buf: &mut Buffer, indent: usize) -> io::Result<()> { +fn write_tt(tt: &MdTree<'_>, buf: &mut Buffer, indent: usize) -> io::Result<()> { match tt { MdTree::CodeBlock { txt, lang: _ } => { buf.set_color(ColorSpec::new().set_dimmed(true))?; diff --git a/compiler/rustc_errors/src/snippet.rs b/compiler/rustc_errors/src/snippet.rs index 50abf8a49c2..8485d7087cf 100644 --- a/compiler/rustc_errors/src/snippet.rs +++ b/compiler/rustc_errors/src/snippet.rs @@ -5,13 +5,13 @@ use rustc_macros::{Decodable, Encodable}; use crate::{Level, Loc}; #[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)] -pub struct Line { +pub(crate) struct Line { pub line_index: usize, pub annotations: Vec, } #[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq, Default)] -pub struct AnnotationColumn { +pub(crate) struct AnnotationColumn { /// the (0-indexed) column for *display* purposes, counted in characters, not utf-8 bytes pub display: usize, /// the (0-indexed) column in the file, counted in characters, not utf-8 bytes. @@ -31,13 +31,13 @@ pub struct AnnotationColumn { } impl AnnotationColumn { - pub fn from_loc(loc: &Loc) -> AnnotationColumn { + pub(crate) fn from_loc(loc: &Loc) -> AnnotationColumn { AnnotationColumn { display: loc.col_display, file: loc.col.0 } } } #[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)] -pub struct MultilineAnnotation { +pub(crate) struct MultilineAnnotation { pub depth: usize, pub line_start: usize, pub line_end: usize, @@ -49,19 +49,19 @@ pub struct MultilineAnnotation { } impl MultilineAnnotation { - pub fn increase_depth(&mut self) { + pub(crate) fn increase_depth(&mut self) { self.depth += 1; } /// Compare two `MultilineAnnotation`s considering only the `Span` they cover. - pub fn same_span(&self, other: &MultilineAnnotation) -> bool { + pub(crate) fn same_span(&self, other: &MultilineAnnotation) -> bool { self.line_start == other.line_start && self.line_end == other.line_end && self.start_col == other.start_col && self.end_col == other.end_col } - pub fn as_start(&self) -> Annotation { + pub(crate) fn as_start(&self) -> Annotation { Annotation { start_col: self.start_col, end_col: AnnotationColumn { @@ -76,7 +76,7 @@ impl MultilineAnnotation { } } - pub fn as_end(&self) -> Annotation { + pub(crate) fn as_end(&self) -> Annotation { Annotation { start_col: AnnotationColumn { // these might not correspond to the same place anymore, @@ -91,7 +91,7 @@ impl MultilineAnnotation { } } - pub fn as_line(&self) -> Annotation { + pub(crate) fn as_line(&self) -> Annotation { Annotation { start_col: Default::default(), end_col: Default::default(), @@ -103,7 +103,7 @@ impl MultilineAnnotation { } #[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)] -pub enum AnnotationType { +pub(crate) enum AnnotationType { /// Annotation under a single line of code Singleline, @@ -129,7 +129,7 @@ pub enum AnnotationType { } #[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)] -pub struct Annotation { +pub(crate) struct Annotation { /// Start column. /// Note that it is important that this field goes /// first, so that when we sort, we sort orderings by start @@ -152,12 +152,12 @@ pub struct Annotation { impl Annotation { /// Whether this annotation is a vertical line placeholder. - pub fn is_line(&self) -> bool { + pub(crate) fn is_line(&self) -> bool { matches!(self.annotation_type, AnnotationType::MultilineLine(_)) } /// Length of this annotation as displayed in the stderr output - pub fn len(&self) -> usize { + pub(crate) fn len(&self) -> usize { // Account for usize underflows if self.end_col.display > self.start_col.display { self.end_col.display - self.start_col.display @@ -166,7 +166,7 @@ impl Annotation { } } - pub fn has_label(&self) -> bool { + pub(crate) fn has_label(&self) -> bool { if let Some(ref label) = self.label { // Consider labels with no text as effectively not being there // to avoid weird output with unnecessary vertical lines, like: @@ -184,7 +184,7 @@ impl Annotation { } } - pub fn takes_space(&self) -> bool { + pub(crate) fn takes_space(&self) -> bool { // Multiline annotations always have to keep vertical space. matches!( self.annotation_type, @@ -194,7 +194,7 @@ impl Annotation { } #[derive(Debug)] -pub struct StyledString { +pub(crate) struct StyledString { pub text: String, pub style: Style, } diff --git a/compiler/rustc_errors/src/styled_buffer.rs b/compiler/rustc_errors/src/styled_buffer.rs index 9aa14e1f214..5ca9e9b18f3 100644 --- a/compiler/rustc_errors/src/styled_buffer.rs +++ b/compiler/rustc_errors/src/styled_buffer.rs @@ -3,7 +3,7 @@ use crate::snippet::{Style, StyledString}; #[derive(Debug)] -pub struct StyledBuffer { +pub(crate) struct StyledBuffer { lines: Vec>, } @@ -22,12 +22,12 @@ impl StyledChar { } impl StyledBuffer { - pub fn new() -> StyledBuffer { + pub(crate) fn new() -> StyledBuffer { StyledBuffer { lines: vec![] } } /// Returns content of `StyledBuffer` split by lines and line styles - pub fn render(&self) -> Vec> { + pub(crate) fn render(&self) -> Vec> { // Tabs are assumed to have been replaced by spaces in calling code. debug_assert!(self.lines.iter().all(|r| !r.iter().any(|sc| sc.chr == '\t'))); @@ -70,7 +70,7 @@ impl StyledBuffer { /// Sets `chr` with `style` for given `line`, `col`. /// If `line` does not exist in our buffer, adds empty lines up to the given /// and fills the last line with unstyled whitespace. - pub fn putc(&mut self, line: usize, col: usize, chr: char, style: Style) { + pub(crate) fn putc(&mut self, line: usize, col: usize, chr: char, style: Style) { self.ensure_lines(line); if col >= self.lines[line].len() { self.lines[line].resize(col + 1, StyledChar::SPACE); @@ -81,7 +81,7 @@ impl StyledBuffer { /// Sets `string` with `style` for given `line`, starting from `col`. /// If `line` does not exist in our buffer, adds empty lines up to the given /// and fills the last line with unstyled whitespace. - pub fn puts(&mut self, line: usize, col: usize, string: &str, style: Style) { + pub(crate) fn puts(&mut self, line: usize, col: usize, string: &str, style: Style) { let mut n = col; for c in string.chars() { self.putc(line, n, c, style); @@ -91,7 +91,7 @@ impl StyledBuffer { /// For given `line` inserts `string` with `style` before old content of that line, /// adding lines if needed - pub fn prepend(&mut self, line: usize, string: &str, style: Style) { + pub(crate) fn prepend(&mut self, line: usize, string: &str, style: Style) { self.ensure_lines(line); let string_len = string.chars().count(); @@ -107,7 +107,7 @@ impl StyledBuffer { /// For given `line` inserts `string` with `style` after old content of that line, /// adding lines if needed - pub fn append(&mut self, line: usize, string: &str, style: Style) { + pub(crate) fn append(&mut self, line: usize, string: &str, style: Style) { if line >= self.lines.len() { self.puts(line, 0, string, style); } else { @@ -116,14 +116,14 @@ impl StyledBuffer { } } - pub fn num_lines(&self) -> usize { + pub(crate) fn num_lines(&self) -> usize { self.lines.len() } /// Set `style` for `line`, `col_start..col_end` range if: /// 1. That line and column range exist in `StyledBuffer` /// 2. `overwrite` is `true` or existing style is `Style::NoStyle` or `Style::Quotation` - pub fn set_style_range( + pub(crate) fn set_style_range( &mut self, line: usize, col_start: usize, @@ -139,7 +139,7 @@ impl StyledBuffer { /// Set `style` for `line`, `col` if: /// 1. That line and column exist in `StyledBuffer` /// 2. `overwrite` is `true` or existing style is `Style::NoStyle` or `Style::Quotation` - pub fn set_style(&mut self, line: usize, col: usize, style: Style, overwrite: bool) { + fn set_style(&mut self, line: usize, col: usize, style: Style, overwrite: bool) { if let Some(ref mut line) = self.lines.get_mut(line) { if let Some(StyledChar { style: s, .. }) = line.get_mut(col) { if overwrite || matches!(s, Style::NoStyle | Style::Quotation) { diff --git a/compiler/rustc_errors/src/translation.rs b/compiler/rustc_errors/src/translation.rs index a44e794ee12..e0b64b276eb 100644 --- a/compiler/rustc_errors/src/translation.rs +++ b/compiler/rustc_errors/src/translation.rs @@ -59,7 +59,7 @@ pub trait Translate { &'a self, message: &'a DiagMessage, args: &'a FluentArgs<'_>, - ) -> Result, TranslateError<'_>> { + ) -> Result, TranslateError<'a>> { trace!(?message, ?args); let (identifier, attr) = match message { DiagMessage::Str(msg) | DiagMessage::Translated(msg) => { diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index f6bf9f5e89f..b0d3fecbb47 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -265,12 +265,7 @@ impl<'a> StripUnconfigured<'a> { /// is in the original source file. Gives a compiler error if the syntax of /// the attribute is incorrect. pub(crate) fn expand_cfg_attr(&self, cfg_attr: &Attribute, recursive: bool) -> Vec { - validate_attr::check_attribute_safety( - self.features.unwrap_or(&Features::default()), - &self.sess.psess, - AttributeSafety::Normal, - &cfg_attr, - ); + validate_attr::check_attribute_safety(&self.sess.psess, AttributeSafety::Normal, &cfg_attr); let Some((cfg_predicate, expanded_attrs)) = rustc_parse::parse_cfg_attr(cfg_attr, &self.sess.psess) @@ -395,11 +390,7 @@ impl<'a> StripUnconfigured<'a> { } }; - validate_attr::deny_builtin_meta_unsafety( - self.features.unwrap_or(&Features::default()), - &self.sess.psess, - &meta_item, - ); + validate_attr::deny_builtin_meta_unsafety(&self.sess.psess, &meta_item); ( parse_cfg(&meta_item, self.sess).map_or(true, |meta_item| { diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index c30a9b0c357..0fdccb08918 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -281,7 +281,7 @@ pub(crate) struct IncompleteParse<'a> { pub macro_path: &'a ast::Path, pub kind_name: &'a str, #[note(expand_macro_expands_to_match_arm)] - pub expands_to_match_arm: Option<()>, + pub expands_to_match_arm: bool, #[suggestion( expand_suggestion_add_semi, @@ -350,7 +350,7 @@ pub(crate) struct ModuleMultipleCandidates { #[derive(Diagnostic)] #[diag(expand_trace_macro)] -pub struct TraceMacro { +pub(crate) struct TraceMacro { #[primary_span] pub span: Span, } @@ -402,14 +402,14 @@ pub(crate) struct CustomAttributePanickedHelp { #[derive(Diagnostic)] #[diag(expand_proc_macro_derive_tokens)] -pub struct ProcMacroDeriveTokens { +pub(crate) struct ProcMacroDeriveTokens { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(expand_duplicate_matcher_binding)] -pub struct DuplicateMatcherBinding { +pub(crate) struct DuplicateMatcherBinding { #[primary_span] #[label] pub span: Span, @@ -421,7 +421,7 @@ pub struct DuplicateMatcherBinding { #[diag(expand_missing_fragment_specifier)] #[note] #[help(expand_valid)] -pub struct MissingFragmentSpecifier { +pub(crate) struct MissingFragmentSpecifier { #[primary_span] pub span: Span, #[suggestion( @@ -437,7 +437,7 @@ pub struct MissingFragmentSpecifier { #[derive(Diagnostic)] #[diag(expand_invalid_fragment_specifier)] #[help] -pub struct InvalidFragmentSpecifier { +pub(crate) struct InvalidFragmentSpecifier { #[primary_span] pub span: Span, pub fragment: Ident, @@ -446,7 +446,7 @@ pub struct InvalidFragmentSpecifier { #[derive(Diagnostic)] #[diag(expand_expected_paren_or_brace)] -pub struct ExpectedParenOrBrace<'a> { +pub(crate) struct ExpectedParenOrBrace<'a> { #[primary_span] pub span: Span, pub token: Cow<'a, str>, @@ -479,7 +479,7 @@ pub(crate) struct GlobDelegationTraitlessQpath { #[derive(Diagnostic)] #[diag(expand_proc_macro_back_compat)] #[note] -pub struct ProcMacroBackCompat { +pub(crate) struct ProcMacroBackCompat { pub crate_name: String, pub fixed_version: String, } diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 37679e17b90..0d56a005f15 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1031,7 +1031,7 @@ pub(crate) fn ensure_complete_parse<'a>( label_span: span, macro_path, kind_name, - expands_to_match_arm: expands_to_match_arm.then_some(()), + expands_to_match_arm, add_semicolon, }); } @@ -1882,7 +1882,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { let mut span: Option = None; while let Some(attr) = attrs.next() { rustc_ast_passes::feature_gate::check_attribute(attr, self.cx.sess, features); - validate_attr::check_attr(features, &self.cx.sess.psess, attr); + validate_attr::check_attr(&self.cx.sess.psess, attr); let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span }; span = Some(current_span); diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index 4222c9fe906..777044e3f33 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -13,6 +13,7 @@ #![feature(rustdoc_internals)] #![feature(try_blocks)] #![feature(yeet_expr)] +#![warn(unreachable_pub)] // tidy-alphabetical-end extern crate proc_macro as pm; diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs index 628c6bfeb79..5778f661622 100644 --- a/compiler/rustc_expand/src/mbe/diagnostics.rs +++ b/compiler/rustc_expand/src/mbe/diagnostics.rs @@ -196,13 +196,14 @@ impl<'dcx> CollectTrackerAndEmitter<'dcx, '_> { } } -/// Currently used by macro_rules! compilation to extract a little information from the `Failure` case. -pub struct FailureForwarder<'matcher> { +/// Currently used by macro_rules! compilation to extract a little information from the `Failure` +/// case. +pub(crate) struct FailureForwarder<'matcher> { expected_token: Option<&'matcher Token>, } impl<'matcher> FailureForwarder<'matcher> { - pub fn new() -> Self { + pub(crate) fn new() -> Self { Self { expected_token: None } } } diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index e5b9c627429..9011d02da33 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -407,7 +407,7 @@ fn token_name_eq(t1: &Token, t2: &Token) -> bool { // Note: the vectors could be created and dropped within `parse_tt`, but to avoid excess // allocations we have a single vector for each kind that is cleared and reused repeatedly. -pub struct TtParser { +pub(crate) struct TtParser { macro_name: Ident, /// The set of current mps to be processed. This should be empty by the end of a successful diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 6f177107e70..256713ef730 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -1154,7 +1154,7 @@ fn check_matcher_core<'tt>( && matches!(kind, NonterminalKind::Pat(PatParam { inferred: true })) && matches!( next_token, - TokenTree::Token(token) if token.kind == BinOp(token::BinOpToken::Or) + TokenTree::Token(token) if *token == BinOp(token::BinOpToken::Or) ) { // It is suggestion to use pat_param, for example: $x:pat -> $x:pat_param. diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index e5a1c6c7899..5df0aebfe57 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -14,12 +14,11 @@ use crate::mbe::macro_parser::count_metavar_decls; use crate::mbe::{Delimited, KleeneOp, KleeneToken, MetaVarExpr, SequenceRepetition, TokenTree}; const VALID_FRAGMENT_NAMES_MSG: &str = "valid fragment specifiers are \ - `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, \ - `literal`, `path`, `meta`, `tt`, `item` and `vis`"; -pub const VALID_FRAGMENT_NAMES_MSG_2021: &str = "valid fragment specifiers are \ - `ident`, `block`, `stmt`, `expr`, `expr_2021`, `pat`, \ - `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, \ - `item` and `vis`"; + `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, \ + `item` and `vis`"; +pub(crate) const VALID_FRAGMENT_NAMES_MSG_2021: &str = "valid fragment specifiers are \ + `ident`, `block`, `stmt`, `expr`, `expr_2021`, `pat`, `ty`, `lifetime`, `literal`, `path`, \ + `meta`, `tt`, `item` and `vis`"; /// Takes a `tokenstream::TokenStream` and returns a `Vec`. Specifically, this /// takes a generic `TokenStream`, such as is used in the rest of the compiler, and returns a @@ -54,18 +53,24 @@ pub(super) fn parse( // For each token tree in `input`, parse the token into a `self::TokenTree`, consuming // additional trees if need be. - let mut trees = input.trees(); + let mut trees = input.trees().peekable(); while let Some(tree) = trees.next() { // Given the parsed tree, if there is a metavar and we are expecting matchers, actually // parse out the matcher (i.e., in `$id:ident` this would parse the `:` and `ident`). let tree = parse_tree(tree, &mut trees, parsing_patterns, sess, node_id, features, edition); match tree { TokenTree::MetaVar(start_sp, ident) if parsing_patterns => { - let span = match trees.next() { + // Not consuming the next token immediately, as it may not be a colon + let span = match trees.peek() { Some(&tokenstream::TokenTree::Token( Token { kind: token::Colon, span: colon_span }, _, )) => { + // Consume the colon first + trees.next(); + + // It's ok to consume the next tree no matter how, + // since if it's not a token then it will be an invalid declaration. match trees.next() { Some(tokenstream::TokenTree::Token(token, _)) => match token.ident() { Some((fragment, _)) => { @@ -125,12 +130,13 @@ pub(super) fn parse( } _ => token.span, }, - Some(tree) => tree.span(), - None => colon_span, + // Invalid, return a nice source location + _ => colon_span.with_lo(start_sp.lo()), } } - Some(tree) => tree.span(), - None => start_sp, + // Whether it's none or some other tree, it doesn't belong to + // the current meta variable, returning the original span. + _ => start_sp, }; result.push(TokenTree::MetaVarDecl(span, ident, None)); diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs index 1e455d465e4..469bed3cd59 100644 --- a/compiler/rustc_expand/src/placeholders.rs +++ b/compiler/rustc_expand/src/placeholders.rs @@ -191,12 +191,12 @@ pub(crate) fn placeholder( } #[derive(Default)] -pub struct PlaceholderExpander { +pub(crate) struct PlaceholderExpander { expanded_fragments: FxHashMap, } impl PlaceholderExpander { - pub fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment) { + pub(crate) fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment) { fragment.mut_visit_with(self); self.expanded_fragments.insert(id, fragment); } diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 1438d1ad11f..4ff5da1a4bd 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -414,7 +414,7 @@ impl ToInternal for Level { } } -pub struct FreeFunctions; +pub(crate) struct FreeFunctions; pub(crate) struct Rustc<'a, 'b> { ecx: &'a mut ExtCtxt<'b>, @@ -426,7 +426,7 @@ pub(crate) struct Rustc<'a, 'b> { } impl<'a, 'b> Rustc<'a, 'b> { - pub fn new(ecx: &'a mut ExtCtxt<'b>) -> Self { + pub(crate) fn new(ecx: &'a mut ExtCtxt<'b>) -> Self { let expn_data = ecx.current_expansion.id.expn_data(); Rustc { def_site: ecx.with_def_site_ctxt(expn_data.def_site), diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 44286cfeeef..9223c3c322a 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -60,6 +60,8 @@ declare_features! ( (accepted, adx_target_feature, "1.61.0", Some(44839)), /// Allows explicit discriminants on non-unit enum variants. (accepted, arbitrary_enum_discriminant, "1.66.0", Some(60553)), + /// Allows using `const` operands in inline assembly. + (accepted, asm_const, "CURRENT_RUSTC_VERSION", Some(93332)), /// Allows using `sym` operands in inline assembly. (accepted, asm_sym, "1.66.0", Some(93333)), /// Allows the definition of associated constants in `trait` or `impl` blocks. @@ -113,6 +115,8 @@ declare_features! ( (accepted, conservative_impl_trait, "1.26.0", Some(34511)), /// Allows calling constructor functions in `const fn`. (accepted, const_constructor, "1.40.0", Some(61456)), + /// Allows basic arithmetic on floating point types in a `const fn`. + (accepted, const_fn_floating_point_arithmetic, "CURRENT_RUSTC_VERSION", Some(57241)), /// Allows using and casting function pointers in a `const fn`. (accepted, const_fn_fn_ptr_basics, "1.61.0", Some(57563)), /// Allows trait bounds in `const fn`. @@ -307,6 +311,8 @@ declare_features! ( (accepted, param_attrs, "1.39.0", Some(60406)), /// Allows parentheses in patterns. (accepted, pattern_parentheses, "1.31.0", Some(51087)), + /// Allows `use<'a, 'b, A, B>` in `impl Trait + use<...>` for precise capture of generic args. + (accepted, precise_capturing, "CURRENT_RUSTC_VERSION", Some(123432)), /// Allows procedural macros in `proc-macro` crates. (accepted, proc_macro, "1.29.0", Some(38356)), /// Allows multi-segment paths in attributes and derives. @@ -319,6 +325,8 @@ declare_features! ( (accepted, raw_dylib, "1.71.0", Some(58713)), /// Allows keywords to be escaped for use as identifiers. (accepted, raw_identifiers, "1.30.0", Some(48589)), + /// Allows `&raw const $place_expr` and `&raw mut $place_expr` expressions. + (accepted, raw_ref_op, "CURRENT_RUSTC_VERSION", Some(64490)), /// Allows relaxing the coherence rules such that /// `impl ForeignTrait for ForeignType` is permitted. (accepted, re_rebalance_coherence, "1.41.0", Some(55437)), @@ -390,6 +398,8 @@ declare_features! ( (accepted, universal_impl_trait, "1.26.0", Some(34511)), /// Allows arbitrary delimited token streams in non-macro attributes. (accepted, unrestricted_attribute_tokens, "1.34.0", Some(55208)), + /// Allows unsafe attributes. + (accepted, unsafe_attributes, "CURRENT_RUSTC_VERSION", Some(123757)), /// The `unsafe_op_in_unsafe_fn` lint (allowed by default): no longer treat an unsafe function as an unsafe block. (accepted, unsafe_block_in_unsafe_fn, "1.52.0", Some(71668)), /// Allows unsafe on extern declarations and safety qualifiers over internal items. diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 72ea55d5999..2747a14d60a 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -578,12 +578,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ EncodeCrossCrate::No, coroutines, experimental!(coroutines) ), - // `#[pointee]` attribute to designate the pointee type in SmartPointer derive-macro - gated!( - pointee, Normal, template!(Word), ErrorFollowing, - EncodeCrossCrate::No, derive_smart_pointer, experimental!(pointee) - ), - // RFC 3543 // `#[patchable_function_entry(prefix_nops = m, entry_nops = n)]` gated!( @@ -643,10 +637,15 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ through unstable paths" ), rustc_attr!( - rustc_deprecated_safe_2024, Normal, template!(Word), WarnFollowing, - EncodeCrossCrate::Yes, + rustc_deprecated_safe_2024, Normal, template!(List: r#"audit_that = "...""#), + ErrorFollowing, EncodeCrossCrate::Yes, "rustc_deprecated_safe_2024 is supposed to be used in libstd only", ), + rustc_attr!( + rustc_pub_transparent, Normal, template!(Word), + WarnFollowing, EncodeCrossCrate::Yes, + "used internally to mark types with a `transparent` representation when it is guaranteed by the documentation", + ), // ========================================================================== diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs index dcc1c3202ea..adaaba3cd23 100644 --- a/compiler/rustc_feature/src/lib.rs +++ b/compiler/rustc_feature/src/lib.rs @@ -15,6 +15,7 @@ #![allow(internal_features)] #![doc(rust_logo)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end mod accepted; diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 47810bc9165..f7ddc3e2c56 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -193,6 +193,8 @@ declare_features! ( (unstable, anonymous_lifetime_in_impl_trait, "1.63.0", None), /// Allows identifying the `compiler_builtins` crate. (internal, compiler_builtins, "1.13.0", None), + /// Gating for a new desugaring of const arguments of usages of const parameters + (internal, const_arg_path, "1.81.0", None), /// Allows writing custom MIR (internal, custom_mir, "1.65.0", None), /// Outputs useful `assert!` messages @@ -300,6 +302,7 @@ declare_features! ( // FIXME: Document these and merge with the list below. // Unstable `#[target_feature]` directives. + (unstable, aarch64_unstable_target_feature, "CURRENT_RUSTC_VERSION", Some(44839)), (unstable, aarch64_ver_target_feature, "1.27.0", Some(44839)), (unstable, arm_target_feature, "1.27.0", Some(44839)), (unstable, avx512_target_feature, "1.27.0", Some(44839)), @@ -348,8 +351,6 @@ declare_features! ( (unstable, alloc_error_handler, "1.29.0", Some(51540)), /// Allows trait methods with arbitrary self types. (unstable, arbitrary_self_types, "1.23.0", Some(44874)), - /// Allows using `const` operands in inline assembly. - (unstable, asm_const, "1.58.0", Some(93332)), /// Enables experimental inline assembly support for additional architectures. (unstable, asm_experimental_arch, "1.58.0", Some(93335)), /// Allows using `label` operands in inline assembly. @@ -402,8 +403,6 @@ declare_features! ( (incomplete, const_closures, "1.68.0", Some(106003)), /// Allows the definition of `const extern fn` and `const unsafe extern fn`. (unstable, const_extern_fn, "1.40.0", Some(64926)), - /// Allows basic arithmetic on floating point types in a `const fn`. - (unstable, const_fn_floating_point_arithmetic, "1.48.0", Some(57241)), /// Allows `for _ in _` loops in const contexts. (unstable, const_for, "1.56.0", Some(87575)), /// Allows using `&mut` in constant functions. @@ -563,12 +562,8 @@ declare_features! ( (unstable, patchable_function_entry, "1.81.0", Some(123115)), /// Allows postfix match `expr.match { ... }` (unstable, postfix_match, "1.79.0", Some(121618)), - /// Allows `use<'a, 'b, A, B>` in `impl Trait + use<...>` for precise capture of generic args. - (unstable, precise_capturing, "1.79.0", Some(123432)), /// Allows macro attributes on expressions, statements and non-inline modules. (unstable, proc_macro_hygiene, "1.30.0", Some(54727)), - /// Allows `&raw const $place_expr` and `&raw mut $place_expr` expressions. - (unstable, raw_ref_op, "1.41.0", Some(64490)), /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024. (incomplete, ref_pat_eat_one_layer_2024, "1.79.0", Some(123076)), /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024—structural variant @@ -600,6 +595,8 @@ declare_features! ( (unstable, strict_provenance, "1.61.0", Some(95228)), /// Allows string patterns to dereference values to match them. (unstable, string_deref_patterns, "1.67.0", Some(87121)), + /// Allows structs to carry target_feature information. + (incomplete, struct_target_features, "CURRENT_RUSTC_VERSION", Some(129107)), /// Allows the use of `#[target_feature]` on safe functions. (unstable, target_feature_11, "1.45.0", Some(69098)), /// Allows using `#[thread_local]` on `static` items. @@ -624,8 +621,6 @@ declare_features! ( (unstable, type_changing_struct_update, "1.58.0", Some(86555)), /// Allows unnamed fields of struct and union type (incomplete, unnamed_fields, "1.74.0", Some(49804)), - /// Allows unsafe attributes. - (unstable, unsafe_attributes, "1.80.0", Some(123757)), /// Allows const generic parameters to be defined with types that /// are not `Sized`, e.g. `fn foo() {`. (incomplete, unsized_const_params, "CURRENT_RUSTC_VERSION", Some(95174)), diff --git a/compiler/rustc_fluent_macro/Cargo.toml b/compiler/rustc_fluent_macro/Cargo.toml index c5a53ae8313..eeceaa4691a 100644 --- a/compiler/rustc_fluent_macro/Cargo.toml +++ b/compiler/rustc_fluent_macro/Cargo.toml @@ -8,7 +8,7 @@ proc-macro = true [dependencies] # tidy-alphabetical-start -annotate-snippets = "0.10" +annotate-snippets = "0.11" fluent-bundle = "0.15.2" fluent-syntax = "0.11" proc-macro2 = "1" diff --git a/compiler/rustc_fluent_macro/src/fluent.rs b/compiler/rustc_fluent_macro/src/fluent.rs index 23795a96b92..ca8bace28f3 100644 --- a/compiler/rustc_fluent_macro/src/fluent.rs +++ b/compiler/rustc_fluent_macro/src/fluent.rs @@ -2,7 +2,7 @@ use std::collections::{HashMap, HashSet}; use std::fs::read_to_string; use std::path::{Path, PathBuf}; -use annotate_snippets::{Annotation, AnnotationType, Renderer, Slice, Snippet, SourceAnnotation}; +use annotate_snippets::{Renderer, Snippet}; use fluent_bundle::{FluentBundle, FluentError, FluentResource}; use fluent_syntax::ast::{ Attribute, Entry, Expression, Identifier, InlineExpression, Message, Pattern, PatternElement, @@ -154,27 +154,15 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok .unwrap() .0; - let snippet = Snippet { - title: Some(Annotation { - label: Some(&err), - id: None, - annotation_type: AnnotationType::Error, - }), - footer: vec![], - slices: vec![Slice { - source: this.source(), - line_start, - origin: Some(&relative_ftl_path), - fold: true, - annotations: vec![SourceAnnotation { - label: "", - annotation_type: AnnotationType::Error, - range: (pos.start, pos.end - 1), - }], - }], - }; + let message = annotate_snippets::Level::Error.title(&err).snippet( + Snippet::source(this.source()) + .line_start(line_start) + .origin(&relative_ftl_path) + .fold(true) + .annotation(annotate_snippets::Level::Error.span(pos.start..pos.end - 1)), + ); let renderer = Renderer::plain(); - eprintln!("{}\n", renderer.render(snippet)); + eprintln!("{}\n", renderer.render(message)); } return failed(&crate_name); diff --git a/compiler/rustc_fluent_macro/src/lib.rs b/compiler/rustc_fluent_macro/src/lib.rs index 0a04e6743a8..6e5add24bcc 100644 --- a/compiler/rustc_fluent_macro/src/lib.rs +++ b/compiler/rustc_fluent_macro/src/lib.rs @@ -6,6 +6,7 @@ #![feature(proc_macro_diagnostic)] #![feature(proc_macro_span)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use proc_macro::TokenStream; diff --git a/compiler/rustc_graphviz/src/lib.rs b/compiler/rustc_graphviz/src/lib.rs index c8f8fd5be02..b5774f64b66 100644 --- a/compiler/rustc_graphviz/src/lib.rs +++ b/compiler/rustc_graphviz/src/lib.rs @@ -277,6 +277,7 @@ )] #![doc(rust_logo)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use std::borrow::Cow; diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 59204d79928..36e29d2dcb2 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -133,6 +133,9 @@ pub enum DefKind { /// we treat them all the same, and code which needs to distinguish them can match /// or `hir::ClosureKind` or `type_of`. Closure, + /// The definition of a synthetic coroutine body created by the lowering of a + /// coroutine-closure, such as an async closure. + SyntheticCoroutineBody, } impl DefKind { @@ -177,6 +180,7 @@ impl DefKind { DefKind::Closure => "closure", DefKind::ExternCrate => "extern crate", DefKind::GlobalAsm => "global assembly block", + DefKind::SyntheticCoroutineBody => "synthetic mir body", } } @@ -236,7 +240,8 @@ impl DefKind { | DefKind::ForeignMod | DefKind::GlobalAsm | DefKind::Impl { .. } - | DefKind::OpaqueTy => None, + | DefKind::OpaqueTy + | DefKind::SyntheticCoroutineBody => None, } } @@ -276,6 +281,7 @@ impl DefKind { DefKind::GlobalAsm => DefPathData::GlobalAsm, DefKind::Impl { .. } => DefPathData::Impl, DefKind::Closure => DefPathData::Closure, + DefKind::SyntheticCoroutineBody => DefPathData::Closure, } } @@ -291,7 +297,8 @@ impl DefKind { | DefKind::AssocFn | DefKind::Ctor(..) | DefKind::Closure - | DefKind::Static { .. } => true, + | DefKind::Static { .. } + | DefKind::SyntheticCoroutineBody => true, DefKind::Mod | DefKind::Struct | DefKind::Union @@ -319,6 +326,41 @@ impl DefKind { | DefKind::ExternCrate => false, } } + + /// Whether `query struct_target_features` should be used with this definition. + pub fn has_struct_target_features(self) -> bool { + match self { + DefKind::Struct | DefKind::Union | DefKind::Enum => true, + DefKind::Fn + | DefKind::AssocFn + | DefKind::Ctor(..) + | DefKind::Closure + | DefKind::Static { .. } + | DefKind::Mod + | DefKind::Variant + | DefKind::Trait + | DefKind::TyAlias + | DefKind::ForeignTy + | DefKind::TraitAlias + | DefKind::AssocTy + | DefKind::Const + | DefKind::AssocConst + | DefKind::Macro(..) + | DefKind::Use + | DefKind::ForeignMod + | DefKind::OpaqueTy + | DefKind::Impl { .. } + | DefKind::Field + | DefKind::TyParam + | DefKind::ConstParam + | DefKind::LifetimeParam + | DefKind::AnonConst + | DefKind::InlineConst + | DefKind::SyntheticCoroutineBody + | DefKind::GlobalAsm + | DefKind::ExternCrate => false, + } + } } /// The resolution of a path or export. diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 33e8432596b..57c47d29857 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1395,7 +1395,7 @@ pub struct LetExpr<'hir> { pub pat: &'hir Pat<'hir>, pub ty: Option<&'hir Ty<'hir>>, pub init: &'hir Expr<'hir>, - /// `Recovered::Yes` when this let expressions is not in a syntanctically valid location. + /// `Recovered::Yes` when this let expressions is not in a syntactically valid location. /// Used to prevent building MIR in such situations. pub recovered: ast::Recovered, } @@ -2773,7 +2773,6 @@ impl PreciseCapturingArg<'_> { /// resolution to. Lifetimes don't have this problem, and for them, it's actually /// kind of detrimental to use a custom node type versus just using [`Lifetime`], /// since resolve_bound_vars operates on `Lifetime`s. -// FIXME(precise_capturing): Investigate storing this as a path instead? #[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct PreciseCapturingNonLifetimeArg { pub hir_id: HirId, @@ -3586,7 +3585,7 @@ impl ForeignItem<'_> { #[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum ForeignItemKind<'hir> { /// A foreign function. - Fn(&'hir FnDecl<'hir>, &'hir [Ident], &'hir Generics<'hir>, Safety), + Fn(FnSig<'hir>, &'hir [Ident], &'hir Generics<'hir>), /// A foreign static item (`static ext: u8`). Static(&'hir Ty<'hir>, Mutability, Safety), /// A foreign type. @@ -3645,7 +3644,10 @@ impl<'hir> OwnerNode<'hir> { match self { OwnerNode::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. }) | OwnerNode::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. }) - | OwnerNode::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig), + | OwnerNode::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) + | OwnerNode::ForeignItem(ForeignItem { + kind: ForeignItemKind::Fn(fn_sig, _, _), .. + }) => Some(fn_sig), _ => None, } } @@ -3654,11 +3656,10 @@ impl<'hir> OwnerNode<'hir> { match self { OwnerNode::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. }) | OwnerNode::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. }) - | OwnerNode::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig.decl), - OwnerNode::ForeignItem(ForeignItem { - kind: ForeignItemKind::Fn(fn_decl, _, _, _), - .. - }) => Some(fn_decl), + | OwnerNode::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) + | OwnerNode::ForeignItem(ForeignItem { + kind: ForeignItemKind::Fn(fn_sig, _, _), .. + }) => Some(fn_sig.decl), _ => None, } } @@ -3846,11 +3847,13 @@ impl<'hir> Node<'hir> { match self { Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. }) | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. }) - | Node::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig.decl), - Node::Expr(Expr { kind: ExprKind::Closure(Closure { fn_decl, .. }), .. }) - | Node::ForeignItem(ForeignItem { - kind: ForeignItemKind::Fn(fn_decl, _, _, _), .. - }) => Some(fn_decl), + | Node::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) + | Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_sig, _, _), .. }) => { + Some(fn_sig.decl) + } + Node::Expr(Expr { kind: ExprKind::Closure(Closure { fn_decl, .. }), .. }) => { + Some(fn_decl) + } _ => None, } } @@ -3874,7 +3877,10 @@ impl<'hir> Node<'hir> { match self { Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. }) | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. }) - | Node::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig), + | Node::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) + | Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_sig, _, _), .. }) => { + Some(fn_sig) + } _ => None, } } @@ -3949,7 +3955,7 @@ impl<'hir> Node<'hir> { pub fn generics(self) -> Option<&'hir Generics<'hir>> { match self { Node::ForeignItem(ForeignItem { - kind: ForeignItemKind::Fn(_, _, generics, _), .. + kind: ForeignItemKind::Fn(_, _, generics), .. }) | Node::TraitItem(TraitItem { generics, .. }) | Node::ImplItem(ImplItem { generics, .. }) => Some(generics), @@ -4039,8 +4045,8 @@ mod size_asserts { static_assert_size!(Expr<'_>, 64); static_assert_size!(ExprKind<'_>, 48); static_assert_size!(FnDecl<'_>, 40); - static_assert_size!(ForeignItem<'_>, 72); - static_assert_size!(ForeignItemKind<'_>, 40); + static_assert_size!(ForeignItem<'_>, 88); + static_assert_size!(ForeignItemKind<'_>, 56); static_assert_size!(GenericArg<'_>, 16); static_assert_size!(GenericBound<'_>, 48); static_assert_size!(Generics<'_>, 56); diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index dd501f8417e..a54596e3088 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -611,9 +611,9 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>( try_visit!(visitor.visit_ident(foreign_item.ident)); match foreign_item.kind { - ForeignItemKind::Fn(ref function_declaration, param_names, ref generics, _) => { + ForeignItemKind::Fn(ref sig, param_names, ref generics) => { try_visit!(visitor.visit_generics(generics)); - try_visit!(visitor.visit_fn_decl(function_declaration)); + try_visit!(visitor.visit_fn_decl(sig.decl)); walk_list!(visitor, visit_ident, param_names.iter().copied()); } ForeignItemKind::Static(ref typ, _, _) => { diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index e517c3fd07a..c1a4a4497c7 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -10,6 +10,7 @@ #![feature(never_type)] #![feature(rustc_attrs)] #![feature(variant_count)] +#![warn(unreachable_pub)] // tidy-alphabetical-end extern crate self as rustc_hir; diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs index c30a6f1eeb9..d0b0c08aa79 100644 --- a/compiler/rustc_hir_analysis/src/bounds.rs +++ b/compiler/rustc_hir_analysis/src/bounds.rs @@ -26,13 +26,13 @@ use rustc_span::Span; /// Our representation is a bit mixed here -- in some cases, we /// include the self type (e.g., `trait_bounds`) but in others we do not #[derive(Default, PartialEq, Eq, Clone, Debug)] -pub struct Bounds<'tcx> { +pub(crate) struct Bounds<'tcx> { clauses: Vec<(ty::Clause<'tcx>, Span)>, effects_min_tys: FxIndexMap, Span>, } impl<'tcx> Bounds<'tcx> { - pub fn push_region_bound( + pub(crate) fn push_region_bound( &mut self, tcx: TyCtxt<'tcx>, region: ty::PolyTypeOutlivesPredicate<'tcx>, @@ -42,7 +42,7 @@ impl<'tcx> Bounds<'tcx> { .push((region.map_bound(|p| ty::ClauseKind::TypeOutlives(p)).upcast(tcx), span)); } - pub fn push_trait_bound( + pub(crate) fn push_trait_bound( &mut self, tcx: TyCtxt<'tcx>, defining_def_id: DefId, @@ -154,7 +154,7 @@ impl<'tcx> Bounds<'tcx> { self.clauses.push((bound_trait_ref.rebind(new_trait_ref).upcast(tcx), span)); } - pub fn push_projection_bound( + pub(crate) fn push_projection_bound( &mut self, tcx: TyCtxt<'tcx>, projection: ty::PolyProjectionPredicate<'tcx>, @@ -166,14 +166,14 @@ impl<'tcx> Bounds<'tcx> { )); } - pub fn push_sized(&mut self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) { + pub(crate) fn push_sized(&mut self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) { let sized_def_id = tcx.require_lang_item(LangItem::Sized, Some(span)); let trait_ref = ty::TraitRef::new(tcx, sized_def_id, [ty]); // Preferable to put this obligation first, since we report better errors for sized ambiguity. self.clauses.insert(0, (trait_ref.upcast(tcx), span)); } - pub fn clauses( + pub(crate) fn clauses( &self, // FIXME(effects): remove tcx _tcx: TyCtxt<'tcx>, @@ -181,7 +181,7 @@ impl<'tcx> Bounds<'tcx> { self.clauses.iter().cloned() } - pub fn effects_min_tys(&self) -> impl Iterator> + '_ { + pub(crate) fn effects_min_tys(&self) -> impl Iterator> + '_ { self.effects_min_tys.keys().copied() } } diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 2e778fd3759..d414bcdb95b 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -529,7 +529,7 @@ fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDe match tcx.named_bound_var(hir_id) { Some(ResolvedArg::EarlyBound(def_id)) => { - expected_captures.insert(def_id); + expected_captures.insert(def_id.to_def_id()); // Make sure we allow capturing these lifetimes through `Self` and // `T::Assoc` projection syntax, too. These will occur when we only @@ -538,7 +538,7 @@ fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDe // feature -- see . if let DefKind::LifetimeParam = tcx.def_kind(def_id) && let Some(def_id) = tcx - .map_opaque_lifetime_to_parent_lifetime(def_id.expect_local()) + .map_opaque_lifetime_to_parent_lifetime(def_id) .opt_param_def_id(tcx, tcx.parent(opaque_def_id.to_def_id())) { shadowed_captures.insert(def_id); @@ -804,8 +804,8 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { let item = tcx.hir().foreign_item(item.id); match &item.kind { - hir::ForeignItemKind::Fn(fn_decl, _, _, _) => { - require_c_abi_if_c_variadic(tcx, fn_decl, abi, item.span); + hir::ForeignItemKind::Fn(sig, _, _) => { + require_c_abi_if_c_variadic(tcx, sig.decl, abi, item.span); } hir::ForeignItemKind::Static(..) => { check_static_inhabited(tcx, def_id); @@ -1053,7 +1053,7 @@ fn check_impl_items_against_trait<'tcx>( } } -pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) { +fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) { let t = tcx.type_of(def_id).instantiate_identity(); if let ty::Adt(def, args) = t.kind() && def.is_struct() @@ -1259,7 +1259,8 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) ty::Tuple(list) => list.iter().try_for_each(|t| check_non_exhaustive(tcx, t)), ty::Array(ty, _) => check_non_exhaustive(tcx, *ty), ty::Adt(def, args) => { - if !def.did().is_local() { + if !def.did().is_local() && !tcx.has_attr(def.did(), sym::rustc_pub_transparent) + { let non_exhaustive = def.is_variant_list_non_exhaustive() || def .variants() @@ -1564,7 +1565,7 @@ fn check_type_alias_type_params_are_used<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalD // * compare the param span to the pred span to detect lone user-written `Sized` bounds let has_explicit_bounds = bounded_params.is_empty() || (*bounded_params).get(¶m.index).is_some_and(|&&pred_sp| pred_sp != span); - let const_param_help = (!has_explicit_bounds).then_some(()); + let const_param_help = !has_explicit_bounds; let mut diag = tcx.dcx().create_err(errors::UnusedGenericParameter { span, diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index 80daaa60324..d2b7ede6523 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -7,7 +7,8 @@ use rustc_lint_defs::builtin::{REFINING_IMPL_TRAIT_INTERNAL, REFINING_IMPL_TRAIT use rustc_middle::span_bug; use rustc_middle::traits::{ObligationCause, Reveal}; use rustc_middle::ty::{ - self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperVisitable, TypeVisitable, TypeVisitor, + self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperVisitable, TypeVisitable, + TypeVisitableExt, TypeVisitor, }; use rustc_span::Span; use rustc_trait_selection::regions::InferCtxtRegionExt; @@ -177,6 +178,10 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( return; }; + if trait_bounds.references_error() || impl_bounds.references_error() { + return; + } + // For quicker lookup, use an `IndexSet` (we don't use one earlier because // it's not foldable..). // Also, We have to anonymize binders in these types because they may contain diff --git a/compiler/rustc_hir_analysis/src/check/entry.rs b/compiler/rustc_hir_analysis/src/check/entry.rs index 1f724580564..83d2c2c1e28 100644 --- a/compiler/rustc_hir_analysis/src/check/entry.rs +++ b/compiler/rustc_hir_analysis/src/check/entry.rs @@ -216,7 +216,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) { } if sig.header.asyncness.is_async() { let span = tcx.def_span(it.owner_id); - tcx.dcx().emit_err(errors::StartAsync { span: span }); + tcx.dcx().emit_err(errors::StartAsync { span }); error = true; } diff --git a/compiler/rustc_hir_analysis/src/check/errs.rs b/compiler/rustc_hir_analysis/src/check/errs.rs index 19a0476e630..22d7d1fea9c 100644 --- a/compiler/rustc_hir_analysis/src/check/errs.rs +++ b/compiler/rustc_hir_analysis/src/check/errs.rs @@ -6,7 +6,7 @@ use rustc_span::Span; use crate::errors; /// Check for shared or mutable references of `static mut` inside expression -pub fn maybe_expr_static_mut(tcx: TyCtxt<'_>, expr: hir::Expr<'_>) { +pub(crate) fn maybe_expr_static_mut(tcx: TyCtxt<'_>, expr: hir::Expr<'_>) { let span = expr.span; let hir_id = expr.hir_id; if let hir::ExprKind::AddrOf(borrow_kind, m, expr) = expr.kind @@ -26,7 +26,7 @@ pub fn maybe_expr_static_mut(tcx: TyCtxt<'_>, expr: hir::Expr<'_>) { } /// Check for shared or mutable references of `static mut` inside statement -pub fn maybe_stmt_static_mut(tcx: TyCtxt<'_>, stmt: hir::Stmt<'_>) { +pub(crate) fn maybe_stmt_static_mut(tcx: TyCtxt<'_>, stmt: hir::Stmt<'_>) { if let hir::StmtKind::Let(loc) = stmt.kind && let hir::PatKind::Binding(ba, _, _, _) = loc.pat.kind && let hir::ByRef::Yes(rmutbl) = ba.0 diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 4b45ced30c5..c2b2f08132e 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -30,7 +30,7 @@ fn equate_intrinsic_type<'tcx>( let (generics, span) = match tcx.hir_node_by_def_id(def_id) { hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. }) | hir::Node::ForeignItem(hir::ForeignItem { - kind: hir::ForeignItemKind::Fn(.., generics, _), + kind: hir::ForeignItemKind::Fn(_, _, generics), .. }) => (tcx.generics_of(def_id), generics.span), _ => { diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index 79ecdee4486..3d5a22fce85 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -68,7 +68,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { ty::Float(FloatTy::F32) => Some(InlineAsmType::F32), ty::Float(FloatTy::F64) => Some(InlineAsmType::F64), ty::Float(FloatTy::F128) => Some(InlineAsmType::F128), - ty::FnPtr(_) => Some(asm_ty_isize), + ty::FnPtr(..) => Some(asm_ty_isize), ty::RawPtr(ty, _) if self.is_thin_ptr_ty(ty) => Some(asm_ty_isize), ty::Adt(adt, args) if adt.repr().simd() => { let fields = &adt.non_enum_variant().fields; diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index bc6641c688c..48335173979 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -22,7 +22,7 @@ use rustc_span::source_map; use super::errs::{maybe_expr_static_mut, maybe_stmt_static_mut}; #[derive(Debug, Copy, Clone)] -pub struct Context { +struct Context { /// The scope that contains any new variables declared, plus its depth in /// the scope tree. var_parent: Option<(Scope, ScopeDepth)>, @@ -893,7 +893,7 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> { /// re-use in incremental scenarios. We may sometimes need to rerun the /// type checker even when the HIR hasn't changed, and in those cases /// we can avoid reconstructing the region scope tree. -pub fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree { +pub(crate) fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree { let typeck_root_def_id = tcx.typeck_root_def_id(def_id); if typeck_root_def_id != def_id { return tcx.region_scope_tree(typeck_root_def_id); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index a9f8630741a..cb66179ec80 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -350,8 +350,8 @@ fn check_foreign_item<'tcx>( ); match item.kind { - hir::ForeignItemKind::Fn(decl, ..) => { - check_item_fn(tcx, def_id, item.ident, item.span, decl) + hir::ForeignItemKind::Fn(sig, ..) => { + check_item_fn(tcx, def_id, item.ident, item.span, sig.decl) } hir::ForeignItemKind::Static(ty, ..) => { check_item_type(tcx, def_id, ty.span, UnsizedHandling::AllowIfForeignTail) @@ -747,7 +747,7 @@ fn region_known_to_outlive<'tcx>( region_b: ty::Region<'tcx>, ) -> bool { test_region_obligations(tcx, id, param_env, wf_tys, |infcx| { - infcx.sub_regions(infer::RelateRegionParamBound(DUMMY_SP), region_b, region_a); + infcx.sub_regions(infer::RelateRegionParamBound(DUMMY_SP, None), region_b, region_a); }) } @@ -951,7 +951,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(), } else { let mut diag = match ty.kind() { ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Error(_) => return Ok(()), - ty::FnPtr(_) => tcx.dcx().struct_span_err( + ty::FnPtr(..) => tcx.dcx().struct_span_err( hir_ty.span, "using function pointers as const generic parameters is forbidden", ), @@ -1972,8 +1972,7 @@ fn report_bivariance<'tcx>( } let const_param_help = - matches!(param.kind, hir::GenericParamKind::Type { .. } if !has_explicit_bounds) - .then_some(()); + matches!(param.kind, hir::GenericParamKind::Type { .. } if !has_explicit_bounds); let mut diag = tcx.dcx().create_err(errors::UnusedGenericParameter { span: param.span, @@ -2175,7 +2174,8 @@ fn lint_redundant_lifetimes<'tcx>( | DefKind::Field | DefKind::LifetimeParam | DefKind::GlobalAsm - | DefKind::Closure => return, + | DefKind::Closure + | DefKind::SyntheticCoroutineBody => return, } // The ordering of this lifetime map is a bit subtle. diff --git a/compiler/rustc_hir_analysis/src/check_unused.rs b/compiler/rustc_hir_analysis/src/check_unused.rs index ed23dc2a827..ca9e2e8a3cc 100644 --- a/compiler/rustc_hir_analysis/src/check_unused.rs +++ b/compiler/rustc_hir_analysis/src/check_unused.rs @@ -5,7 +5,7 @@ use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::lint; -pub fn provide(providers: &mut Providers) { +pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { check_unused_traits, ..*providers }; } diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index fecd78bc38f..23f1adfe302 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -332,7 +332,7 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<() } } -pub fn coerce_unsized_info<'tcx>( +pub(crate) fn coerce_unsized_info<'tcx>( tcx: TyCtxt<'tcx>, impl_did: LocalDefId, ) -> Result { diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs index e2d3ff558cf..bd8b43e28e5 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs @@ -19,7 +19,7 @@ use rustc_span::ErrorGuaranteed; use crate::errors; /// On-demand query: yields a map containing all types mapped to their inherent impls. -pub fn crate_inherent_impls( +pub(crate) fn crate_inherent_impls( tcx: TyCtxt<'_>, (): (), ) -> Result<&'_ CrateInherentImpls, ErrorGuaranteed> { @@ -32,7 +32,7 @@ pub fn crate_inherent_impls( Ok(tcx.arena.alloc(collect.impls_map)) } -pub fn crate_incoherent_impls( +pub(crate) fn crate_incoherent_impls( tcx: TyCtxt<'_>, simp: SimplifiedType, ) -> Result<&[DefId], ErrorGuaranteed> { @@ -43,7 +43,10 @@ pub fn crate_incoherent_impls( } /// On-demand query: yields a vector of the inherent impls for a specific type. -pub fn inherent_impls(tcx: TyCtxt<'_>, ty_def_id: LocalDefId) -> Result<&[DefId], ErrorGuaranteed> { +pub(crate) fn inherent_impls( + tcx: TyCtxt<'_>, + ty_def_id: LocalDefId, +) -> Result<&[DefId], ErrorGuaranteed> { let crate_map = tcx.crate_inherent_impls(())?; Ok(match crate_map.inherent_impls.get(&ty_def_id) { Some(v) => &v[..], @@ -172,7 +175,7 @@ impl<'tcx> InherentCollect<'tcx> { | ty::RawPtr(_, _) | ty::Ref(..) | ty::Never - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::Tuple(..) => self.check_primitive_impl(id, self_ty), ty::Alias(ty::Projection | ty::Inherent | ty::Opaque, _) | ty::Param(_) => { Err(self.tcx.dcx().emit_err(errors::InherentNominal { span: item_span })) diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs index cd5cc33d65a..00bbbf7130f 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs @@ -11,7 +11,10 @@ use rustc_span::{ErrorGuaranteed, Symbol}; use rustc_trait_selection::traits::{self, SkipLeakCheck}; use smallvec::SmallVec; -pub fn crate_inherent_impls_overlap_check(tcx: TyCtxt<'_>, (): ()) -> Result<(), ErrorGuaranteed> { +pub(crate) fn crate_inherent_impls_overlap_check( + tcx: TyCtxt<'_>, + (): (), +) -> Result<(), ErrorGuaranteed> { let mut inherent_overlap_checker = InherentOverlapChecker { tcx }; let mut res = Ok(()); for id in tcx.hir().items() { diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index 8e4da90ca26..3d800bb165c 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -123,7 +123,7 @@ fn enforce_empty_impls_for_marker_traits( .emit()) } -pub fn provide(providers: &mut Providers) { +pub(crate) fn provide(providers: &mut Providers) { use self::builtin::coerce_unsized_info; use self::inherent_impls::{crate_incoherent_impls, crate_inherent_impls, inherent_impls}; use self::inherent_impls_overlap::crate_inherent_impls_overlap_check; diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 91fa066ec6a..3acf2c63145 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -34,7 +34,7 @@ use rustc_infer::traits::ObligationCause; use rustc_middle::hir::nested_filter; use rustc_middle::query::Providers; use rustc_middle::ty::util::{Discr, IntTypeExt}; -use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, Ty, TyCtxt, Upcast}; +use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; @@ -70,7 +70,6 @@ pub fn provide(providers: &mut Providers) { impl_super_outlives: item_bounds::impl_super_outlives, generics_of: generics_of::generics_of, predicates_of: predicates_of::predicates_of, - predicates_defined_on, explicit_predicates_of: predicates_of::explicit_predicates_of, explicit_super_predicates_of: predicates_of::explicit_super_predicates_of, explicit_implied_predicates_of: predicates_of::explicit_implied_predicates_of, @@ -392,7 +391,7 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { } fn re_infer(&self, span: Span, reason: RegionInferReason<'_>) -> ty::Region<'tcx> { - if let RegionInferReason::BorrowedObjectLifetimeDefault = reason { + if let RegionInferReason::ObjectLifetimeDefault = reason { let e = struct_span_code_err!( self.dcx(), span, @@ -1440,11 +1439,9 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn icx.lowerer().lower_fn_ty(hir_id, header.safety, header.abi, decl, Some(generics), None) } - ForeignItem(&hir::ForeignItem { - kind: ForeignItemKind::Fn(fn_decl, _, _, safety), .. - }) => { + ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(sig, _, _), .. }) => { let abi = tcx.hir().get_foreign_abi(hir_id); - compute_sig_of_foreign_fn_decl(tcx, def_id, fn_decl, abi, safety) + compute_sig_of_foreign_fn_decl(tcx, def_id, sig.decl, abi, sig.header.safety) } Ctor(data) | Variant(hir::Variant { data, .. }) if data.ctor().is_some() => { @@ -1777,34 +1774,6 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx: 'a>( }) } -/// Returns a list of type predicates for the definition with ID `def_id`, including inferred -/// lifetime constraints. This includes all predicates returned by `explicit_predicates_of`, plus -/// inferred constraints concerning which regions outlive other regions. -#[instrument(level = "debug", skip(tcx))] -fn predicates_defined_on(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> { - let mut result = tcx.explicit_predicates_of(def_id); - debug!("predicates_defined_on: explicit_predicates_of({:?}) = {:?}", def_id, result); - let inferred_outlives = tcx.inferred_outlives_of(def_id); - if !inferred_outlives.is_empty() { - debug!( - "predicates_defined_on: inferred_outlives_of({:?}) = {:?}", - def_id, inferred_outlives, - ); - let inferred_outlives_iter = - inferred_outlives.iter().map(|(clause, span)| ((*clause).upcast(tcx), *span)); - if result.predicates.is_empty() { - result.predicates = tcx.arena.alloc_from_iter(inferred_outlives_iter); - } else { - result.predicates = tcx.arena.alloc_from_iter( - result.predicates.into_iter().copied().chain(inferred_outlives_iter), - ); - } - } - - debug!("predicates_defined_on({:?}) = {:?}", def_id, result); - result -} - fn compute_sig_of_foreign_fn_decl<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 6ac4802b195..bba8b0497be 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -18,10 +18,26 @@ use crate::delegation::inherit_predicates_for_delegation_item; use crate::hir_ty_lowering::{HirTyLowerer, OnlySelfBounds, PredicateFilter, RegionInferReason}; /// Returns a list of all type predicates (explicit and implicit) for the definition with -/// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus -/// `Self: Trait` predicates for traits. +/// ID `def_id`. This includes all predicates returned by `explicit_predicates_of`, plus +/// inferred constraints concerning which regions outlive other regions. +#[instrument(level = "debug", skip(tcx))] pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> { - let mut result = tcx.predicates_defined_on(def_id); + let mut result = tcx.explicit_predicates_of(def_id); + debug!("predicates_of: explicit_predicates_of({:?}) = {:?}", def_id, result); + + let inferred_outlives = tcx.inferred_outlives_of(def_id); + if !inferred_outlives.is_empty() { + debug!("predicates_of: inferred_outlives_of({:?}) = {:?}", def_id, inferred_outlives,); + let inferred_outlives_iter = + inferred_outlives.iter().map(|(clause, span)| ((*clause).upcast(tcx), *span)); + if result.predicates.is_empty() { + result.predicates = tcx.arena.alloc_from_iter(inferred_outlives_iter); + } else { + result.predicates = tcx.arena.alloc_from_iter( + result.predicates.into_iter().copied().chain(inferred_outlives_iter), + ); + } + } if tcx.is_trait(def_id) { // For traits, add `Self: Trait` predicate. This is @@ -51,7 +67,8 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic .chain(std::iter::once((ty::TraitRef::identity(tcx, def_id).upcast(tcx), span))), ); } - debug!("predicates_of(def_id={:?}) = {:?}", def_id, result); + + debug!("predicates_of({:?}) = {:?}", def_id, result); result } diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index e11d3c9c48b..e38492d9e64 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -13,7 +13,6 @@ use rustc_ast::visit::walk_list; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirId, HirIdMap, LifetimeName, Node}; use rustc_macros::extension; @@ -22,7 +21,7 @@ use rustc_middle::middle::resolve_bound_vars::*; use rustc_middle::query::Providers; use rustc_middle::ty::{self, TyCtxt, TypeSuperVisitable, TypeVisitor}; use rustc_middle::{bug, span_bug}; -use rustc_span::def_id::DefId; +use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; @@ -32,7 +31,7 @@ use crate::errors; impl ResolvedArg { fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg) { debug!("ResolvedArg::early: def_id={:?}", param.def_id); - (param.def_id, ResolvedArg::EarlyBound(param.def_id.to_def_id())) + (param.def_id, ResolvedArg::EarlyBound(param.def_id)) } fn late(idx: u32, param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg) { @@ -41,10 +40,10 @@ impl ResolvedArg { "ResolvedArg::late: idx={:?}, param={:?} depth={:?} def_id={:?}", idx, param, depth, param.def_id, ); - (param.def_id, ResolvedArg::LateBound(depth, idx, param.def_id.to_def_id())) + (param.def_id, ResolvedArg::LateBound(depth, idx, param.def_id)) } - fn id(&self) -> Option { + fn id(&self) -> Option { match *self { ResolvedArg::StaticLifetime | ResolvedArg::Error(_) => None, @@ -288,13 +287,14 @@ fn late_arg_as_bound_arg<'tcx>( ) -> ty::BoundVariableKind { match arg { ResolvedArg::LateBound(_, _, def_id) => { - let name = tcx.hir().name(tcx.local_def_id_to_hir_id(def_id.expect_local())); + let def_id = def_id.to_def_id(); + let name = tcx.item_name(def_id); match param.kind { GenericParamKind::Lifetime { .. } => { - ty::BoundVariableKind::Region(ty::BrNamed(*def_id, name)) + ty::BoundVariableKind::Region(ty::BrNamed(def_id, name)) } GenericParamKind::Type { .. } => { - ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(*def_id, name)) + ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(def_id, name)) } GenericParamKind::Const { .. } => ty::BoundVariableKind::Const, } @@ -604,7 +604,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) { match item.kind { - hir::ForeignItemKind::Fn(_, _, generics, _) => { + hir::ForeignItemKind::Fn(_, _, generics) => { self.visit_early_late(item.hir_id(), generics, |this| { intravisit::walk_foreign_item(this, item); }) @@ -717,7 +717,6 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { // In the future, this should be fixed and this error should be removed. let def = self.map.defs.get(&lifetime.hir_id).copied(); let Some(ResolvedArg::LateBound(_, _, lifetime_def_id)) = def else { continue }; - let Some(lifetime_def_id) = lifetime_def_id.as_local() else { continue }; let lifetime_hir_id = self.tcx.local_def_id_to_hir_id(lifetime_def_id); let bad_place = match self.tcx.hir_node(self.tcx.parent_hir_id(lifetime_hir_id)) @@ -1150,7 +1149,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { .param_def_id_to_index(self.tcx, region_def_id.to_def_id()) .is_some() { - break Some(ResolvedArg::EarlyBound(region_def_id.to_def_id())); + break Some(ResolvedArg::EarlyBound(region_def_id)); } break None; } @@ -1259,7 +1258,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { kind => span_bug!( use_span, "did not expect to resolve lifetime to {}", - kind.descr(param_def_id) + kind.descr(param_def_id.to_def_id()) ), }; def = ResolvedArg::Error(guar); @@ -1277,10 +1276,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { kind: hir::ImplItemKind::Fn(..), .. }) => { - def = ResolvedArg::Free(owner_id.to_def_id(), def.id().unwrap()); + def = ResolvedArg::Free(owner_id.def_id, def.id().unwrap()); } Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(closure), .. }) => { - def = ResolvedArg::Free(closure.def_id.to_def_id(), def.id().unwrap()); + def = ResolvedArg::Free(closure.def_id, def.id().unwrap()); } _ => {} } @@ -1351,7 +1350,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { .param_def_id_to_index(self.tcx, param_def_id.to_def_id()) .is_some() { - break Some(ResolvedArg::EarlyBound(param_def_id.to_def_id())); + break Some(ResolvedArg::EarlyBound(param_def_id)); } break None; } @@ -2072,7 +2071,7 @@ fn is_late_bound_map( } } -pub fn deny_non_region_late_bound( +fn deny_non_region_late_bound( tcx: TyCtxt<'_>, bound_vars: &mut FxIndexMap, where_: &str, diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 8cb4ba6c669..96256b91b9f 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -725,7 +725,7 @@ fn check_feature_inherent_assoc_ty(tcx: TyCtxt<'_>, span: Span) { } } -pub fn type_alias_is_lazy<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool { +pub(crate) fn type_alias_is_lazy<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool { use hir::intravisit::Visitor; if tcx.features().lazy_type_alias { return true; diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs index d1048b742a0..c8b0f03a929 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -331,7 +331,7 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, owner_def_id: LocalDefId, -) -> Ty<'_> { +) -> Ty<'tcx> { let tables = tcx.typeck(owner_def_id); // Check that all of the opaques we inferred during HIR are compatible. diff --git a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs index 620170164f5..edf65245664 100644 --- a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs +++ b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs @@ -6,7 +6,7 @@ use rustc_span::Span; use rustc_type_ir::fold::TypeFoldable; #[derive(Clone, PartialEq, Eq, Hash, Debug)] -pub struct Parameter(pub u32); +pub(crate) struct Parameter(pub u32); impl From for Parameter { fn from(param: ty::ParamTy) -> Self { @@ -27,7 +27,7 @@ impl From for Parameter { } /// Returns the set of parameters constrained by the impl header. -pub fn parameters_for_impl<'tcx>( +pub(crate) fn parameters_for_impl<'tcx>( tcx: TyCtxt<'tcx>, impl_self_ty: Ty<'tcx>, impl_trait_ref: Option>, @@ -44,7 +44,7 @@ pub fn parameters_for_impl<'tcx>( /// uniquely determined by `value` (see RFC 447). If it is true, return the list /// of parameters whose values are needed in order to constrain `value` - these /// differ, with the latter being a superset, in the presence of projections. -pub fn parameters_for<'tcx>( +pub(crate) fn parameters_for<'tcx>( tcx: TyCtxt<'tcx>, value: impl TypeFoldable>, include_nonconstraining: bool, @@ -102,7 +102,7 @@ impl<'tcx> TypeVisitor> for ParameterCollector { } } -pub fn identify_constrained_generic_params<'tcx>( +pub(crate) fn identify_constrained_generic_params<'tcx>( tcx: TyCtxt<'tcx>, predicates: ty::GenericPredicates<'tcx>, impl_trait_ref: Option>, @@ -156,7 +156,7 @@ pub fn identify_constrained_generic_params<'tcx>( /// which is determined by 1, which requires `U`, that is determined /// by 0. I should probably pick a less tangled example, but I can't /// think of any. -pub fn setup_constraining_predicates<'tcx>( +pub(crate) fn setup_constraining_predicates<'tcx>( tcx: TyCtxt<'tcx>, predicates: &mut [(ty::Clause<'tcx>, Span)], impl_trait_ref: Option>, diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 7034735aec0..39df18ff658 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -11,15 +11,15 @@ use rustc_span::{Span, Symbol}; use crate::fluent_generated as fluent; mod pattern_types; -pub use pattern_types::*; -pub mod wrong_number_of_generic_args; +pub(crate) use pattern_types::*; +pub(crate) mod wrong_number_of_generic_args; mod precise_captures; pub(crate) use precise_captures::*; #[derive(Diagnostic)] #[diag(hir_analysis_ambiguous_assoc_item)] -pub struct AmbiguousAssocItem<'a> { +pub(crate) struct AmbiguousAssocItem<'a> { #[primary_span] #[label] pub span: Span, @@ -30,7 +30,7 @@ pub struct AmbiguousAssocItem<'a> { #[derive(Diagnostic)] #[diag(hir_analysis_assoc_kind_mismatch)] -pub struct AssocKindMismatch { +pub(crate) struct AssocKindMismatch { #[primary_span] #[label] pub span: Span, @@ -52,7 +52,7 @@ pub struct AssocKindMismatch { hir_analysis_assoc_kind_mismatch_wrap_in_braces_sugg, applicability = "maybe-incorrect" )] -pub struct AssocKindMismatchWrapInBracesSugg { +pub(crate) struct AssocKindMismatchWrapInBracesSugg { #[suggestion_part(code = "{{ ")] pub lo: Span, #[suggestion_part(code = " }}")] @@ -61,7 +61,7 @@ pub struct AssocKindMismatchWrapInBracesSugg { #[derive(Diagnostic)] #[diag(hir_analysis_assoc_item_is_private, code = E0624)] -pub struct AssocItemIsPrivate { +pub(crate) struct AssocItemIsPrivate { #[primary_span] #[label] pub span: Span, @@ -73,7 +73,7 @@ pub struct AssocItemIsPrivate { #[derive(Diagnostic)] #[diag(hir_analysis_assoc_item_not_found, code = E0220)] -pub struct AssocItemNotFound<'a> { +pub(crate) struct AssocItemNotFound<'a> { #[primary_span] pub span: Span, pub assoc_name: Ident, @@ -86,7 +86,7 @@ pub struct AssocItemNotFound<'a> { } #[derive(Subdiagnostic)] -pub enum AssocItemNotFoundLabel<'a> { +pub(crate) enum AssocItemNotFoundLabel<'a> { #[label(hir_analysis_assoc_item_not_found_label)] NotFound { #[primary_span] @@ -105,7 +105,7 @@ pub enum AssocItemNotFoundLabel<'a> { #[derive(Subdiagnostic)] -pub enum AssocItemNotFoundSugg<'a> { +pub(crate) enum AssocItemNotFoundSugg<'a> { #[suggestion( hir_analysis_assoc_item_not_found_similar_sugg, code = "{suggested_name}", @@ -162,7 +162,7 @@ pub enum AssocItemNotFoundSugg<'a> { #[derive(Diagnostic)] #[diag(hir_analysis_unrecognized_atomic_operation, code = E0092)] -pub struct UnrecognizedAtomicOperation<'a> { +pub(crate) struct UnrecognizedAtomicOperation<'a> { #[primary_span] #[label] pub span: Span, @@ -171,7 +171,7 @@ pub struct UnrecognizedAtomicOperation<'a> { #[derive(Diagnostic)] #[diag(hir_analysis_wrong_number_of_generic_arguments_to_intrinsic, code = E0094)] -pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> { +pub(crate) struct WrongNumberOfGenericArgumentsToIntrinsic<'a> { #[primary_span] #[label] pub span: Span, @@ -183,7 +183,7 @@ pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> { #[derive(Diagnostic)] #[diag(hir_analysis_unrecognized_intrinsic_function, code = E0093)] #[help] -pub struct UnrecognizedIntrinsicFunction { +pub(crate) struct UnrecognizedIntrinsicFunction { #[primary_span] #[label] pub span: Span, @@ -192,7 +192,7 @@ pub struct UnrecognizedIntrinsicFunction { #[derive(Diagnostic)] #[diag(hir_analysis_lifetimes_or_bounds_mismatch_on_trait, code = E0195)] -pub struct LifetimesOrBoundsMismatchOnTrait { +pub(crate) struct LifetimesOrBoundsMismatchOnTrait { #[primary_span] #[label] pub span: Span, @@ -208,14 +208,14 @@ pub struct LifetimesOrBoundsMismatchOnTrait { #[derive(Diagnostic)] #[diag(hir_analysis_drop_impl_on_wrong_item, code = E0120)] -pub struct DropImplOnWrongItem { +pub(crate) struct DropImplOnWrongItem { #[primary_span] #[label] pub span: Span, } #[derive(Diagnostic)] -pub enum FieldAlreadyDeclared { +pub(crate) enum FieldAlreadyDeclared { #[diag(hir_analysis_field_already_declared, code = E0124)] NotNested { field_name: Symbol, @@ -272,14 +272,14 @@ pub enum FieldAlreadyDeclared { #[derive(Subdiagnostic)] #[help(hir_analysis_field_already_declared_nested_help)] -pub struct FieldAlreadyDeclaredNestedHelp { +pub(crate) struct FieldAlreadyDeclaredNestedHelp { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(hir_analysis_copy_impl_on_type_with_dtor, code = E0184)] -pub struct CopyImplOnTypeWithDtor { +pub(crate) struct CopyImplOnTypeWithDtor { #[primary_span] #[label] pub span: Span, @@ -287,14 +287,14 @@ pub struct CopyImplOnTypeWithDtor { #[derive(Diagnostic)] #[diag(hir_analysis_multiple_relaxed_default_bounds, code = E0203)] -pub struct MultipleRelaxedDefaultBounds { +pub(crate) struct MultipleRelaxedDefaultBounds { #[primary_span] pub spans: Vec, } #[derive(Diagnostic)] #[diag(hir_analysis_copy_impl_on_non_adt, code = E0206)] -pub struct CopyImplOnNonAdt { +pub(crate) struct CopyImplOnNonAdt { #[primary_span] #[label] pub span: Span, @@ -302,7 +302,7 @@ pub struct CopyImplOnNonAdt { #[derive(Diagnostic)] #[diag(hir_analysis_const_param_ty_impl_on_unsized)] -pub struct ConstParamTyImplOnUnsized { +pub(crate) struct ConstParamTyImplOnUnsized { #[primary_span] #[label] pub span: Span, @@ -310,7 +310,7 @@ pub struct ConstParamTyImplOnUnsized { #[derive(Diagnostic)] #[diag(hir_analysis_const_param_ty_impl_on_non_adt)] -pub struct ConstParamTyImplOnNonAdt { +pub(crate) struct ConstParamTyImplOnNonAdt { #[primary_span] #[label] pub span: Span, @@ -318,7 +318,7 @@ pub struct ConstParamTyImplOnNonAdt { #[derive(Diagnostic)] #[diag(hir_analysis_trait_object_declared_with_no_traits, code = E0224)] -pub struct TraitObjectDeclaredWithNoTraits { +pub(crate) struct TraitObjectDeclaredWithNoTraits { #[primary_span] pub span: Span, #[label(hir_analysis_alias_span)] @@ -327,14 +327,14 @@ pub struct TraitObjectDeclaredWithNoTraits { #[derive(Diagnostic)] #[diag(hir_analysis_ambiguous_lifetime_bound, code = E0227)] -pub struct AmbiguousLifetimeBound { +pub(crate) struct AmbiguousLifetimeBound { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(hir_analysis_assoc_item_constraints_not_allowed_here, code = E0229)] -pub struct AssocItemConstraintsNotAllowedHere { +pub(crate) struct AssocItemConstraintsNotAllowedHere { #[primary_span] #[label] pub span: Span, @@ -383,7 +383,7 @@ pub(crate) struct EscapingBoundVarInTyOfAssocConstBinding<'tcx> { #[derive(Subdiagnostic)] #[help(hir_analysis_parenthesized_fn_trait_expansion)] -pub struct ParenthesizedFnTraitExpansion { +pub(crate) struct ParenthesizedFnTraitExpansion { #[primary_span] pub span: Span, @@ -392,7 +392,7 @@ pub struct ParenthesizedFnTraitExpansion { #[derive(Diagnostic)] #[diag(hir_analysis_typeof_reserved_keyword_used, code = E0516)] -pub struct TypeofReservedKeywordUsed<'tcx> { +pub(crate) struct TypeofReservedKeywordUsed<'tcx> { pub ty: Ty<'tcx>, #[primary_span] #[label] @@ -403,7 +403,7 @@ pub struct TypeofReservedKeywordUsed<'tcx> { #[derive(Diagnostic)] #[diag(hir_analysis_value_of_associated_struct_already_specified, code = E0719)] -pub struct ValueOfAssociatedStructAlreadySpecified { +pub(crate) struct ValueOfAssociatedStructAlreadySpecified { #[primary_span] #[label] pub span: Span, @@ -416,7 +416,7 @@ pub struct ValueOfAssociatedStructAlreadySpecified { #[derive(Diagnostic)] #[diag(hir_analysis_unconstrained_opaque_type)] #[note] -pub struct UnconstrainedOpaqueType { +pub(crate) struct UnconstrainedOpaqueType { #[primary_span] pub span: Span, pub name: Symbol, @@ -426,7 +426,7 @@ pub struct UnconstrainedOpaqueType { #[derive(Diagnostic)] #[diag(hir_analysis_tait_forward_compat)] #[note] -pub struct TaitForwardCompat { +pub(crate) struct TaitForwardCompat { #[primary_span] pub span: Span, #[note] @@ -436,7 +436,7 @@ pub struct TaitForwardCompat { #[derive(Diagnostic)] #[diag(hir_analysis_tait_forward_compat2)] #[note] -pub struct TaitForwardCompat2 { +pub(crate) struct TaitForwardCompat2 { #[primary_span] pub span: Span, #[note(hir_analysis_opaque)] @@ -444,7 +444,7 @@ pub struct TaitForwardCompat2 { pub opaque_type: String, } -pub struct MissingTypeParams { +pub(crate) struct MissingTypeParams { pub span: Span, pub def_span: Span, pub span_snippet: Option, @@ -512,7 +512,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for MissingTypeParams { #[derive(Diagnostic)] #[diag(hir_analysis_manual_implementation, code = E0183)] #[help] -pub struct ManualImplementation { +pub(crate) struct ManualImplementation { #[primary_span] #[label] pub span: Span, @@ -521,14 +521,14 @@ pub struct ManualImplementation { #[derive(Diagnostic)] #[diag(hir_analysis_generic_args_on_overridden_impl)] -pub struct GenericArgsOnOverriddenImpl { +pub(crate) struct GenericArgsOnOverriddenImpl { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(hir_analysis_const_impl_for_non_const_trait)] -pub struct ConstImplForNonConstTrait { +pub(crate) struct ConstImplForNonConstTrait { #[primary_span] pub trait_ref_span: Span, pub trait_name: String, @@ -542,7 +542,7 @@ pub struct ConstImplForNonConstTrait { #[derive(Diagnostic)] #[diag(hir_analysis_const_bound_for_non_const_trait)] -pub struct ConstBoundForNonConstTrait { +pub(crate) struct ConstBoundForNonConstTrait { #[primary_span] pub span: Span, pub modifier: &'static str, @@ -550,7 +550,7 @@ pub struct ConstBoundForNonConstTrait { #[derive(Diagnostic)] #[diag(hir_analysis_self_in_impl_self)] -pub struct SelfInImplSelf { +pub(crate) struct SelfInImplSelf { #[primary_span] pub span: MultiSpan, #[note] @@ -567,7 +567,7 @@ pub(crate) struct LinkageType { #[derive(Diagnostic)] #[help] #[diag(hir_analysis_auto_deref_reached_recursion_limit, code = E0055)] -pub struct AutoDerefReachedRecursionLimit<'a> { +pub(crate) struct AutoDerefReachedRecursionLimit<'a> { #[primary_span] #[label] pub span: Span, @@ -736,7 +736,7 @@ pub(crate) struct InvalidUnionField { #[derive(Diagnostic)] #[diag(hir_analysis_invalid_unnamed_field_ty)] -pub struct InvalidUnnamedFieldTy { +pub(crate) struct InvalidUnnamedFieldTy { #[primary_span] pub span: Span, } @@ -894,7 +894,7 @@ pub(crate) struct SIMDFFIHighlyExperimental { } #[derive(Diagnostic)] -pub enum ImplNotMarkedDefault { +pub(crate) enum ImplNotMarkedDefault { #[diag(hir_analysis_impl_not_marked_default, code = E0520)] #[note] Ok { @@ -1137,7 +1137,7 @@ pub(crate) enum LateBoundInApit { #[derive(LintDiagnostic)] #[diag(hir_analysis_unused_associated_type_bounds)] #[note] -pub struct UnusedAssociatedTypeBounds { +pub(crate) struct UnusedAssociatedTypeBounds { #[suggestion(code = "")] pub span: Span, } @@ -1162,7 +1162,7 @@ pub(crate) struct ReturnPositionImplTraitInTraitRefined<'tcx> { #[derive(Diagnostic)] #[diag(hir_analysis_inherent_ty_outside, code = E0390)] #[help] -pub struct InherentTyOutside { +pub(crate) struct InherentTyOutside { #[primary_span] #[help(hir_analysis_span_help)] pub span: Span, @@ -1170,7 +1170,7 @@ pub struct InherentTyOutside { #[derive(Diagnostic)] #[diag(hir_analysis_coerce_unsized_may, code = E0378)] -pub struct DispatchFromDynCoercion<'a> { +pub(crate) struct DispatchFromDynCoercion<'a> { #[primary_span] pub span: Span, pub trait_name: &'a str, @@ -1182,7 +1182,7 @@ pub struct DispatchFromDynCoercion<'a> { #[derive(Diagnostic)] #[diag(hir_analysis_dispatch_from_dyn_repr, code = E0378)] -pub struct DispatchFromDynRepr { +pub(crate) struct DispatchFromDynRepr { #[primary_span] pub span: Span, } @@ -1190,7 +1190,7 @@ pub struct DispatchFromDynRepr { #[derive(Diagnostic)] #[diag(hir_analysis_inherent_ty_outside_relevant, code = E0390)] #[help] -pub struct InherentTyOutsideRelevant { +pub(crate) struct InherentTyOutsideRelevant { #[primary_span] pub span: Span, #[help(hir_analysis_span_help)] @@ -1200,7 +1200,7 @@ pub struct InherentTyOutsideRelevant { #[derive(Diagnostic)] #[diag(hir_analysis_inherent_ty_outside_new, code = E0116)] #[note] -pub struct InherentTyOutsideNew { +pub(crate) struct InherentTyOutsideNew { #[primary_span] #[label] pub span: Span, @@ -1209,7 +1209,7 @@ pub struct InherentTyOutsideNew { #[derive(Diagnostic)] #[diag(hir_analysis_inherent_ty_outside_primitive, code = E0390)] #[help] -pub struct InherentTyOutsidePrimitive { +pub(crate) struct InherentTyOutsidePrimitive { #[primary_span] pub span: Span, #[help(hir_analysis_span_help)] @@ -1219,7 +1219,7 @@ pub struct InherentTyOutsidePrimitive { #[derive(Diagnostic)] #[diag(hir_analysis_inherent_primitive_ty, code = E0390)] #[help] -pub struct InherentPrimitiveTy<'a> { +pub(crate) struct InherentPrimitiveTy<'a> { #[primary_span] pub span: Span, #[subdiagnostic] @@ -1228,14 +1228,14 @@ pub struct InherentPrimitiveTy<'a> { #[derive(Subdiagnostic)] #[note(hir_analysis_inherent_primitive_ty_note)] -pub struct InherentPrimitiveTyNote<'a> { +pub(crate) struct InherentPrimitiveTyNote<'a> { pub subty: Ty<'a>, } #[derive(Diagnostic)] #[diag(hir_analysis_inherent_dyn, code = E0785)] #[note] -pub struct InherentDyn { +pub(crate) struct InherentDyn { #[primary_span] #[label] pub span: Span, @@ -1244,7 +1244,7 @@ pub struct InherentDyn { #[derive(Diagnostic)] #[diag(hir_analysis_inherent_nominal, code = E0118)] #[note] -pub struct InherentNominal { +pub(crate) struct InherentNominal { #[primary_span] #[label] pub span: Span, @@ -1253,7 +1253,7 @@ pub struct InherentNominal { #[derive(Diagnostic)] #[diag(hir_analysis_dispatch_from_dyn_zst, code = E0378)] #[note] -pub struct DispatchFromDynZST<'a> { +pub(crate) struct DispatchFromDynZST<'a> { #[primary_span] pub span: Span, pub name: Symbol, @@ -1262,7 +1262,7 @@ pub struct DispatchFromDynZST<'a> { #[derive(Diagnostic)] #[diag(hir_analysis_coerce_unsized_may, code = E0378)] -pub struct DispatchFromDynSingle<'a> { +pub(crate) struct DispatchFromDynSingle<'a> { #[primary_span] pub span: Span, pub trait_name: &'a str, @@ -1273,7 +1273,7 @@ pub struct DispatchFromDynSingle<'a> { #[derive(Diagnostic)] #[diag(hir_analysis_dispatch_from_dyn_multi, code = E0378)] #[note] -pub struct DispatchFromDynMulti { +pub(crate) struct DispatchFromDynMulti { #[primary_span] pub span: Span, #[note(hir_analysis_coercions_note)] @@ -1284,7 +1284,7 @@ pub struct DispatchFromDynMulti { #[derive(Diagnostic)] #[diag(hir_analysis_coerce_unsized_may, code = E0376)] -pub struct DispatchFromDynStruct<'a> { +pub(crate) struct DispatchFromDynStruct<'a> { #[primary_span] pub span: Span, pub trait_name: &'a str, @@ -1292,7 +1292,7 @@ pub struct DispatchFromDynStruct<'a> { #[derive(Diagnostic)] #[diag(hir_analysis_coerce_unsized_may, code = E0377)] -pub struct DispatchFromDynSame<'a> { +pub(crate) struct DispatchFromDynSame<'a> { #[primary_span] pub span: Span, pub trait_name: &'a str, @@ -1304,7 +1304,7 @@ pub struct DispatchFromDynSame<'a> { #[derive(Diagnostic)] #[diag(hir_analysis_coerce_unsized_may, code = E0374)] -pub struct CoerceUnsizedOneField<'a> { +pub(crate) struct CoerceUnsizedOneField<'a> { #[primary_span] pub span: Span, pub trait_name: &'a str, @@ -1315,7 +1315,7 @@ pub struct CoerceUnsizedOneField<'a> { #[derive(Diagnostic)] #[diag(hir_analysis_coerce_unsized_multi, code = E0375)] #[note] -pub struct CoerceUnsizedMulti { +pub(crate) struct CoerceUnsizedMulti { #[primary_span] #[label] pub span: Span, @@ -1327,7 +1327,7 @@ pub struct CoerceUnsizedMulti { #[derive(Diagnostic)] #[diag(hir_analysis_coerce_unsized_may, code = E0378)] -pub struct CoerceUnsizedMay<'a> { +pub(crate) struct CoerceUnsizedMay<'a> { #[primary_span] pub span: Span, pub trait_name: &'a str, @@ -1335,7 +1335,7 @@ pub struct CoerceUnsizedMay<'a> { #[derive(Diagnostic)] #[diag(hir_analysis_trait_cannot_impl_for_ty, code = E0204)] -pub struct TraitCannotImplForTy { +pub(crate) struct TraitCannotImplForTy { #[primary_span] pub span: Span, pub trait_name: String, @@ -1347,7 +1347,7 @@ pub struct TraitCannotImplForTy { #[derive(Subdiagnostic)] #[note(hir_analysis_requires_note)] -pub struct ImplForTyRequires { +pub(crate) struct ImplForTyRequires { #[primary_span] pub span: MultiSpan, pub error_predicate: String, @@ -1358,7 +1358,7 @@ pub struct ImplForTyRequires { #[derive(Diagnostic)] #[diag(hir_analysis_traits_with_defualt_impl, code = E0321)] #[note] -pub struct TraitsWithDefaultImpl<'a> { +pub(crate) struct TraitsWithDefaultImpl<'a> { #[primary_span] pub span: Span, pub traits: String, @@ -1368,7 +1368,7 @@ pub struct TraitsWithDefaultImpl<'a> { #[derive(Diagnostic)] #[diag(hir_analysis_cross_crate_traits, code = E0321)] -pub struct CrossCrateTraits<'a> { +pub(crate) struct CrossCrateTraits<'a> { #[primary_span] #[label] pub span: Span, @@ -1378,7 +1378,7 @@ pub struct CrossCrateTraits<'a> { #[derive(Diagnostic)] #[diag(hir_analysis_cross_crate_traits_defined, code = E0321)] -pub struct CrossCrateTraitsDefined { +pub(crate) struct CrossCrateTraitsDefined { #[primary_span] #[label] pub span: Span, @@ -1390,7 +1390,7 @@ pub struct CrossCrateTraitsDefined { #[derive(Diagnostic)] #[diag(hir_analysis_ty_param_first_local, code = E0210)] #[note] -pub struct TyParamFirstLocal<'tcx> { +pub(crate) struct TyParamFirstLocal<'tcx> { #[primary_span] #[label] pub span: Span, @@ -1403,7 +1403,7 @@ pub struct TyParamFirstLocal<'tcx> { #[derive(LintDiagnostic)] #[diag(hir_analysis_ty_param_first_local, code = E0210)] #[note] -pub struct TyParamFirstLocalLint<'tcx> { +pub(crate) struct TyParamFirstLocalLint<'tcx> { #[label] pub span: Span, #[note(hir_analysis_case_note)] @@ -1415,7 +1415,7 @@ pub struct TyParamFirstLocalLint<'tcx> { #[derive(Diagnostic)] #[diag(hir_analysis_ty_param_some, code = E0210)] #[note] -pub struct TyParamSome { +pub(crate) struct TyParamSome { #[primary_span] #[label] pub span: Span, @@ -1427,7 +1427,7 @@ pub struct TyParamSome { #[derive(LintDiagnostic)] #[diag(hir_analysis_ty_param_some, code = E0210)] #[note] -pub struct TyParamSomeLint { +pub(crate) struct TyParamSomeLint { #[label] pub span: Span, #[note(hir_analysis_only_note)] @@ -1436,7 +1436,7 @@ pub struct TyParamSomeLint { } #[derive(Diagnostic)] -pub enum OnlyCurrentTraits { +pub(crate) enum OnlyCurrentTraits { #[diag(hir_analysis_only_current_traits_outside, code = E0117)] Outside { #[primary_span] @@ -1465,20 +1465,20 @@ pub enum OnlyCurrentTraits { #[derive(Subdiagnostic)] #[label(hir_analysis_only_current_traits_opaque)] -pub struct OnlyCurrentTraitsOpaque { +pub(crate) struct OnlyCurrentTraitsOpaque { #[primary_span] pub span: Span, } #[derive(Subdiagnostic)] #[label(hir_analysis_only_current_traits_foreign)] -pub struct OnlyCurrentTraitsForeign { +pub(crate) struct OnlyCurrentTraitsForeign { #[primary_span] pub span: Span, } #[derive(Subdiagnostic)] #[label(hir_analysis_only_current_traits_name)] -pub struct OnlyCurrentTraitsName<'a> { +pub(crate) struct OnlyCurrentTraitsName<'a> { #[primary_span] pub span: Span, pub name: &'a str, @@ -1486,7 +1486,7 @@ pub struct OnlyCurrentTraitsName<'a> { #[derive(Subdiagnostic)] #[label(hir_analysis_only_current_traits_pointer)] -pub struct OnlyCurrentTraitsPointer<'a> { +pub(crate) struct OnlyCurrentTraitsPointer<'a> { #[primary_span] pub span: Span, pub pointer: Ty<'a>, @@ -1494,7 +1494,7 @@ pub struct OnlyCurrentTraitsPointer<'a> { #[derive(Subdiagnostic)] #[label(hir_analysis_only_current_traits_ty)] -pub struct OnlyCurrentTraitsTy<'a> { +pub(crate) struct OnlyCurrentTraitsTy<'a> { #[primary_span] pub span: Span, pub ty: Ty<'a>, @@ -1502,7 +1502,7 @@ pub struct OnlyCurrentTraitsTy<'a> { #[derive(Subdiagnostic)] #[label(hir_analysis_only_current_traits_adt)] -pub struct OnlyCurrentTraitsAdt { +pub(crate) struct OnlyCurrentTraitsAdt { #[primary_span] pub span: Span, pub name: String, @@ -1513,11 +1513,11 @@ pub struct OnlyCurrentTraitsAdt { hir_analysis_only_current_traits_pointer_sugg, applicability = "maybe-incorrect" )] -pub struct OnlyCurrentTraitsPointerSugg<'a> { +pub(crate) struct OnlyCurrentTraitsPointerSugg<'a> { #[suggestion_part(code = "WrapperType")] pub wrapper_span: Span, #[suggestion_part(code = "struct WrapperType(*{mut_key}{ptr_ty});\n\n")] - pub struct_span: Span, + pub(crate) struct_span: Span, pub mut_key: &'a str, pub ptr_ty: Ty<'a>, } @@ -1525,7 +1525,7 @@ pub struct OnlyCurrentTraitsPointerSugg<'a> { #[derive(Diagnostic)] #[diag(hir_analysis_static_mut_ref, code = E0796)] #[note] -pub struct StaticMutRef<'a> { +pub(crate) struct StaticMutRef<'a> { #[primary_span] #[label] pub span: Span, @@ -1535,7 +1535,7 @@ pub struct StaticMutRef<'a> { } #[derive(Subdiagnostic)] -pub enum MutRefSugg { +pub(crate) enum MutRefSugg { #[multipart_suggestion( hir_analysis_suggestion, style = "verbose", @@ -1565,7 +1565,7 @@ pub enum MutRefSugg { #[diag(hir_analysis_static_mut_refs_lint)] #[note] #[note(hir_analysis_why_note)] -pub struct RefOfMutStatic<'a> { +pub(crate) struct RefOfMutStatic<'a> { #[label] pub span: Span, #[subdiagnostic] @@ -1575,7 +1575,7 @@ pub struct RefOfMutStatic<'a> { #[derive(Diagnostic)] #[diag(hir_analysis_not_supported_delegation)] -pub struct UnsupportedDelegation<'a> { +pub(crate) struct UnsupportedDelegation<'a> { #[primary_span] pub span: Span, pub descr: &'a str, @@ -1585,7 +1585,7 @@ pub struct UnsupportedDelegation<'a> { #[derive(Diagnostic)] #[diag(hir_analysis_method_should_return_future)] -pub struct MethodShouldReturnFuture { +pub(crate) struct MethodShouldReturnFuture { #[primary_span] pub span: Span, pub method_name: Symbol, @@ -1606,7 +1606,7 @@ pub(crate) struct UnusedGenericParameter { #[subdiagnostic] pub help: UnusedGenericParameterHelp, #[help(hir_analysis_const_param_help)] - pub const_param_help: Option<()>, + pub const_param_help: bool, } #[derive(Diagnostic)] @@ -1643,13 +1643,13 @@ pub(crate) struct UnconstrainedGenericParameter { pub param_name: Symbol, pub param_def_kind: &'static str, #[note(hir_analysis_const_param_note)] - pub const_param_note: Option<()>, + pub const_param_note: bool, #[note(hir_analysis_const_param_note2)] - pub const_param_note2: Option<()>, + pub const_param_note2: bool, } #[derive(Diagnostic)] -pub enum UnnamedFieldsRepr<'a> { +pub(crate) enum UnnamedFieldsRepr<'a> { #[diag(hir_analysis_unnamed_fields_repr_missing_repr_c)] MissingReprC { #[primary_span] @@ -1678,14 +1678,14 @@ pub enum UnnamedFieldsRepr<'a> { #[derive(Subdiagnostic)] #[note(hir_analysis_unnamed_fields_repr_field_defined)] -pub struct UnnamedFieldsReprFieldDefined { +pub(crate) struct UnnamedFieldsReprFieldDefined { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(hir_analysis_opaque_captures_higher_ranked_lifetime, code = E0657)] -pub struct OpaqueCapturesHigherRankedLifetime { +pub(crate) struct OpaqueCapturesHigherRankedLifetime { #[primary_span] pub span: Span, #[label] @@ -1697,7 +1697,7 @@ pub struct OpaqueCapturesHigherRankedLifetime { #[derive(Diagnostic)] #[diag(hir_analysis_pattern_type_non_const_range)] -pub struct NonConstRange { +pub(crate) struct NonConstRange { #[primary_span] pub span: Span, } @@ -1706,7 +1706,7 @@ pub struct NonConstRange { #[diag(hir_analysis_invalid_receiver_ty, code = E0307)] #[note] #[help(hir_analysis_invalid_receiver_ty_help)] -pub struct InvalidReceiverTy<'tcx> { +pub(crate) struct InvalidReceiverTy<'tcx> { #[primary_span] pub span: Span, pub receiver_ty: Ty<'tcx>, @@ -1716,12 +1716,12 @@ pub struct InvalidReceiverTy<'tcx> { #[diag(hir_analysis_effects_without_next_solver)] #[note] #[help] -pub struct EffectsWithoutNextSolver; +pub(crate) struct EffectsWithoutNextSolver; #[derive(Diagnostic)] #[diag(hir_analysis_cmse_call_inputs_stack_spill, code = E0798)] #[note] -pub struct CmseCallInputsStackSpill { +pub(crate) struct CmseCallInputsStackSpill { #[primary_span] #[label] pub span: Span, @@ -1732,7 +1732,7 @@ pub struct CmseCallInputsStackSpill { #[diag(hir_analysis_cmse_call_output_stack_spill, code = E0798)] #[note(hir_analysis_note1)] #[note(hir_analysis_note2)] -pub struct CmseCallOutputStackSpill { +pub(crate) struct CmseCallOutputStackSpill { #[primary_span] #[label] pub span: Span, @@ -1740,7 +1740,7 @@ pub struct CmseCallOutputStackSpill { #[derive(Diagnostic)] #[diag(hir_analysis_cmse_call_generic, code = E0798)] -pub struct CmseCallGeneric { +pub(crate) struct CmseCallGeneric { #[primary_span] pub span: Span, } diff --git a/compiler/rustc_hir_analysis/src/errors/pattern_types.rs b/compiler/rustc_hir_analysis/src/errors/pattern_types.rs index 008d2698989..bb771d6ea17 100644 --- a/compiler/rustc_hir_analysis/src/errors/pattern_types.rs +++ b/compiler/rustc_hir_analysis/src/errors/pattern_types.rs @@ -3,7 +3,7 @@ use rustc_span::Span; #[derive(Diagnostic)] #[diag(hir_analysis_pattern_type_wild_pat)] -pub struct WildPatTy { +pub(crate) struct WildPatTy { #[primary_span] pub span: Span, } diff --git a/compiler/rustc_hir_analysis/src/errors/precise_captures.rs b/compiler/rustc_hir_analysis/src/errors/precise_captures.rs index 8a9b5fe6369..af2bb053c0a 100644 --- a/compiler/rustc_hir_analysis/src/errors/precise_captures.rs +++ b/compiler/rustc_hir_analysis/src/errors/precise_captures.rs @@ -4,7 +4,7 @@ use rustc_span::{Span, Symbol}; #[derive(Diagnostic)] #[diag(hir_analysis_param_not_captured)] #[note] -pub struct ParamNotCaptured { +pub(crate) struct ParamNotCaptured { #[primary_span] pub opaque_span: Span, #[label] @@ -15,7 +15,7 @@ pub struct ParamNotCaptured { #[derive(Diagnostic)] #[diag(hir_analysis_self_ty_not_captured)] #[note] -pub struct SelfTyNotCaptured { +pub(crate) struct SelfTyNotCaptured { #[primary_span] pub opaque_span: Span, #[label] @@ -24,7 +24,7 @@ pub struct SelfTyNotCaptured { #[derive(Diagnostic)] #[diag(hir_analysis_lifetime_not_captured)] -pub struct LifetimeNotCaptured { +pub(crate) struct LifetimeNotCaptured { #[primary_span] pub use_span: Span, #[label(hir_analysis_param_label)] @@ -35,7 +35,7 @@ pub struct LifetimeNotCaptured { #[derive(Diagnostic)] #[diag(hir_analysis_bad_precise_capture)] -pub struct BadPreciseCapture { +pub(crate) struct BadPreciseCapture { #[primary_span] pub span: Span, pub kind: &'static str, @@ -44,7 +44,7 @@ pub struct BadPreciseCapture { #[derive(Diagnostic)] #[diag(hir_analysis_precise_capture_self_alias)] -pub struct PreciseCaptureSelfAlias { +pub(crate) struct PreciseCaptureSelfAlias { #[primary_span] pub span: Span, #[label] @@ -54,7 +54,7 @@ pub struct PreciseCaptureSelfAlias { #[derive(Diagnostic)] #[diag(hir_analysis_duplicate_precise_capture)] -pub struct DuplicatePreciseCapture { +pub(crate) struct DuplicatePreciseCapture { #[primary_span] pub first_span: Span, pub name: Symbol, @@ -64,7 +64,7 @@ pub struct DuplicatePreciseCapture { #[derive(Diagnostic)] #[diag(hir_analysis_lifetime_must_be_first)] -pub struct LifetimesMustBeFirst { +pub(crate) struct LifetimesMustBeFirst { #[primary_span] pub lifetime_span: Span, pub name: Symbol, diff --git a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs index 8ecf53bfacb..f8b2469dfea 100644 --- a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs +++ b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs @@ -8,7 +8,7 @@ use rustc_span::def_id::DefId; use GenericArgsInfo::*; /// Handles the `wrong number of type / lifetime / ... arguments` family of error messages. -pub struct WrongNumberOfGenericArgs<'a, 'tcx> { +pub(crate) struct WrongNumberOfGenericArgs<'a, 'tcx> { pub(crate) tcx: TyCtxt<'tcx>, pub(crate) angle_brackets: AngleBrackets, @@ -49,7 +49,7 @@ pub(crate) enum AngleBrackets { // Information about the kind of arguments that are either missing or are unexpected #[derive(Debug)] -pub enum GenericArgsInfo { +pub(crate) enum GenericArgsInfo { MissingLifetimes { num_missing_args: usize, }, @@ -87,7 +87,7 @@ pub enum GenericArgsInfo { } impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { - pub fn new( + pub(crate) fn new( tcx: TyCtxt<'tcx>, gen_args_info: GenericArgsInfo, path_segment: &'a hir::PathSegment<'_>, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs index e99717ce00f..1b73cecd666 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs @@ -11,7 +11,7 @@ use crate::errors; /// Check conditions on inputs and outputs that the cmse ABIs impose: arguments and results MUST be /// returned via registers (i.e. MUST NOT spill to the stack). LLVM will also validate these /// conditions, but by checking them here rustc can emit nicer error messages. -pub fn validate_cmse_abi<'tcx>( +pub(crate) fn validate_cmse_abi<'tcx>( tcx: TyCtxt<'tcx>, dcx: DiagCtxtHandle<'_>, hir_id: HirId, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index d77cbe30536..af319fd53bd 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -608,7 +608,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| { let msg = format!("`{}`", if obligation.len() > 50 { quiet } else { obligation }); - match &self_ty.kind() { + match self_ty.kind() { // Point at the type that couldn't satisfy the bound. ty::Adt(def, _) => { bound_spans.get_mut_or_insert_default(tcx.def_span(def.did())).push(msg) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index 6aff518390f..7be45463f15 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -15,11 +15,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// /// *Bare* trait object types are ones that aren't preceded by the keyword `dyn`. /// In edition 2021 and onward we emit a hard error for them. - pub(super) fn prohibit_or_lint_bare_trait_object_ty( - &self, - self_ty: &hir::Ty<'_>, - in_path: bool, - ) { + pub(super) fn prohibit_or_lint_bare_trait_object_ty(&self, self_ty: &hir::Ty<'_>) { let tcx = self.tcx(); let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) = @@ -28,6 +24,21 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { return; }; + let in_path = match tcx.parent_hir_node(self_ty.hir_id) { + hir::Node::Ty(hir::Ty { + kind: hir::TyKind::Path(hir::QPath::TypeRelative(qself, _)), + .. + }) + | hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Path(hir::QPath::TypeRelative(qself, _)), + .. + }) + | hir::Node::Pat(hir::Pat { + kind: hir::PatKind::Path(hir::QPath::TypeRelative(qself, _)), + .. + }) if qself.hir_id == self_ty.hir_id => true, + _ => false, + }; let needs_bracket = in_path && !tcx .sess diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index d865357b829..0cdd3e4a1c6 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -85,10 +85,9 @@ pub enum PredicateFilter { #[derive(Debug)] pub enum RegionInferReason<'a> { - /// Lifetime on a trait object behind a reference. - /// This allows inferring information from the reference. - BorrowedObjectLifetimeDefault, - /// A trait object's lifetime. + /// Lifetime on a trait object that is spelled explicitly, e.g. `+ 'a` or `+ '_`. + ExplicitObjectLifetime, + /// A trait object's lifetime when it is elided, e.g. `dyn Any`. ObjectLifetimeDefault, /// Generic lifetime parameter Param(&'a ty::GenericParamDef), @@ -296,25 +295,29 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Some(rbv::ResolvedArg::StaticLifetime) => tcx.lifetimes.re_static, Some(rbv::ResolvedArg::LateBound(debruijn, index, def_id)) => { - let name = lifetime_name(def_id.expect_local()); + let name = lifetime_name(def_id); let br = ty::BoundRegion { var: ty::BoundVar::from_u32(index), - kind: ty::BrNamed(def_id, name), + kind: ty::BrNamed(def_id.to_def_id(), name), }; ty::Region::new_bound(tcx, debruijn, br) } Some(rbv::ResolvedArg::EarlyBound(def_id)) => { - let name = tcx.hir().ty_param_name(def_id.expect_local()); - let item_def_id = tcx.hir().ty_param_owner(def_id.expect_local()); + let name = tcx.hir().ty_param_name(def_id); + let item_def_id = tcx.hir().ty_param_owner(def_id); let generics = tcx.generics_of(item_def_id); - let index = generics.param_def_id_to_index[&def_id]; + let index = generics.param_def_id_to_index[&def_id.to_def_id()]; ty::Region::new_early_param(tcx, ty::EarlyParamRegion { index, name }) } Some(rbv::ResolvedArg::Free(scope, id)) => { - let name = lifetime_name(id.expect_local()); - ty::Region::new_late_param(tcx, scope, ty::BrNamed(id, name)) + let name = lifetime_name(id); + ty::Region::new_late_param( + tcx, + scope.to_def_id(), + ty::BrNamed(id.to_def_id(), name), + ) // (*) -- not late-bound, won't change } @@ -959,11 +962,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { \n where\n T: {qself_str},\n{}", where_bounds.join(",\n"), )); - } - let reported = err.emit(); - if !where_bounds.is_empty() { + let reported = err.emit(); return Err(reported); } + err.emit(); } Ok(bound) @@ -1054,7 +1056,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Find the type of the associated item, and the trait where the associated // item is declared. - let bound = match (&qself_ty.kind(), qself_res) { + let bound = match (qself_ty.kind(), qself_res) { (_, Res::SelfTyAlias { alias_to: impl_def_id, is_trait_impl: true, .. }) => { // `Self` in an impl of a trait -- we have a concrete self type and a // trait reference. @@ -1954,15 +1956,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let tcx = self.tcx(); match tcx.named_bound_var(hir_id) { Some(rbv::ResolvedArg::LateBound(debruijn, index, def_id)) => { - let name = tcx.item_name(def_id); + let name = tcx.item_name(def_id.to_def_id()); let br = ty::BoundTy { var: ty::BoundVar::from_u32(index), - kind: ty::BoundTyKind::Param(def_id, name), + kind: ty::BoundTyKind::Param(def_id.to_def_id(), name), }; Ty::new_bound(tcx, debruijn, br) } Some(rbv::ResolvedArg::EarlyBound(def_id)) => { - let def_id = def_id.expect_local(); let item_def_id = tcx.hir().ty_param_owner(def_id); let generics = tcx.generics_of(item_def_id); let index = generics.param_def_id_to_index[&def_id.to_def_id()]; @@ -1983,10 +1984,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Some(rbv::ResolvedArg::EarlyBound(def_id)) => { // Find the name and index of the const parameter by indexing the generics of // the parent item and construct a `ParamConst`. - let item_def_id = tcx.parent(def_id); + let item_def_id = tcx.local_parent(def_id); let generics = tcx.generics_of(item_def_id); - let index = generics.param_def_id_to_index[&def_id]; - let name = tcx.item_name(def_id); + let index = generics.param_def_id_to_index[&def_id.to_def_id()]; + let name = tcx.item_name(def_id.to_def_id()); ty::Const::new_param(tcx, ty::ParamConst::new(index, name)) } Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => { @@ -1997,16 +1998,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } - /// Lower a type from the HIR to our internal notion of a type. - pub fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { - self.lower_ty_common(hir_ty, false, false) - } - - /// Lower a type inside of a path from the HIR to our internal notion of a type. - pub fn lower_ty_in_path(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { - self.lower_ty_common(hir_ty, false, true) - } - fn lower_delegation_ty(&self, idx: hir::InferDelegationKind) -> Ty<'tcx> { let delegation_sig = self.tcx().inherit_sig_for_delegation_item(self.item_def_id()); match idx { @@ -2024,7 +2015,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// 2. `in_path`: Whether the type appears inside of a path. /// Used to provide correct diagnostics for bare trait object types. #[instrument(level = "debug", skip(self), ret)] - fn lower_ty_common(&self, hir_ty: &hir::Ty<'tcx>, borrowed: bool, in_path: bool) -> Ty<'tcx> { + pub fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { let tcx = self.tcx(); let result_ty = match &hir_ty.kind { @@ -2034,7 +2025,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir::TyKind::Ref(region, mt) => { let r = self.lower_lifetime(region, RegionInferReason::Reference); debug!(?r); - let t = self.lower_ty_common(mt.ty, true, false); + let t = self.lower_ty(mt.ty); Ty::new_ref(tcx, r, t, mt.mutbl) } hir::TyKind::Never => tcx.types.never, @@ -2063,20 +2054,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) } hir::TyKind::TraitObject(bounds, lifetime, repr) => { - self.prohibit_or_lint_bare_trait_object_ty(hir_ty, in_path); + self.prohibit_or_lint_bare_trait_object_ty(hir_ty); let repr = match repr { TraitObjectSyntax::Dyn | TraitObjectSyntax::None => ty::Dyn, TraitObjectSyntax::DynStar => ty::DynStar, }; - self.lower_trait_object_ty( - hir_ty.span, - hir_ty.hir_id, - bounds, - lifetime, - borrowed, - repr, - ) + self.lower_trait_object_ty(hir_ty.span, hir_ty.hir_id, bounds, lifetime, repr) } hir::TyKind::Path(hir::QPath::Resolved(maybe_qself, path)) => { debug!(?maybe_qself, ?path); @@ -2104,7 +2088,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } hir::TyKind::Path(hir::QPath::TypeRelative(qself, segment)) => { debug!(?qself, ?segment); - let ty = self.lower_ty_common(qself, false, true); + let ty = self.lower_ty(qself); self.lower_assoc_path(hir_ty.hir_id, hir_ty.span, ty, qself, segment, false) .map(|(ty, _, _)| ty) .unwrap_or_else(|guar| Ty::new_error(tcx, guar)) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs index 31d1750f33d..52e167379b5 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs @@ -30,7 +30,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir_id: hir::HirId, hir_trait_bounds: &[(hir::PolyTraitRef<'tcx>, hir::TraitBoundModifier)], lifetime: &hir::Lifetime, - borrowed: bool, representation: DynKind, ) -> Ty<'tcx> { let tcx = self.tcx(); @@ -325,22 +324,32 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { v.dedup(); let existential_predicates = tcx.mk_poly_existential_predicates(&v); - // Use explicitly-specified region bound. + // Use explicitly-specified region bound, unless the bound is missing. let region_bound = if !lifetime.is_elided() { - self.lower_lifetime(lifetime, RegionInferReason::ObjectLifetimeDefault) + self.lower_lifetime(lifetime, RegionInferReason::ExplicitObjectLifetime) } else { self.compute_object_lifetime_bound(span, existential_predicates).unwrap_or_else(|| { + // Curiously, we prefer object lifetime default for `+ '_`... if tcx.named_bound_var(lifetime.hir_id).is_some() { - self.lower_lifetime(lifetime, RegionInferReason::ObjectLifetimeDefault) + self.lower_lifetime(lifetime, RegionInferReason::ExplicitObjectLifetime) } else { - self.re_infer( - span, - if borrowed { - RegionInferReason::ObjectLifetimeDefault + let reason = + if let hir::LifetimeName::ImplicitObjectLifetimeDefault = lifetime.res { + if let hir::Node::Ty(hir::Ty { + kind: hir::TyKind::Ref(parent_lifetime, _), + .. + }) = tcx.parent_hir_node(hir_id) + && tcx.named_bound_var(parent_lifetime.hir_id).is_none() + { + // Parent lifetime must have failed to resolve. Don't emit a redundant error. + RegionInferReason::ExplicitObjectLifetime + } else { + RegionInferReason::ObjectLifetimeDefault + } } else { - RegionInferReason::BorrowedObjectLifetimeDefault - }, - ) + RegionInferReason::ExplicitObjectLifetime + }; + self.re_infer(span, reason) } }) }; diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index 7d2cabd3f2c..3ecf61501f6 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -11,7 +11,7 @@ use rustc_trait_selection::traits::{self, ObligationCtxt}; use crate::collect::ItemCtxt; -pub fn provide(providers: &mut Providers) { +pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { diagnostic_hir_wf_check, ..*providers }; } diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs index ab441ed4cde..7f183324f04 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs @@ -53,7 +53,10 @@ mod min_specialization; /// impl<'a> Trait for Bar { type X = &'a i32; } /// // ^ 'a is unused and appears in assoc type, error /// ``` -pub fn check_impl_wf(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) -> Result<(), ErrorGuaranteed> { +pub(crate) fn check_impl_wf( + tcx: TyCtxt<'_>, + impl_def_id: LocalDefId, +) -> Result<(), ErrorGuaranteed> { let min_specialization = tcx.features().min_specialization; let mut res = Ok(()); debug_assert_matches!(tcx.def_kind(impl_def_id), DefKind::Impl { .. }); @@ -137,8 +140,7 @@ fn enforce_impl_params_are_constrained( } }; if err { - let const_param_note = - matches!(param.kind, ty::GenericParamDefKind::Const { .. }).then_some(()); + let const_param_note = matches!(param.kind, ty::GenericParamDefKind::Const { .. }); let mut diag = tcx.dcx().create_err(UnconstrainedGenericParameter { span: tcx.def_span(param.def_id), param_name: param.name, diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 291d57f2a17..891e4fcd019 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -72,6 +72,7 @@ This API is completely unstable and subject to change. #![feature(slice_partition_dedup)] #![feature(try_blocks)] #![feature(unwrap_infallible)] +#![warn(unreachable_pub)] // tidy-alphabetical-end #[macro_use] @@ -200,10 +201,6 @@ pub fn check_crate(tcx: TyCtxt<'_>) { } }); - // Freeze definitions as we don't add new ones at this point. This improves performance by - // allowing lock-free access to them. - tcx.untracked().definitions.freeze(); - // FIXME: Remove this when we implement creating `DefId`s // for anon constants during their parents' typeck. // Typeck all body owners in parallel will produce queries diff --git a/compiler/rustc_hir_analysis/src/outlives/explicit.rs b/compiler/rustc_hir_analysis/src/outlives/explicit.rs index bbfadbb5c30..f576499ecac 100644 --- a/compiler/rustc_hir_analysis/src/outlives/explicit.rs +++ b/compiler/rustc_hir_analysis/src/outlives/explicit.rs @@ -5,12 +5,12 @@ use rustc_middle::ty::{self, OutlivesPredicate, TyCtxt}; use super::utils::*; #[derive(Debug)] -pub struct ExplicitPredicatesMap<'tcx> { +pub(crate) struct ExplicitPredicatesMap<'tcx> { map: FxIndexMap>>, } impl<'tcx> ExplicitPredicatesMap<'tcx> { - pub fn new() -> ExplicitPredicatesMap<'tcx> { + pub(crate) fn new() -> ExplicitPredicatesMap<'tcx> { ExplicitPredicatesMap { map: FxIndexMap::default() } } diff --git a/compiler/rustc_hir_analysis/src/outlives/mod.rs b/compiler/rustc_hir_analysis/src/outlives/mod.rs index cb61ef7c64d..e3cdb1bf5f7 100644 --- a/compiler/rustc_hir_analysis/src/outlives/mod.rs +++ b/compiler/rustc_hir_analysis/src/outlives/mod.rs @@ -9,7 +9,7 @@ mod explicit; mod implicit_infer; mod utils; -pub fn provide(providers: &mut Providers) { +pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { inferred_outlives_of, inferred_outlives_crate, ..*providers }; } diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs index 92baa41e07f..4fb7a02f8c9 100644 --- a/compiler/rustc_hir_analysis/src/variance/constraints.rs +++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs @@ -12,7 +12,7 @@ use rustc_middle::{bug, span_bug}; use super::terms::VarianceTerm::*; use super::terms::*; -pub struct ConstraintContext<'a, 'tcx> { +pub(crate) struct ConstraintContext<'a, 'tcx> { pub terms_cx: TermsContext<'a, 'tcx>, // These are pointers to common `ConstantTerm` instances @@ -27,7 +27,7 @@ pub struct ConstraintContext<'a, 'tcx> { /// Declares that the variable `decl_id` appears in a location with /// variance `variance`. #[derive(Copy, Clone)] -pub struct Constraint<'a> { +pub(crate) struct Constraint<'a> { pub inferred: InferredIndex, pub variance: &'a VarianceTerm<'a>, } @@ -41,11 +41,11 @@ pub struct Constraint<'a> { /// ``` /// then while we are visiting `Bar`, the `CurrentItem` would have /// the `DefId` and the start of `Foo`'s inferreds. -pub struct CurrentItem { +struct CurrentItem { inferred_start: InferredIndex, } -pub fn add_constraints_from_crate<'a, 'tcx>( +pub(crate) fn add_constraints_from_crate<'a, 'tcx>( terms_cx: TermsContext<'a, 'tcx>, ) -> ConstraintContext<'a, 'tcx> { let tcx = terms_cx.tcx; @@ -317,8 +317,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.add_constraint(current, data.index, variance); } - ty::FnPtr(sig) => { - self.add_constraints_from_sig(current, sig, variance); + ty::FnPtr(sig_tys, hdr) => { + self.add_constraints_from_sig(current, sig_tys.with(hdr), variance); } ty::Error(_) => { diff --git a/compiler/rustc_hir_analysis/src/variance/dump.rs b/compiler/rustc_hir_analysis/src/variance/dump.rs index 1a17dabb677..ace183986bd 100644 --- a/compiler/rustc_hir_analysis/src/variance/dump.rs +++ b/compiler/rustc_hir_analysis/src/variance/dump.rs @@ -1,18 +1,36 @@ +use std::fmt::Write; + use rustc_hir::def::DefKind; -use rustc_hir::def_id::CRATE_DEF_ID; -use rustc_middle::ty::TyCtxt; +use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; +use rustc_middle::ty::{GenericArgs, TyCtxt}; use rustc_span::symbol::sym; +fn format_variances(tcx: TyCtxt<'_>, def_id: LocalDefId) -> String { + let variances = tcx.variances_of(def_id); + let generics = GenericArgs::identity_for_item(tcx, def_id); + // 7 = 2-letter parameter + ": " + 1-letter variance + ", " + let mut ret = String::with_capacity(2 + 7 * variances.len()); + ret.push('['); + for (arg, variance) in generics.iter().zip(variances.iter()) { + write!(ret, "{arg}: {variance:?}, ").unwrap(); + } + // Remove trailing `, `. + if !variances.is_empty() { + ret.pop(); + ret.pop(); + } + ret.push(']'); + ret +} + pub(crate) fn variances(tcx: TyCtxt<'_>) { if tcx.has_attr(CRATE_DEF_ID, sym::rustc_variance_of_opaques) { for id in tcx.hir().items() { let DefKind::OpaqueTy = tcx.def_kind(id.owner_id) else { continue }; - let variances = tcx.variances_of(id.owner_id); - tcx.dcx().emit_err(crate::errors::VariancesOf { span: tcx.def_span(id.owner_id), - variances: format!("{variances:?}"), + variances: format_variances(tcx, id.owner_id.def_id), }); } } @@ -22,11 +40,9 @@ pub(crate) fn variances(tcx: TyCtxt<'_>) { continue; } - let variances = tcx.variances_of(id.owner_id); - tcx.dcx().emit_err(crate::errors::VariancesOf { span: tcx.def_span(id.owner_id), - variances: format!("{variances:?}"), + variances: format_variances(tcx, id.owner_id.def_id), }); } } diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index 8a4114c3e4b..e8e2caf7e62 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -28,7 +28,7 @@ pub(crate) mod dump; /// Code for transforming variances. mod xform; -pub fn provide(providers: &mut Providers) { +pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { variances_of, crate_variances, ..*providers }; } diff --git a/compiler/rustc_hir_analysis/src/variance/solve.rs b/compiler/rustc_hir_analysis/src/variance/solve.rs index e64c6721fe0..4f1bac17e71 100644 --- a/compiler/rustc_hir_analysis/src/variance/solve.rs +++ b/compiler/rustc_hir_analysis/src/variance/solve.rs @@ -21,7 +21,7 @@ struct SolveContext<'a, 'tcx> { solutions: Vec, } -pub fn solve_constraints<'tcx>( +pub(crate) fn solve_constraints<'tcx>( constraints_cx: ConstraintContext<'_, 'tcx>, ) -> ty::CrateVariancesMap<'tcx> { let ConstraintContext { terms_cx, constraints, .. } = constraints_cx; diff --git a/compiler/rustc_hir_analysis/src/variance/terms.rs b/compiler/rustc_hir_analysis/src/variance/terms.rs index 36bff60e019..597699b37b1 100644 --- a/compiler/rustc_hir_analysis/src/variance/terms.rs +++ b/compiler/rustc_hir_analysis/src/variance/terms.rs @@ -18,13 +18,13 @@ use rustc_middle::ty::{self, TyCtxt}; use self::VarianceTerm::*; -pub type VarianceTermPtr<'a> = &'a VarianceTerm<'a>; +pub(crate) type VarianceTermPtr<'a> = &'a VarianceTerm<'a>; #[derive(Copy, Clone, Debug)] -pub struct InferredIndex(pub usize); +pub(crate) struct InferredIndex(pub usize); #[derive(Copy, Clone)] -pub enum VarianceTerm<'a> { +pub(crate) enum VarianceTerm<'a> { ConstantTerm(ty::Variance), TransformTerm(VarianceTermPtr<'a>, VarianceTermPtr<'a>), InferredTerm(InferredIndex), @@ -45,7 +45,7 @@ impl<'a> fmt::Debug for VarianceTerm<'a> { /// The first pass over the crate simply builds up the set of inferreds. -pub struct TermsContext<'a, 'tcx> { +pub(crate) struct TermsContext<'a, 'tcx> { pub tcx: TyCtxt<'tcx>, pub arena: &'a DroplessArena, @@ -62,7 +62,7 @@ pub struct TermsContext<'a, 'tcx> { pub inferred_terms: Vec>, } -pub fn determine_parameters_to_be_inferred<'a, 'tcx>( +pub(crate) fn determine_parameters_to_be_inferred<'a, 'tcx>( tcx: TyCtxt<'tcx>, arena: &'a DroplessArena, ) -> TermsContext<'a, 'tcx> { diff --git a/compiler/rustc_hir_analysis/src/variance/xform.rs b/compiler/rustc_hir_analysis/src/variance/xform.rs index 027f0859fcd..2e9964788e6 100644 --- a/compiler/rustc_hir_analysis/src/variance/xform.rs +++ b/compiler/rustc_hir_analysis/src/variance/xform.rs @@ -1,6 +1,6 @@ use rustc_middle::ty; -pub fn glb(v1: ty::Variance, v2: ty::Variance) -> ty::Variance { +pub(crate) fn glb(v1: ty::Variance, v2: ty::Variance) -> ty::Variance { // Greatest lower bound of the variance lattice as // defined in The Paper: // diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 089cee2fa0d..ac6707f9316 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -3,6 +3,7 @@ // tidy-alphabetical-start #![recursion_limit = "256"] +#![warn(unreachable_pub)] // tidy-alphabetical-end use std::cell::Cell; @@ -352,16 +353,11 @@ impl<'a> State<'a> { self.maybe_print_comment(item.span.lo()); self.print_outer_attributes(self.attrs(item.hir_id())); match item.kind { - hir::ForeignItemKind::Fn(decl, arg_names, generics, safety) => { + hir::ForeignItemKind::Fn(sig, arg_names, generics) => { self.head(""); self.print_fn( - decl, - hir::FnHeader { - safety, - constness: hir::Constness::NotConst, - abi: Abi::Rust, - asyncness: hir::IsAsync::NotAsync, - }, + sig.decl, + sig.header, Some(item.ident.name), generics, arg_names, diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index bc0ed4a7fa9..7427fb14716 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -374,7 +374,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn maybe_get_coercion_reason( + pub(crate) fn maybe_get_coercion_reason( &self, hir_id: hir::HirId, sp: Span, @@ -584,7 +584,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // (e.g. we're in the tail of a function body) // // Returns the `LocalDefId` of the RPIT, which is always identity-substituted. - pub fn return_position_impl_trait_from_match_expectation( + pub(crate) fn return_position_impl_trait_from_match_expectation( &self, expectation: Expectation<'tcx>, ) -> Option { diff --git a/compiler/rustc_hir_typeck/src/autoderef.rs b/compiler/rustc_hir_typeck/src/autoderef.rs index 69c4889d7a4..d2d6da8f32b 100644 --- a/compiler/rustc_hir_typeck/src/autoderef.rs +++ b/compiler/rustc_hir_typeck/src/autoderef.rs @@ -13,11 +13,11 @@ use super::method::MethodCallee; use super::{FnCtxt, PlaceOp}; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { - pub fn autoderef(&'a self, span: Span, base_ty: Ty<'tcx>) -> Autoderef<'a, 'tcx> { + pub(crate) fn autoderef(&'a self, span: Span, base_ty: Ty<'tcx>) -> Autoderef<'a, 'tcx> { Autoderef::new(self, self.param_env, self.body_id, span, base_ty) } - pub fn try_overloaded_deref( + pub(crate) fn try_overloaded_deref( &self, span: Span, base_ty: Ty<'tcx>, @@ -26,11 +26,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } /// Returns the adjustment steps. - pub fn adjust_steps(&self, autoderef: &Autoderef<'a, 'tcx>) -> Vec> { + pub(crate) fn adjust_steps(&self, autoderef: &Autoderef<'a, 'tcx>) -> Vec> { self.register_infer_ok_obligations(self.adjust_steps_as_infer_ok(autoderef)) } - pub fn adjust_steps_as_infer_ok( + pub(crate) fn adjust_steps_as_infer_ok( &self, autoderef: &Autoderef<'a, 'tcx>, ) -> InferOk<'tcx, Vec>> { diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 07f64ead6f6..fc08b872efc 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -29,7 +29,7 @@ use crate::errors; /// Checks that it is legal to call methods of the trait corresponding /// to `trait_id` (this only cares about the trait, not the specific /// method that is called). -pub fn check_legal_trait_for_method_call( +pub(crate) fn check_legal_trait_for_method_call( tcx: TyCtxt<'_>, span: Span, receiver: Option, @@ -62,7 +62,7 @@ enum CallStep<'tcx> { } impl<'a, 'tcx> FnCtxt<'a, 'tcx> { - pub fn check_call( + pub(crate) fn check_call( &self, call_expr: &'tcx hir::Expr<'tcx>, callee_expr: &'tcx hir::Expr<'tcx>, @@ -137,7 +137,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If the callee is a bare function or a closure, then we're all set. match *adjusted_ty.kind() { - ty::FnDef(..) | ty::FnPtr(_) => { + ty::FnDef(..) | ty::FnPtr(..) => { let adjustments = self.adjust_steps(autoderef); self.apply_adjustments(callee_expr, adjustments); return Some(CallStep::Builtin(adjusted_ty)); @@ -467,7 +467,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (fn_sig, Some(def_id)) } // FIXME(effects): these arms should error because we can't enforce them - ty::FnPtr(sig) => (sig, None), + ty::FnPtr(sig_tys, hdr) => (sig_tys.with(hdr), None), _ => { for arg in arg_exprs { self.check_expr(arg); @@ -940,7 +940,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } #[derive(Debug)] -pub struct DeferredCallResolution<'tcx> { +pub(crate) struct DeferredCallResolution<'tcx> { call_expr: &'tcx hir::Expr<'tcx>, callee_expr: &'tcx hir::Expr<'tcx>, closure_ty: Ty<'tcx>, @@ -949,7 +949,7 @@ pub struct DeferredCallResolution<'tcx> { } impl<'a, 'tcx> DeferredCallResolution<'tcx> { - pub fn resolve(self, fcx: &FnCtxt<'a, 'tcx>) { + pub(crate) fn resolve(self, fcx: &FnCtxt<'a, 'tcx>) { debug!("DeferredCallResolution::resolve() {:?}", self); // we should not be invoked until the closure kind has been diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 7cd97166ed1..3a309d2ec0b 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -505,7 +505,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { span: self.span, expr_ty: self.expr_ty, cast_ty: fcx.ty_to_string(self.cast_ty), - teach: fcx.tcx.sess.teach(E0607).then_some(()), + teach: fcx.tcx.sess.teach(E0607), }); } CastError::IntToFatCast(known_metadata) => { @@ -967,7 +967,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { // need to special-case obtaining a raw pointer // from a region pointer to a vector. - // Coerce to a raw pointer so that we generate AddressOf in MIR. + // Coerce to a raw pointer so that we generate RawPtr in MIR. let array_ptr_type = Ty::new_ptr(fcx.tcx, m_expr.ty, m_expr.mutbl); fcx.coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No, None) .unwrap_or_else(|_| { diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index 89df464cca0..cd357e4a7ad 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -160,15 +160,11 @@ pub(super) fn check_fn<'a, 'tcx>( fcx.demand_suptype(span, ret_ty, actual_return_ty); // Check that a function marked as `#[panic_handler]` has signature `fn(&PanicInfo) -> !` - if let Some(panic_impl_did) = tcx.lang_items().panic_impl() - && panic_impl_did == fn_def_id.to_def_id() - { - check_panic_info_fn(tcx, panic_impl_did.expect_local(), fn_sig); + if tcx.is_lang_item(fn_def_id.to_def_id(), LangItem::PanicImpl) { + check_panic_info_fn(tcx, fn_def_id, fn_sig); } - if let Some(lang_start_defid) = tcx.lang_items().start_fn() - && lang_start_defid == fn_def_id.to_def_id() - { + if tcx.is_lang_item(fn_def_id.to_def_id(), LangItem::Start) { check_lang_start_fn(tcx, fn_sig, fn_def_id); } diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index a7953acc95c..6b813dc64ce 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -14,7 +14,7 @@ use rustc_middle::span_bug; use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt}; use rustc_middle::ty::{self, GenericArgs, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor}; use rustc_span::def_id::LocalDefId; -use rustc_span::Span; +use rustc_span::{Span, DUMMY_SP}; use rustc_target::spec::abi::Abi; use rustc_trait_selection::error_reporting::traits::ArgKind; use rustc_trait_selection::traits; @@ -336,9 +336,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .into_iter() .map(|obl| (obl.predicate, obl.cause.span)), ), - ty::FnPtr(sig) => match closure_kind { + ty::FnPtr(sig_tys, hdr) => match closure_kind { hir::ClosureKind::Closure => { - let expected_sig = ExpectedSig { cause_span: None, sig }; + let expected_sig = ExpectedSig { cause_span: None, sig: sig_tys.with(hdr) }; (Some(expected_sig), Some(ty::ClosureKind::Fn)) } hir::ClosureKind::Coroutine(_) | hir::ClosureKind::CoroutineClosure(_) => { @@ -539,6 +539,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// we identify the `FnOnce` bound, and if the output type is /// an inference variable `?Fut`, we check if that is bounded by a `Future` /// projection. + /// + /// This function is actually best-effort with the return type; if we don't find a + /// `Future` projection, we still will return arguments that we extracted from the `FnOnce` + /// projection, and the output will be an unconstrained type variable instead. fn extract_sig_from_projection_and_future_bound( &self, cause_span: Option, @@ -564,24 +568,43 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; // FIXME: We may want to elaborate here, though I assume this will be exceedingly rare. + let mut return_ty = None; for bound in self.obligations_for_self_ty(return_vid) { if let Some(ret_projection) = bound.predicate.as_projection_clause() && let Some(ret_projection) = ret_projection.no_bound_vars() && self.tcx.is_lang_item(ret_projection.def_id(), LangItem::FutureOutput) { - let sig = projection.rebind(self.tcx.mk_fn_sig( - input_tys, - ret_projection.term.expect_type(), - false, - hir::Safety::Safe, - Abi::Rust, - )); - - return Some(ExpectedSig { cause_span, sig }); + return_ty = Some(ret_projection.term.expect_type()); + break; } } - None + // SUBTLE: If we didn't find a `Future` bound for the return + // vid, we still want to attempt to provide inference guidance for the async + // closure's arguments. Instantiate a new vid to plug into the output type. + // + // You may be wondering, what if it's higher-ranked? Well, given that we + // found a type variable for the `FnOnce::Output` projection above, we know + // that the output can't mention any of the vars. + // + // Also note that we use a fresh var here for the signature since the signature + // records the output of the *future*, and `return_vid` above is the type + // variable of the future, not its output. + // + // FIXME: We probably should store this signature inference output in a way + // that does not misuse a `FnSig` type, but that can be done separately. + let return_ty = + return_ty.unwrap_or_else(|| self.next_ty_var(cause_span.unwrap_or(DUMMY_SP))); + + let sig = projection.rebind(self.tcx.mk_fn_sig( + input_tys, + return_ty, + false, + hir::Safety::Safe, + Abi::Rust, + )); + + return Some(ExpectedSig { cause_span, sig }); } fn sig_of_closure( diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index fcd3798eb48..54ddff98869 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -106,7 +106,7 @@ fn identity(_: Ty<'_>) -> Vec> { vec![] } -fn simple<'tcx>(kind: Adjust<'tcx>) -> impl FnOnce(Ty<'tcx>) -> Vec> { +fn simple<'tcx>(kind: Adjust<'tcx>) -> impl FnOnce(Ty<'tcx>) -> Vec> { move |target| vec![Adjustment { kind, target }] } @@ -137,7 +137,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { at.lub(DefineOpaqueTypes::Yes, b, a) } else { at.sup(DefineOpaqueTypes::Yes, b, a) - .map(|InferOk { value: (), obligations }| InferOk { value: a, obligations }) + .map(|InferOk { value: (), obligations }| InferOk { value: b, obligations }) }; // In the new solver, lazy norm may allow us to shallowly equate @@ -225,10 +225,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // items to drop the unsafe qualifier. self.coerce_from_fn_item(a, b) } - ty::FnPtr(a_f) => { + ty::FnPtr(a_sig_tys, a_hdr) => { // We permit coercion of fn pointers to drop the // unsafe qualifier. - self.coerce_from_fn_pointer(a, a_f, b) + self.coerce_from_fn_pointer(a, a_sig_tys.with(a_hdr), b) } ty::Closure(closure_def_id_a, args_a) => { // Non-capturing closures are coercible to @@ -788,9 +788,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { self.commit_if_ok(|snapshot| { let outer_universe = self.infcx.universe(); - let result = if let ty::FnPtr(fn_ty_b) = b.kind() - && let (hir::Safety::Safe, hir::Safety::Unsafe) = - (fn_ty_a.safety(), fn_ty_b.safety()) + let result = if let ty::FnPtr(_, hdr_b) = b.kind() + && let (hir::Safety::Safe, hir::Safety::Unsafe) = (fn_ty_a.safety(), hdr_b.safety) { let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a); self.unify_and(unsafe_a, b, to_unsafe) @@ -842,7 +841,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { debug!("coerce_from_fn_item(a={:?}, b={:?})", a, b); match b.kind() { - ty::FnPtr(b_sig) => { + ty::FnPtr(_, b_hdr) => { let a_sig = a.fn_sig(self.tcx); if let ty::FnDef(def_id, _) = *a.kind() { // Intrinsics are not coercible to function pointers @@ -851,8 +850,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } // Safe `#[target_feature]` functions are not assignable to safe fn pointers (RFC 2396). + // FIXME(struct_target_features): should this be true also for functions that inherit + // target features from structs? - if b_sig.safety() == hir::Safety::Safe + if b_hdr.safety == hir::Safety::Safe && !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty() { return Err(TypeError::TargetFeatureCast(def_id)); @@ -910,7 +911,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // // All we care here is if any variable is being captured and not the exact paths, // so we check `upvars_mentioned` for root variables being captured. - ty::FnPtr(fn_ty) + ty::FnPtr(_, hdr) if self .tcx .upvars_mentioned(closure_def_id_a.expect_local()) @@ -923,7 +924,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // or // `unsafe fn(arg0,arg1,...) -> _` let closure_sig = args_a.as_closure().sig(); - let safety = fn_ty.safety(); + let safety = hdr.safety; let pointer_ty = Ty::new_fn_ptr(self.tcx, self.tcx.signature_unclosure(closure_sig, safety)); debug!("coerce_closure_to_fn(a={:?}, b={:?}, pty={:?})", a, b, pointer_ty); @@ -977,7 +978,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// adjusted type of the expression, if successful. /// Adjustments are only recorded if the coercion succeeded. /// The expressions *must not* have any preexisting adjustments. - pub fn coerce( + pub(crate) fn coerce( &self, expr: &hir::Expr<'_>, expr_ty: Ty<'tcx>, @@ -1012,7 +1013,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// /// Returns false if the coercion creates any obligations that result in /// errors. - pub fn can_coerce(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> bool { + pub(crate) fn can_coerce(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> bool { // FIXME(-Znext-solver): We need to structurally resolve both types here. let source = self.resolve_vars_with_obligations(expr_ty); debug!("coercion::can_with_predicates({:?} -> {:?})", source, target); @@ -1033,7 +1034,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Given a type and a target type, this function will calculate and return /// how many dereference steps needed to achieve `expr_ty <: target`. If /// it's not possible, return `None`. - pub fn deref_steps(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> Option { + pub(crate) fn deref_steps(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> Option { let cause = self.cause(DUMMY_SP, ObligationCauseCode::ExprAssignable); // We don't ever need two-phase here since we throw out the result of the coercion let coerce = Coerce::new(self, cause, AllowTwoPhase::No); @@ -1048,7 +1049,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// This function is for diagnostics only, since it does not register /// trait or region sub-obligations. (presumably we could, but it's not /// particularly important for diagnostics...) - pub fn deref_once_mutably_for_diagnostic(&self, expr_ty: Ty<'tcx>) -> Option> { + pub(crate) fn deref_once_mutably_for_diagnostic(&self, expr_ty: Ty<'tcx>) -> Option> { self.autoderef(DUMMY_SP, expr_ty).nth(1).and_then(|(deref_ty, _)| { self.infcx .type_implements_trait( @@ -1342,7 +1343,7 @@ pub fn can_coerce<'tcx>( /// } /// let final_ty = coerce.complete(fcx); /// ``` -pub struct CoerceMany<'tcx, 'exprs, E: AsCoercionSite> { +pub(crate) struct CoerceMany<'tcx, 'exprs, E: AsCoercionSite> { expected_ty: Ty<'tcx>, final_ty: Option>, expressions: Expressions<'tcx, 'exprs, E>, @@ -1351,7 +1352,7 @@ pub struct CoerceMany<'tcx, 'exprs, E: AsCoercionSite> { /// The type of a `CoerceMany` that is storing up the expressions into /// a buffer. We use this in `check/mod.rs` for things like `break`. -pub type DynamicCoerceMany<'tcx> = CoerceMany<'tcx, 'tcx, &'tcx hir::Expr<'tcx>>; +pub(crate) type DynamicCoerceMany<'tcx> = CoerceMany<'tcx, 'tcx, &'tcx hir::Expr<'tcx>>; enum Expressions<'tcx, 'exprs, E: AsCoercionSite> { Dynamic(Vec<&'tcx hir::Expr<'tcx>>), @@ -1362,7 +1363,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { /// The usual case; collect the set of expressions dynamically. /// If the full set of coercion sites is known before hand, /// consider `with_coercion_sites()` instead to avoid allocation. - pub fn new(expected_ty: Ty<'tcx>) -> Self { + pub(crate) fn new(expected_ty: Ty<'tcx>) -> Self { Self::make(expected_ty, Expressions::Dynamic(vec![])) } @@ -1371,7 +1372,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { /// expected to pass each element in the slice to `coerce(...)` in /// order. This is used with arrays in particular to avoid /// needlessly cloning the slice. - pub fn with_coercion_sites(expected_ty: Ty<'tcx>, coercion_sites: &'exprs [E]) -> Self { + pub(crate) fn with_coercion_sites(expected_ty: Ty<'tcx>, coercion_sites: &'exprs [E]) -> Self { Self::make(expected_ty, Expressions::UpFront(coercion_sites)) } @@ -1387,7 +1388,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { /// Typically, this is used as the expected type when /// type-checking each of the alternative expressions whose types /// we are trying to merge. - pub fn expected_ty(&self) -> Ty<'tcx> { + pub(crate) fn expected_ty(&self) -> Ty<'tcx> { self.expected_ty } @@ -1395,7 +1396,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { /// at the LUB of the expressions we've seen so far (if any). This /// isn't *final* until you call `self.complete()`, which will return /// the merged type. - pub fn merged_ty(&self) -> Ty<'tcx> { + pub(crate) fn merged_ty(&self) -> Ty<'tcx> { self.final_ty.unwrap_or(self.expected_ty) } @@ -1404,7 +1405,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { /// could coerce from. This will record `expression`, and later /// calls to `coerce` may come back and add adjustments and things /// if necessary. - pub fn coerce<'a>( + pub(crate) fn coerce<'a>( &mut self, fcx: &FnCtxt<'a, 'tcx>, cause: &ObligationCause<'tcx>, @@ -1426,7 +1427,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { /// The `augment_error` gives you a chance to extend the error /// message, in case any results (e.g., we use this to suggest /// removing a `;`). - pub fn coerce_forced_unit<'a>( + pub(crate) fn coerce_forced_unit<'a>( &mut self, fcx: &FnCtxt<'a, 'tcx>, cause: &ObligationCause<'tcx>, @@ -1860,7 +1861,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { }; // If this is due to an explicit `return`, suggest adding a return type. - if let Some((fn_id, fn_decl, can_suggest)) = fcx.get_fn_decl(parent_id) + if let Some((fn_id, fn_decl, can_suggest)) = fcx.get_fn_decl(block_or_return_id) && !due_to_block { fcx.suggest_missing_return_type(&mut err, fn_decl, expected, found, can_suggest, fn_id); @@ -1921,7 +1922,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { } } - pub fn complete<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Ty<'tcx> { + pub(crate) fn complete<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Ty<'tcx> { if let Some(final_ty) = self.final_ty { final_ty } else { @@ -1935,7 +1936,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { /// Something that can be converted into an expression to which we can /// apply a coercion. -pub trait AsCoercionSite { +pub(crate) trait AsCoercionSite { fn as_coercion_site(&self) -> &hir::Expr<'_>; } diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 0a9fa5c64a5..89f27e80774 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -18,7 +18,7 @@ use super::method::probe; use crate::FnCtxt; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { - pub fn emit_type_mismatch_suggestions( + pub(crate) fn emit_type_mismatch_suggestions( &self, err: &mut Diag<'_>, expr: &hir::Expr<'tcx>, @@ -70,7 +70,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn emit_coerce_suggestions( + pub(crate) fn emit_coerce_suggestions( &self, err: &mut Diag<'_>, expr: &hir::Expr<'tcx>, @@ -165,13 +165,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Requires that the two types unify, and prints an error message if /// they don't. - pub fn demand_suptype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) { + pub(crate) fn demand_suptype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) { if let Err(e) = self.demand_suptype_diag(sp, expected, actual) { e.emit(); } } - pub fn demand_suptype_diag( + pub(crate) fn demand_suptype_diag( &'a self, sp: Span, expected: Ty<'tcx>, @@ -193,13 +193,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .map_err(|e| self.err_ctxt().report_mismatched_types(cause, expected, actual, e)) } - pub fn demand_eqtype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) { + pub(crate) fn demand_eqtype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) { if let Err(err) = self.demand_eqtype_diag(sp, expected, actual) { err.emit(); } } - pub fn demand_eqtype_diag( + pub(crate) fn demand_eqtype_diag( &'a self, sp: Span, expected: Ty<'tcx>, @@ -208,7 +208,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.demand_eqtype_with_origin(&self.misc(sp), expected, actual) } - pub fn demand_eqtype_with_origin( + pub(crate) fn demand_eqtype_with_origin( &'a self, cause: &ObligationCause<'tcx>, expected: Ty<'tcx>, @@ -220,7 +220,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .map_err(|e| self.err_ctxt().report_mismatched_types(cause, expected, actual, e)) } - pub fn demand_coerce( + pub(crate) fn demand_coerce( &self, expr: &'tcx hir::Expr<'tcx>, checked_ty: Ty<'tcx>, @@ -279,7 +279,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Notes the point at which a variable is constrained to some type incompatible /// with some expectation given by `source`. - pub fn note_source_of_type_mismatch_constraint( + pub(crate) fn note_source_of_type_mismatch_constraint( &self, err: &mut Diag<'_>, expr: &hir::Expr<'_>, @@ -558,7 +558,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // When encountering a type error on the value of a `break`, try to point at the reason for the // expected type. - pub fn annotate_loop_expected_due_to_inference( + pub(crate) fn annotate_loop_expected_due_to_inference( &self, err: &mut Diag<'_>, expr: &hir::Expr<'_>, @@ -964,7 +964,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } - pub fn get_conversion_methods_for_diagnostic( + pub(crate) fn get_conversion_methods_for_diagnostic( &self, span: Span, expected: Ty<'tcx>, @@ -1186,7 +1186,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } -pub enum TypeMismatchSource<'tcx> { +pub(crate) enum TypeMismatchSource<'tcx> { /// Expected the binding to have the given type, but it was found to have /// a different type. Find out when that type first became incompatible. Ty(Ty<'tcx>), diff --git a/compiler/rustc_hir_typeck/src/diverges.rs b/compiler/rustc_hir_typeck/src/diverges.rs index aa30fb0f0af..3066561a31d 100644 --- a/compiler/rustc_hir_typeck/src/diverges.rs +++ b/compiler/rustc_hir_typeck/src/diverges.rs @@ -8,7 +8,7 @@ use rustc_span::{Span, DUMMY_SP}; /// as diverging), with some manual adjustments for control-flow /// primitives (approximating a CFG). #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub enum Diverges { +pub(crate) enum Diverges { /// Potentially unknown, some cases converge, /// others require a CFG to determine them. Maybe, diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index f802b8cf9cc..4d2770d2e50 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -17,7 +17,7 @@ use crate::fluent_generated as fluent; #[derive(Diagnostic)] #[diag(hir_typeck_field_multiply_specified_in_initializer, code = E0062)] -pub struct FieldMultiplySpecifiedInInitializer { +pub(crate) struct FieldMultiplySpecifiedInInitializer { #[primary_span] #[label] pub span: Span, @@ -28,7 +28,7 @@ pub struct FieldMultiplySpecifiedInInitializer { #[derive(Diagnostic)] #[diag(hir_typeck_return_stmt_outside_of_fn_body, code = E0572)] -pub struct ReturnStmtOutsideOfFnBody { +pub(crate) struct ReturnStmtOutsideOfFnBody { #[primary_span] pub span: Span, #[label(hir_typeck_encl_body_label)] @@ -38,7 +38,7 @@ pub struct ReturnStmtOutsideOfFnBody { pub statement_kind: ReturnLikeStatementKind, } -pub enum ReturnLikeStatementKind { +pub(crate) enum ReturnLikeStatementKind { Return, Become, } @@ -57,21 +57,21 @@ impl IntoDiagArg for ReturnLikeStatementKind { #[derive(Diagnostic)] #[diag(hir_typeck_rustcall_incorrect_args)] -pub struct RustCallIncorrectArgs { +pub(crate) struct RustCallIncorrectArgs { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(hir_typeck_yield_expr_outside_of_coroutine, code = E0627)] -pub struct YieldExprOutsideOfCoroutine { +pub(crate) struct YieldExprOutsideOfCoroutine { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(hir_typeck_struct_expr_non_exhaustive, code = E0639)] -pub struct StructExprNonExhaustive { +pub(crate) struct StructExprNonExhaustive { #[primary_span] pub span: Span, pub what: &'static str, @@ -79,21 +79,21 @@ pub struct StructExprNonExhaustive { #[derive(Diagnostic)] #[diag(hir_typeck_functional_record_update_on_non_struct, code = E0436)] -pub struct FunctionalRecordUpdateOnNonStruct { +pub(crate) struct FunctionalRecordUpdateOnNonStruct { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(hir_typeck_address_of_temporary_taken, code = E0745)] -pub struct AddressOfTemporaryTaken { +pub(crate) struct AddressOfTemporaryTaken { #[primary_span] #[label] pub span: Span, } #[derive(Subdiagnostic)] -pub enum AddReturnTypeSuggestion { +pub(crate) enum AddReturnTypeSuggestion { #[suggestion( hir_typeck_add_return_type_add, code = " -> {found}", @@ -116,7 +116,7 @@ pub enum AddReturnTypeSuggestion { } #[derive(Subdiagnostic)] -pub enum ExpectedReturnTypeLabel<'tcx> { +pub(crate) enum ExpectedReturnTypeLabel<'tcx> { #[label(hir_typeck_expected_default_return_type)] Unit { #[primary_span] @@ -132,7 +132,7 @@ pub enum ExpectedReturnTypeLabel<'tcx> { #[derive(Diagnostic)] #[diag(hir_typeck_explicit_destructor, code = E0040)] -pub struct ExplicitDestructorCall { +pub(crate) struct ExplicitDestructorCall { #[primary_span] #[label] pub span: Span, @@ -141,7 +141,7 @@ pub struct ExplicitDestructorCall { } #[derive(Subdiagnostic)] -pub enum ExplicitDestructorCallSugg { +pub(crate) enum ExplicitDestructorCallSugg { #[suggestion(hir_typeck_suggestion, code = "drop", applicability = "maybe-incorrect")] Empty(#[primary_span] Span), #[multipart_suggestion(hir_typeck_suggestion, style = "short")] @@ -155,7 +155,7 @@ pub enum ExplicitDestructorCallSugg { #[derive(Diagnostic)] #[diag(hir_typeck_missing_parentheses_in_range, code = E0689)] -pub struct MissingParenthesesInRange { +pub(crate) struct MissingParenthesesInRange { #[primary_span] #[label(hir_typeck_missing_parentheses_in_range)] pub span: Span, @@ -166,7 +166,7 @@ pub struct MissingParenthesesInRange { } #[derive(LintDiagnostic)] -pub enum NeverTypeFallbackFlowingIntoUnsafe { +pub(crate) enum NeverTypeFallbackFlowingIntoUnsafe { #[help] #[diag(hir_typeck_never_type_fallback_flowing_into_unsafe_call)] Call, @@ -187,7 +187,7 @@ pub enum NeverTypeFallbackFlowingIntoUnsafe { #[derive(LintDiagnostic)] #[help] #[diag(hir_typeck_dependency_on_unit_never_type_fallback)] -pub struct DependencyOnUnitNeverTypeFallback<'tcx> { +pub(crate) struct DependencyOnUnitNeverTypeFallback<'tcx> { #[note] pub obligation_span: Span, pub obligation: ty::Predicate<'tcx>, @@ -199,7 +199,7 @@ pub struct DependencyOnUnitNeverTypeFallback<'tcx> { style = "verbose", applicability = "maybe-incorrect" )] -pub struct AddMissingParenthesesInRange { +pub(crate) struct AddMissingParenthesesInRange { pub func_name: String, #[suggestion_part(code = "(")] pub left: Span, @@ -207,7 +207,7 @@ pub struct AddMissingParenthesesInRange { pub right: Span, } -pub struct TypeMismatchFruTypo { +pub(crate) struct TypeMismatchFruTypo { /// Span of the LHS of the range pub expr_span: Span, /// Span of the `..RHS` part of the range @@ -246,7 +246,7 @@ impl Subdiagnostic for TypeMismatchFruTypo { #[derive(LintDiagnostic)] #[diag(hir_typeck_lossy_provenance_int2ptr)] #[help] -pub struct LossyProvenanceInt2Ptr<'tcx> { +pub(crate) struct LossyProvenanceInt2Ptr<'tcx> { pub expr_ty: Ty<'tcx>, pub cast_ty: Ty<'tcx>, #[subdiagnostic] @@ -255,14 +255,14 @@ pub struct LossyProvenanceInt2Ptr<'tcx> { #[derive(LintDiagnostic)] #[diag(hir_typeck_ptr_cast_add_auto_to_object)] -pub struct PtrCastAddAutoToObject { +pub(crate) struct PtrCastAddAutoToObject { pub traits_len: usize, pub traits: DiagSymbolList, } #[derive(Subdiagnostic)] #[multipart_suggestion(hir_typeck_suggestion, applicability = "has-placeholders")] -pub struct LossyProvenanceInt2PtrSuggestion { +pub(crate) struct LossyProvenanceInt2PtrSuggestion { #[suggestion_part(code = "(...).with_addr(")] pub lo: Span, #[suggestion_part(code = ")")] @@ -272,7 +272,7 @@ pub struct LossyProvenanceInt2PtrSuggestion { #[derive(LintDiagnostic)] #[diag(hir_typeck_lossy_provenance_ptr2int)] #[help] -pub struct LossyProvenancePtr2Int<'tcx> { +pub(crate) struct LossyProvenancePtr2Int<'tcx> { pub expr_ty: Ty<'tcx>, pub cast_ty: Ty<'tcx>, #[subdiagnostic] @@ -280,7 +280,7 @@ pub struct LossyProvenancePtr2Int<'tcx> { } #[derive(Subdiagnostic)] -pub enum LossyProvenancePtr2IntSuggestion<'tcx> { +pub(crate) enum LossyProvenancePtr2IntSuggestion<'tcx> { #[multipart_suggestion(hir_typeck_suggestion, applicability = "maybe-incorrect")] NeedsParensCast { #[suggestion_part(code = "(")] @@ -314,7 +314,7 @@ pub enum LossyProvenancePtr2IntSuggestion<'tcx> { } #[derive(Subdiagnostic)] -pub enum HelpUseLatestEdition { +pub(crate) enum HelpUseLatestEdition { #[help(hir_typeck_help_set_edition_cargo)] #[note(hir_typeck_note_edition_guide)] Cargo { edition: Edition }, @@ -324,7 +324,7 @@ pub enum HelpUseLatestEdition { } impl HelpUseLatestEdition { - pub fn new() -> Self { + pub(crate) fn new() -> Self { let edition = LATEST_STABLE_EDITION; if rustc_session::utils::was_invoked_from_cargo() { Self::Cargo { edition } @@ -336,7 +336,7 @@ impl HelpUseLatestEdition { #[derive(Diagnostic)] #[diag(hir_typeck_invalid_callee, code = E0618)] -pub struct InvalidCallee { +pub(crate) struct InvalidCallee { #[primary_span] pub span: Span, pub ty: String, @@ -344,7 +344,7 @@ pub struct InvalidCallee { #[derive(Diagnostic)] #[diag(hir_typeck_int_to_fat, code = E0606)] -pub struct IntToWide<'tcx> { +pub(crate) struct IntToWide<'tcx> { #[primary_span] #[label(hir_typeck_int_to_fat_label)] pub span: Span, @@ -357,7 +357,7 @@ pub struct IntToWide<'tcx> { } #[derive(Subdiagnostic)] -pub enum OptionResultRefMismatch { +pub(crate) enum OptionResultRefMismatch { #[suggestion( hir_typeck_option_result_copied, code = ".copied()", @@ -396,7 +396,7 @@ pub enum OptionResultRefMismatch { // }, } -pub struct RemoveSemiForCoerce { +pub(crate) struct RemoveSemiForCoerce { pub expr: Span, pub ret: Span, pub semi: Span, @@ -426,7 +426,7 @@ impl Subdiagnostic for RemoveSemiForCoerce { #[derive(Diagnostic)] #[diag(hir_typeck_const_select_must_be_const)] #[help] -pub struct ConstSelectMustBeConst { +pub(crate) struct ConstSelectMustBeConst { #[primary_span] pub span: Span, } @@ -435,7 +435,7 @@ pub struct ConstSelectMustBeConst { #[diag(hir_typeck_const_select_must_be_fn)] #[note] #[help] -pub struct ConstSelectMustBeFn<'a> { +pub(crate) struct ConstSelectMustBeFn<'a> { #[primary_span] pub span: Span, pub ty: Ty<'a>, @@ -443,14 +443,14 @@ pub struct ConstSelectMustBeFn<'a> { #[derive(Diagnostic)] #[diag(hir_typeck_union_pat_multiple_fields)] -pub struct UnionPatMultipleFields { +pub(crate) struct UnionPatMultipleFields { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(hir_typeck_union_pat_dotdot)] -pub struct UnionPatDotDot { +pub(crate) struct UnionPatDotDot { #[primary_span] pub span: Span, } @@ -461,7 +461,7 @@ pub struct UnionPatDotDot { applicability = "maybe-incorrect", style = "verbose" )] -pub struct UseIsEmpty { +pub(crate) struct UseIsEmpty { #[suggestion_part(code = "!")] pub lo: Span, #[suggestion_part(code = ".is_empty()")] @@ -471,13 +471,13 @@ pub struct UseIsEmpty { #[derive(Diagnostic)] #[diag(hir_typeck_arg_mismatch_indeterminate)] -pub struct ArgMismatchIndeterminate { +pub(crate) struct ArgMismatchIndeterminate { #[primary_span] pub span: Span, } #[derive(Subdiagnostic)] -pub enum SuggestBoxing { +pub(crate) enum SuggestBoxing { #[note(hir_typeck_suggest_boxing_note)] #[multipart_suggestion( hir_typeck_suggest_boxing_when_appropriate, @@ -511,7 +511,7 @@ pub enum SuggestBoxing { style = "verbose", code = "core::ptr::null_mut()" )] -pub struct SuggestPtrNullMut { +pub(crate) struct SuggestPtrNullMut { #[primary_span] pub span: Span, } @@ -519,7 +519,7 @@ pub struct SuggestPtrNullMut { #[derive(LintDiagnostic)] #[diag(hir_typeck_trivial_cast)] #[help] -pub struct TrivialCast<'tcx> { +pub(crate) struct TrivialCast<'tcx> { pub numeric: bool, pub expr_ty: Ty<'tcx>, pub cast_ty: Ty<'tcx>, @@ -527,7 +527,7 @@ pub struct TrivialCast<'tcx> { #[derive(Diagnostic)] #[diag(hir_typeck_no_associated_item, code = E0599)] -pub struct NoAssociatedItem { +pub(crate) struct NoAssociatedItem { #[primary_span] pub span: Span, pub item_kind: &'static str, @@ -539,7 +539,7 @@ pub struct NoAssociatedItem { #[derive(Subdiagnostic)] #[note(hir_typeck_candidate_trait_note)] -pub struct CandidateTraitNote { +pub(crate) struct CandidateTraitNote { #[primary_span] pub span: Span, pub trait_name: String, @@ -549,7 +549,7 @@ pub struct CandidateTraitNote { #[derive(Diagnostic)] #[diag(hir_typeck_cannot_cast_to_bool, code = E0054)] -pub struct CannotCastToBool<'tcx> { +pub(crate) struct CannotCastToBool<'tcx> { #[primary_span] pub span: Span, pub expr_ty: Ty<'tcx>, @@ -559,14 +559,14 @@ pub struct CannotCastToBool<'tcx> { #[derive(LintDiagnostic)] #[diag(hir_typeck_cast_enum_drop)] -pub struct CastEnumDrop<'tcx> { +pub(crate) struct CastEnumDrop<'tcx> { pub expr_ty: Ty<'tcx>, pub cast_ty: Ty<'tcx>, } #[derive(Diagnostic)] #[diag(hir_typeck_cast_unknown_pointer, code = E0641)] -pub struct CastUnknownPointer { +pub(crate) struct CastUnknownPointer { #[primary_span] pub span: Span, pub to: bool, @@ -574,7 +574,7 @@ pub struct CastUnknownPointer { pub sub: CastUnknownPointerSub, } -pub enum CastUnknownPointerSub { +pub(crate) enum CastUnknownPointerSub { To(Span), From(Span), } @@ -601,7 +601,7 @@ impl rustc_errors::Subdiagnostic for CastUnknownPointerSub { } #[derive(Subdiagnostic)] -pub enum CannotCastToBoolHelp { +pub(crate) enum CannotCastToBoolHelp { #[suggestion( hir_typeck_suggestion, applicability = "machine-applicable", @@ -615,7 +615,7 @@ pub enum CannotCastToBoolHelp { #[derive(Diagnostic)] #[diag(hir_typeck_ctor_is_private, code = E0603)] -pub struct CtorIsPrivate { +pub(crate) struct CtorIsPrivate { #[primary_span] pub span: Span, pub def: String, @@ -623,7 +623,7 @@ pub struct CtorIsPrivate { #[derive(Subdiagnostic)] #[note(hir_typeck_deref_is_empty)] -pub struct DerefImplsIsEmpty { +pub(crate) struct DerefImplsIsEmpty { #[primary_span] pub span: Span, pub deref_ty: String, @@ -635,7 +635,7 @@ pub struct DerefImplsIsEmpty { applicability = "machine-applicable", style = "verbose" )] -pub struct SuggestConvertViaMethod<'tcx> { +pub(crate) struct SuggestConvertViaMethod<'tcx> { #[suggestion_part(code = "{sugg}")] pub span: Span, #[suggestion_part(code = "")] @@ -647,13 +647,13 @@ pub struct SuggestConvertViaMethod<'tcx> { #[derive(Subdiagnostic)] #[note(hir_typeck_note_caller_chooses_ty_for_ty_param)] -pub struct NoteCallerChoosesTyForTyParam<'tcx> { +pub(crate) struct NoteCallerChoosesTyForTyParam<'tcx> { pub ty_param_name: Symbol, pub found_ty: Ty<'tcx>, } #[derive(Subdiagnostic)] -pub enum SuggestBoxingForReturnImplTrait { +pub(crate) enum SuggestBoxingForReturnImplTrait { #[multipart_suggestion(hir_typeck_rpit_change_return_type, applicability = "maybe-incorrect")] ChangeReturnType { #[suggestion_part(code = "Box { pub expr_ty: Ty<'tcx>, pub cast_ty: String, #[note(hir_typeck_teach_help)] - pub(crate) teach: Option<()>, + pub(crate) teach: bool, } #[derive(Diagnostic)] @@ -720,7 +720,7 @@ pub(crate) struct PassToVariadicFunction<'tcx, 'a> { pub sugg_span: Option, pub replace: String, #[help] - pub help: Option<()>, + pub help: bool, #[note(hir_typeck_teach_help)] - pub(crate) teach: Option<()>, + pub(crate) teach: bool, } diff --git a/compiler/rustc_hir_typeck/src/expectation.rs b/compiler/rustc_hir_typeck/src/expectation.rs index 76ae41db5c5..67f4dbee3cb 100644 --- a/compiler/rustc_hir_typeck/src/expectation.rs +++ b/compiler/rustc_hir_typeck/src/expectation.rs @@ -7,7 +7,7 @@ use super::FnCtxt; /// When type-checking an expression, we propagate downward /// whatever type hint we are able in the form of an `Expectation`. #[derive(Copy, Clone, Debug)] -pub enum Expectation<'tcx> { +pub(crate) enum Expectation<'tcx> { /// We know nothing about what type this expression should have. NoExpectation, diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index fec6efdc0f7..dd33b947b0d 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -51,7 +51,7 @@ use crate::{ }; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { - pub fn check_expr_has_type_or_error( + pub(crate) fn check_expr_has_type_or_error( &self, expr: &'tcx hir::Expr<'tcx>, expected_ty: Ty<'tcx>, @@ -841,6 +841,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ret_ty = ret_coercion.borrow().expected_ty(); let return_expr_ty = self.check_expr_with_hint(return_expr, ret_ty); let mut span = return_expr.span; + let mut hir_id = return_expr.hir_id; // Use the span of the trailing expression for our cause, // not the span of the entire function if !explicit_return @@ -848,6 +849,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && let Some(last_expr) = body.expr { span = last_expr.span; + hir_id = last_expr.hir_id; } ret_coercion.borrow_mut().coerce( self, @@ -864,6 +866,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.select_obligations_where_possible(|errors| { self.point_at_return_for_opaque_ty_error( errors, + hir_id, span, return_expr_ty, return_expr.span, @@ -921,6 +924,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn point_at_return_for_opaque_ty_error( &self, errors: &mut Vec>, + hir_id: HirId, span: Span, return_expr_ty: Ty<'tcx>, return_span: Span, @@ -935,7 +939,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let new_cause = ObligationCause::new( cause.span, cause.body_id, - ObligationCauseCode::OpaqueReturnType(Some((return_expr_ty, span))), + ObligationCauseCode::OpaqueReturnType(Some((return_expr_ty, hir_id))), ); *cause = new_cause; } @@ -973,7 +977,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } /// Check if the expression that could not be assigned to was a typoed expression that - pub fn check_for_missing_semi(&self, expr: &'tcx hir::Expr<'tcx>, err: &mut Diag<'_>) -> bool { + pub(crate) fn check_for_missing_semi( + &self, + expr: &'tcx hir::Expr<'tcx>, + err: &mut Diag<'_>, + ) -> bool { if let hir::ExprKind::Binary(binop, lhs, rhs) = expr.kind && let hir::BinOpKind::Mul = binop.node && self.tcx.sess.source_map().is_multiline(lhs.span.between(rhs.span)) diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index 6e1b7504626..b1dc19b3777 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -18,7 +18,7 @@ use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt}; use crate::{errors, FnCtxt, TypeckRootCtxt}; #[derive(Copy, Clone)] -pub enum DivergingFallbackBehavior { +pub(crate) enum DivergingFallbackBehavior { /// Always fallback to `()` (aka "always spontaneous decay") ToUnit, /// Sometimes fallback to `!`, but mainly fallback to `()` so that most of the crates are not broken. diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index b169f75796b..2d205d1ede9 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -132,18 +132,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { deferred_call_resolutions.remove(&closure_def_id).unwrap_or_default() } - pub fn tag(&self) -> String { + fn tag(&self) -> String { format!("{self:p}") } - pub fn local_ty(&self, span: Span, nid: HirId) -> Ty<'tcx> { + pub(crate) fn local_ty(&self, span: Span, nid: HirId) -> Ty<'tcx> { self.locals.borrow().get(&nid).cloned().unwrap_or_else(|| { span_bug!(span, "no type for local variable {}", self.tcx.hir().node_to_string(nid)) }) } #[inline] - pub fn write_ty(&self, id: HirId, ty: Ty<'tcx>) { + pub(crate) fn write_ty(&self, id: HirId, ty: Ty<'tcx>) { debug!("write_ty({:?}, {:?}) in fcx {}", id, self.resolve_vars_if_possible(ty), self.tag()); let mut typeck = self.typeck_results.borrow_mut(); let mut node_ty = typeck.node_types_mut(); @@ -165,7 +165,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn write_field_index( + pub(crate) fn write_field_index( &self, hir_id: HirId, index: FieldIdx, @@ -198,7 +198,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.write_args(hir_id, method.args); } - pub fn write_args(&self, node_id: HirId, args: GenericArgsRef<'tcx>) { + fn write_args(&self, node_id: HirId, args: GenericArgsRef<'tcx>) { if !args.is_empty() { debug!("write_args({:?}, {:?}) in fcx {}", node_id, args, self.tag()); @@ -364,7 +364,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) } - pub fn require_type_meets( + pub(crate) fn require_type_meets( &self, ty: Ty<'tcx>, span: Span, @@ -374,7 +374,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.register_bound(ty, def_id, traits::ObligationCause::new(span, self.body_id, code)); } - pub fn require_type_is_sized( + pub(crate) fn require_type_is_sized( &self, ty: Ty<'tcx>, span: Span, @@ -386,7 +386,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn require_type_is_sized_deferred( + pub(crate) fn require_type_is_sized_deferred( &self, ty: Ty<'tcx>, span: Span, @@ -397,7 +397,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn require_type_has_static_alignment( + pub(crate) fn require_type_has_static_alignment( &self, ty: Ty<'tcx>, span: Span, @@ -426,7 +426,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn register_bound( + pub(crate) fn register_bound( &self, ty: Ty<'tcx>, def_id: DefId, @@ -443,7 +443,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> LoweredTy<'tcx> { + pub(crate) fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> LoweredTy<'tcx> { let ty = self.lowerer().lower_ty(hir_ty); self.register_wf_obligation(ty.into(), hir_ty.span, ObligationCauseCode::WellFormed(None)); LoweredTy::from_raw(self, hir_ty.span, ty) @@ -474,7 +474,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn lower_array_length(&self, length: &hir::ArrayLen<'tcx>) -> ty::Const<'tcx> { + pub(crate) fn lower_array_length(&self, length: &hir::ArrayLen<'tcx>) -> ty::Const<'tcx> { match length { hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span), hir::ArrayLen::Body(const_arg) => { @@ -486,7 +486,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn lower_const_arg( + pub(crate) fn lower_const_arg( &self, const_arg: &'tcx hir::ConstArg<'tcx>, param_def_id: DefId, @@ -515,7 +515,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { t.has_free_regions() || t.has_aliases() || t.has_infer_types() } - pub fn node_ty(&self, id: HirId) -> Ty<'tcx> { + pub(crate) fn node_ty(&self, id: HirId) -> Ty<'tcx> { match self.typeck_results.borrow().node_types().get(id) { Some(&t) => t, None if let Some(e) = self.tainted_by_errors() => Ty::new_error(self.tcx, e), @@ -529,7 +529,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn node_ty_opt(&self, id: HirId) -> Option> { + pub(crate) fn node_ty_opt(&self, id: HirId) -> Option> { match self.typeck_results.borrow().node_types().get(id) { Some(&t) => Some(t), None if let Some(e) = self.tainted_by_errors() => Some(Ty::new_error(self.tcx, e)), @@ -538,7 +538,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } /// Registers an obligation for checking later, during regionck, that `arg` is well-formed. - pub fn register_wf_obligation( + pub(crate) fn register_wf_obligation( &self, arg: ty::GenericArg<'tcx>, span: Span, @@ -555,7 +555,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } /// Registers obligations that all `args` are well-formed. - pub fn add_wf_bounds(&self, args: GenericArgsRef<'tcx>, expr: &hir::Expr<'_>) { + pub(crate) fn add_wf_bounds(&self, args: GenericArgsRef<'tcx>, expr: &hir::Expr<'_>) { for arg in args.iter().filter(|arg| { matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..)) }) { @@ -566,7 +566,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // FIXME(arielb1): use this instead of field.ty everywhere // Only for fields! Returns for methods> // Indifferent to privacy flags - pub fn field_ty( + pub(crate) fn field_ty( &self, span: Span, field: &'tcx ty::FieldDef, @@ -798,7 +798,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // to be object-safe. // We manually call `register_wf_obligation` in the success path // below. - let ty = self.lowerer().lower_ty_in_path(qself); + let ty = self.lowerer().lower_ty(qself); (LoweredTy::from_raw(self, span, ty), qself, segment) } QPath::LangItem(..) => { @@ -897,7 +897,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Given a `HirId`, return the `HirId` of the enclosing function, its `FnDecl`, and whether a /// suggestion can be made, `None` otherwise. - pub fn get_fn_decl( + pub(crate) fn get_fn_decl( &self, blk_id: HirId, ) -> Option<(LocalDefId, &'tcx hir::FnDecl<'tcx>, bool)> { @@ -1534,7 +1534,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// /// If no resolution is possible, then an error is reported. /// Numeric inference variables may be left unresolved. - pub fn structurally_resolve_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> { + pub(crate) fn structurally_resolve_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> { let ty = self.try_structurally_resolve_type(sp, ty); if !ty.is_ty_var() { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index 130fd130ec8..a8ba9f139cc 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -12,7 +12,7 @@ use rustc_trait_selection::traits; use crate::FnCtxt; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { - pub fn adjust_fulfillment_error_for_expr_obligation( + pub(crate) fn adjust_fulfillment_error_for_expr_obligation( &self, error: &mut traits::FulfillmentError<'tcx>, ) -> bool { @@ -483,7 +483,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { * * This function only updates the error span. */ - pub fn blame_specific_expr_if_possible( + pub(crate) fn blame_specific_expr_if_possible( &self, error: &mut traits::FulfillmentError<'tcx>, expr: &'tcx hir::Expr<'tcx>, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs index 78895689433..cb77d3f85d9 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs @@ -17,7 +17,7 @@ rustc_index::newtype_index! { } impl ExpectedIdx { - pub fn to_provided_idx(self) -> ProvidedIdx { + pub(crate) fn to_provided_idx(self) -> ProvidedIdx { ProvidedIdx::from_usize(self.as_usize()) } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 89e7227eda2..5333982c420 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -45,7 +45,7 @@ use crate::{ }; #[derive(Clone, Copy, Default)] -pub enum DivergingBlockBehavior { +pub(crate) enum DivergingBlockBehavior { /// This is the current stable behavior: /// /// ```rust @@ -406,9 +406,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) { let (sugg_span, replace, help) = if let Ok(snippet) = sess.source_map().span_to_snippet(span) { - (Some(span), format!("{snippet} as {cast_ty}"), None) + (Some(span), format!("{snippet} as {cast_ty}"), false) } else { - (None, "".to_string(), Some(())) + (None, "".to_string(), true) }; sess.dcx().emit_err(errors::PassToVariadicFunction { @@ -418,7 +418,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { help, replace, sugg_span, - teach: sess.teach(E0617).then_some(()), + teach: sess.teach(E0617), }); } @@ -1530,7 +1530,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Int(_) | ty::Uint(_) => Some(ty), ty::Char => Some(tcx.types.u8), ty::RawPtr(..) => Some(tcx.types.usize), - ty::FnDef(..) | ty::FnPtr(_) => Some(tcx.types.usize), + ty::FnDef(..) | ty::FnPtr(..) => Some(tcx.types.usize), _ => None, }); opt_ty.unwrap_or_else(|| self.next_int_var()) @@ -1556,7 +1556,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn check_struct_path( + pub(crate) fn check_struct_path( &self, qpath: &QPath<'tcx>, hir_id: HirId, @@ -1622,7 +1622,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn check_decl_initializer( + fn check_decl_initializer( &self, hir_id: HirId, pat: &'tcx hir::Pat<'tcx>, @@ -1700,7 +1700,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } /// Type check a `let` statement. - pub fn check_decl_local(&self, local: &'tcx hir::LetStmt<'tcx>) { + fn check_decl_local(&self, local: &'tcx hir::LetStmt<'tcx>) { self.check_decl(local.into()); if local.pat.is_never_pattern() { self.diverges.set(Diverges::Always { @@ -1710,7 +1710,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn check_stmt(&self, stmt: &'tcx hir::Stmt<'tcx>) { + fn check_stmt(&self, stmt: &'tcx hir::Stmt<'tcx>) { // Don't do all the complex logic below for `DeclItem`. match stmt.kind { hir::StmtKind::Item(..) => return, @@ -1745,7 +1745,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.diverges.set(self.diverges.get() | old_diverges); } - pub fn check_block_no_value(&self, blk: &'tcx hir::Block<'tcx>) { + pub(crate) fn check_block_no_value(&self, blk: &'tcx hir::Block<'tcx>) { let unit = self.tcx.types.unit; let ty = self.check_block_with_expected(blk, ExpectHasType(unit)); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 33f80dd3773..8e69a075030 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -117,7 +117,7 @@ pub(crate) struct FnCtxt<'a, 'tcx> { } impl<'a, 'tcx> FnCtxt<'a, 'tcx> { - pub fn new( + pub(crate) fn new( root_ctxt: &'a TypeckRootCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, body_id: LocalDefId, @@ -148,15 +148,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.root_ctxt.infcx.dcx() } - pub fn cause(&self, span: Span, code: ObligationCauseCode<'tcx>) -> ObligationCause<'tcx> { + pub(crate) fn cause( + &self, + span: Span, + code: ObligationCauseCode<'tcx>, + ) -> ObligationCause<'tcx> { ObligationCause::new(span, self.body_id, code) } - pub fn misc(&self, span: Span) -> ObligationCause<'tcx> { + pub(crate) fn misc(&self, span: Span) -> ObligationCause<'tcx> { self.cause(span, ObligationCauseCode::Misc) } - pub fn sess(&self) -> &Session { + pub(crate) fn sess(&self) -> &Session { self.tcx.sess } @@ -165,7 +169,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Use [`InferCtxtErrorExt::err_ctxt`] to start one without a `TypeckResults`. /// /// [`InferCtxtErrorExt::err_ctxt`]: rustc_trait_selection::error_reporting::InferCtxtErrorExt::err_ctxt - pub fn err_ctxt(&'a self) -> TypeErrCtxt<'a, 'tcx> { + pub(crate) fn err_ctxt(&'a self) -> TypeErrCtxt<'a, 'tcx> { let mut sub_relations = SubRelations::default(); sub_relations.add_constraints( self, @@ -365,7 +369,7 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> { /// This is a bridge between the interface of HIR ty lowering, which outputs a raw /// `Ty`, and the API in this module, which expect `Ty` to be fully normalized. #[derive(Clone, Copy, Debug)] -pub struct LoweredTy<'tcx> { +pub(crate) struct LoweredTy<'tcx> { /// The unnormalized type provided by the user. pub raw: Ty<'tcx>, @@ -374,7 +378,7 @@ pub struct LoweredTy<'tcx> { } impl<'tcx> LoweredTy<'tcx> { - pub fn from_raw(fcx: &FnCtxt<'_, 'tcx>, span: Span, raw: Ty<'tcx>) -> LoweredTy<'tcx> { + fn from_raw(fcx: &FnCtxt<'_, 'tcx>, span: Span, raw: Ty<'tcx>) -> LoweredTy<'tcx> { // FIXME(-Znext-solver): We're still figuring out how to best handle // normalization and this doesn't feel too great. We should look at this // code again before stabilizing it. diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 6b4edcd95d9..031aa6159d2 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -64,7 +64,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// - Points out the method's return type as the reason for the expected type. /// - Possible missing semicolon. /// - Possible missing return type if the return type is the default, and not `fn main()`. - pub fn suggest_mismatched_types_on_tail( + pub(crate) fn suggest_mismatched_types_on_tail( &self, err: &mut Diag<'_>, expr: &'tcx hir::Expr<'tcx>, @@ -177,7 +177,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.err_ctxt().extract_callable_info(self.body_id, self.param_env, ty) } - pub fn suggest_two_fn_call( + pub(crate) fn suggest_two_fn_call( &self, err: &mut Diag<'_>, lhs_expr: &'tcx hir::Expr<'tcx>, @@ -251,7 +251,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn suggest_remove_last_method_call( + pub(crate) fn suggest_remove_last_method_call( &self, err: &mut Diag<'_>, expr: &hir::Expr<'tcx>, @@ -280,7 +280,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false } - pub fn suggest_deref_ref_or_into( + pub(crate) fn suggest_deref_ref_or_into( &self, err: &mut Diag<'_>, expr: &hir::Expr<'tcx>, @@ -604,7 +604,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Ty<'tcx>, found: Ty<'tcx>, ) -> bool { - if let (ty::FnPtr(_), ty::Closure(def_id, _)) = (expected.kind(), found.kind()) { + if let (ty::FnPtr(..), ty::Closure(def_id, _)) = (expected.kind(), found.kind()) { if let Some(upvars) = self.tcx.upvars_mentioned(*def_id) { // Report upto four upvars being captured to reduce the amount error messages // reported back to the user. @@ -747,7 +747,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// /// If the expression is the expression of a closure without block (`|| expr`), a /// block is needed to be added too (`|| { expr; }`). This is denoted by `needs_block`. - pub fn suggest_missing_semicolon( + pub(crate) fn suggest_missing_semicolon( &self, err: &mut Diag<'_>, expression: &'tcx hir::Expr<'tcx>, @@ -2077,7 +2077,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If the expr is a while or for loop and is the tail expr of its // enclosing body suggest returning a value right after it - pub fn suggest_returning_value_after_loop( + pub(crate) fn suggest_returning_value_after_loop( &self, err: &mut Diag<'_>, expr: &hir::Expr<'tcx>, @@ -2975,7 +2975,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut suffix_suggestion = sugg.clone(); suffix_suggestion.push(( if matches!( - (&expected_ty.kind(), &checked_ty.kind()), + (expected_ty.kind(), checked_ty.kind()), (ty::Int(_) | ty::Uint(_), ty::Float(_)) ) { // Remove fractional part from literal, for example `42.0f32` into `42` @@ -3077,7 +3077,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.multipart_suggestion_verbose(msg, suggestion, Applicability::MachineApplicable); }; - match (&expected_ty.kind(), &checked_ty.kind()) { + match (expected_ty.kind(), checked_ty.kind()) { (ty::Int(exp), ty::Int(found)) => { let (f2e_is_fallible, e2f_is_fallible) = match (exp.bit_width(), found.bit_width()) { diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs index a9c929e76d5..62aa29e673d 100644 --- a/compiler/rustc_hir_typeck/src/intrinsicck.rs +++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs @@ -38,7 +38,7 @@ fn unpack_option_like<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { } impl<'a, 'tcx> FnCtxt<'a, 'tcx> { - pub fn check_transmute(&self, from: Ty<'tcx>, to: Ty<'tcx>, hir_id: HirId) { + pub(crate) fn check_transmute(&self, from: Ty<'tcx>, to: Ty<'tcx>, hir_id: HirId) { let tcx = self.tcx; let dl = &tcx.data_layout; let span = tcx.hir().span(hir_id); diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 758a1cefe63..8e6484f1e29 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -5,10 +5,10 @@ #![feature(box_patterns)] #![feature(control_flow_enum)] #![feature(if_let_guard)] -#![feature(is_none_or)] #![feature(let_chains)] #![feature(never_type)] #![feature(try_blocks)] +#![warn(unreachable_pub)] // tidy-alphabetical-end #[macro_use] @@ -88,14 +88,17 @@ fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &UnordSet(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> { +fn typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx ty::TypeckResults<'tcx> { let fallback = move || tcx.type_of(def_id.to_def_id()).instantiate_identity(); typeck_with_fallback(tcx, def_id, fallback, None) } /// Used only to get `TypeckResults` for type inference during error recovery. /// Currently only used for type inference of `static`s and `const`s to avoid type cycle errors. -fn diagnostic_only_typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> { +fn diagnostic_only_typeck<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, +) -> &'tcx ty::TypeckResults<'tcx> { let fallback = move || { let span = tcx.hir().span(tcx.local_def_id_to_hir_id(def_id)); Ty::new_error_with_message(tcx, span, "diagnostic only typeck table used") diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index e0c0adac076..2c3cfcf3cbd 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -42,13 +42,13 @@ impl<'a, 'tcx> Deref for ConfirmContext<'a, 'tcx> { } #[derive(Debug)] -pub struct ConfirmResult<'tcx> { +pub(crate) struct ConfirmResult<'tcx> { pub callee: MethodCallee<'tcx>, pub illegal_sized_bound: Option, } impl<'a, 'tcx> FnCtxt<'a, 'tcx> { - pub fn confirm_method( + pub(crate) fn confirm_method( &self, span: Span, self_expr: &'tcx hir::Expr<'tcx>, @@ -66,7 +66,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { confirm_cx.confirm(unadjusted_self_ty, pick, segment) } - pub fn confirm_method_for_diagnostic( + pub(crate) fn confirm_method_for_diagnostic( &self, span: Span, self_expr: &'tcx hir::Expr<'tcx>, diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index d6110ab94c1..39307a29dad 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -4,7 +4,7 @@ mod confirm; mod prelude_edition_lints; -pub mod probe; +pub(crate) mod probe; mod suggest; use rustc_errors::{Applicability, Diag, SubdiagMessage}; @@ -24,15 +24,15 @@ use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::{self, NormalizeExt}; use self::probe::{IsSuggestion, ProbeScope}; -pub use self::MethodError::*; +pub(crate) use self::MethodError::*; use crate::FnCtxt; -pub fn provide(providers: &mut Providers) { +pub(crate) fn provide(providers: &mut Providers) { probe::provide(providers); } #[derive(Clone, Copy, Debug)] -pub struct MethodCallee<'tcx> { +pub(crate) struct MethodCallee<'tcx> { /// Impl method ID, for inherent methods, or trait method ID, otherwise. pub def_id: DefId, pub args: GenericArgsRef<'tcx>, @@ -44,7 +44,7 @@ pub struct MethodCallee<'tcx> { } #[derive(Debug)] -pub enum MethodError<'tcx> { +pub(crate) enum MethodError<'tcx> { // Did not find an applicable method, but we did find various near-misses that may work. NoMatch(NoMatchData<'tcx>), @@ -70,7 +70,7 @@ pub enum MethodError<'tcx> { // Contains a list of static methods that may apply, a list of unsatisfied trait predicates which // could lead to matches if satisfied, and a list of not-in-scope traits which may work. #[derive(Debug)] -pub struct NoMatchData<'tcx> { +pub(crate) struct NoMatchData<'tcx> { pub static_candidates: Vec, pub unsatisfied_predicates: Vec<(ty::Predicate<'tcx>, Option>, Option>)>, @@ -82,7 +82,7 @@ pub struct NoMatchData<'tcx> { // A pared down enum describing just the places from which a method // candidate can arise. Used for error reporting only. #[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub enum CandidateSource { +pub(crate) enum CandidateSource { Impl(DefId), Trait(DefId /* trait id */), } @@ -254,7 +254,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ok(result.callee) } - pub fn lookup_method_for_diagnostic( + pub(crate) fn lookup_method_for_diagnostic( &self, self_ty: Ty<'tcx>, segment: &hir::PathSegment<'tcx>, @@ -296,7 +296,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ok(pick) } - pub fn lookup_probe_for_diagnostic( + pub(crate) fn lookup_probe_for_diagnostic( &self, method_name: Ident, self_ty: Ty<'tcx>, @@ -569,7 +569,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Finds item with name `item_name` defined in impl/trait `def_id` /// and return it, or `None`, if no such item was defined there. - pub fn associated_value(&self, def_id: DefId, item_name: Ident) -> Option { + fn associated_value(&self, def_id: DefId, item_name: Ident) -> Option { self.tcx .associated_items(def_id) .find_by_name_and_namespace(self.tcx, item_name, Namespace::ValueNS, def_id) diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 28f537c87c4..48e33c81b85 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -38,14 +38,14 @@ use rustc_trait_selection::traits::{self, ObligationCause, ObligationCtxt}; use smallvec::{smallvec, SmallVec}; use self::CandidateKind::*; -pub use self::PickKind::*; +pub(crate) use self::PickKind::*; use super::{suggest, CandidateSource, MethodError, NoMatchData}; use crate::FnCtxt; /// Boolean flag used to indicate if this search is for a suggestion /// or not. If true, we can allow ambiguity and so forth. #[derive(Clone, Copy, Debug)] -pub struct IsSuggestion(pub bool); +pub(crate) struct IsSuggestion(pub bool); pub(crate) struct ProbeContext<'a, 'tcx> { fcx: &'a FnCtxt<'a, 'tcx>, @@ -134,7 +134,7 @@ enum ProbeResult { /// (at most) one of these. Either the receiver has type `T` and we convert it to `&T` (or with /// `mut`), or it has type `*mut T` and we convert it to `*const T`. #[derive(Debug, PartialEq, Copy, Clone)] -pub enum AutorefOrPtrAdjustment { +pub(crate) enum AutorefOrPtrAdjustment { /// Receiver has type `T`, add `&` or `&mut` (it `T` is `mut`), and maybe also "unsize" it. /// Unsizing is used to convert a `[T; N]` to `[T]`, which only makes sense when autorefing. Autoref { @@ -158,7 +158,7 @@ impl AutorefOrPtrAdjustment { } #[derive(Debug, Clone)] -pub struct Pick<'tcx> { +pub(crate) struct Pick<'tcx> { pub item: ty::AssocItem, pub kind: PickKind<'tcx>, pub import_ids: SmallVec<[LocalDefId; 1]>, @@ -179,7 +179,7 @@ pub struct Pick<'tcx> { } #[derive(Clone, Debug, PartialEq, Eq)] -pub enum PickKind<'tcx> { +pub(crate) enum PickKind<'tcx> { InherentImplPick, ObjectPick, TraitPick, @@ -189,10 +189,10 @@ pub enum PickKind<'tcx> { ), } -pub type PickResult<'tcx> = Result, MethodError<'tcx>>; +pub(crate) type PickResult<'tcx> = Result, MethodError<'tcx>>; #[derive(PartialEq, Eq, Copy, Clone, Debug)] -pub enum Mode { +pub(crate) enum Mode { // An expression of the form `receiver.method_name(...)`. // Autoderefs are performed on `receiver`, lookup is done based on the // `self` argument of the method, and static methods aren't considered. @@ -204,7 +204,7 @@ pub enum Mode { } #[derive(PartialEq, Eq, Copy, Clone, Debug)] -pub enum ProbeScope { +pub(crate) enum ProbeScope { // Single candidate coming from pre-resolved delegation method. Single(DefId), @@ -507,7 +507,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } -pub fn provide(providers: &mut Providers) { +pub(crate) fn provide(providers: &mut Providers) { providers.method_autoderef_steps = method_autoderef_steps; } @@ -1288,7 +1288,7 @@ impl<'tcx> Pick<'tcx> { /// Checks whether two picks do not refer to the same trait item for the same `Self` type. /// Only useful for comparisons of picks in order to improve diagnostics. /// Do not use for type checking. - pub fn differs_from(&self, other: &Self) -> bool { + pub(crate) fn differs_from(&self, other: &Self) -> bool { let Self { item: AssocItem { @@ -1312,7 +1312,7 @@ impl<'tcx> Pick<'tcx> { } /// In case there were unstable name collisions, emit them as a lint. - pub fn maybe_emit_unstable_name_collision_hint( + pub(crate) fn maybe_emit_unstable_name_collision_hint( &self, tcx: TyCtxt<'tcx>, span: Span, diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 61287d98676..b78bb8cb98d 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -50,7 +50,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Not all of these (e.g., unsafe fns) implement `FnOnce`, // so we look for these beforehand. // FIXME(async_closures): These don't impl `FnOnce` by default. - ty::Closure(..) | ty::FnDef(..) | ty::FnPtr(_) => true, + ty::Closure(..) | ty::FnDef(..) | ty::FnPtr(..) => true, // If it's not a simple function, look for things which implement `FnOnce`. _ => { let Some(fn_once) = tcx.lang_items().fn_once_trait() else { @@ -415,7 +415,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err } - pub fn suggest_use_shadowed_binding_with_method( + fn suggest_use_shadowed_binding_with_method( &self, self_source: SelfSource<'tcx>, method_name: Ident, @@ -527,7 +527,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { if self.check_and_add_sugg_binding(LetStmt { ty_hir_id_opt: if let Some(ty) = ty { Some(ty.hir_id) } else { None }, - binding_id: binding_id, + binding_id, span: pat.span, init_hir_id: init.hir_id, }) { @@ -1012,7 +1012,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| { let msg = format!("`{}`", if obligation.len() > 50 { quiet } else { obligation }); - match &self_ty.kind() { + match self_ty.kind() { // Point at the type that couldn't satisfy the bound. ty::Adt(def, _) => { bound_spans.get_mut_or_insert_default(tcx.def_span(def.did())).push(msg) @@ -3448,6 +3448,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { trait_missing_method: bool, ) { let mut alt_rcvr_sugg = false; + let mut trait_in_other_version_found = false; if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) { debug!( "suggest_traits_to_import: span={:?}, item_name={:?}, rcvr_ty={:?}, rcvr={:?}", @@ -3489,8 +3490,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // self types and rely on the suggestion to `use` the trait from // `suggest_valid_traits`. let did = Some(pick.item.container_id(self.tcx)); - let skip = skippable.contains(&did); - if pick.autoderefs == 0 && !skip { + if skippable.contains(&did) { + continue; + } + trait_in_other_version_found = self + .detect_and_explain_multiple_crate_versions( + err, + pick.item.def_id, + rcvr.hir_id, + Some(*rcvr_ty), + ); + if pick.autoderefs == 0 && !trait_in_other_version_found { err.span_label( pick.item.ident(self.tcx).span, format!("the method is available for `{rcvr_ty}` here"), @@ -3675,7 +3685,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - if self.suggest_valid_traits(err, item_name, valid_out_of_scope_traits, true) { + + if let SelfSource::QPath(ty) = source + && !valid_out_of_scope_traits.is_empty() + && let hir::TyKind::Path(path) = ty.kind + && let hir::QPath::Resolved(..) = path + && let Some(assoc) = self + .tcx + .associated_items(valid_out_of_scope_traits[0]) + .filter_by_name_unhygienic(item_name.name) + .next() + { + // See if the `Type::function(val)` where `function` wasn't found corresponds to a + // `Trait` that is imported directly, but `Type` came from a different version of the + // same crate. + + let rcvr_ty = self.node_ty_opt(ty.hir_id); + trait_in_other_version_found = self.detect_and_explain_multiple_crate_versions( + err, + assoc.def_id, + ty.hir_id, + rcvr_ty, + ); + } + if !trait_in_other_version_found + && self.suggest_valid_traits(err, item_name, valid_out_of_scope_traits, true) + { return; } @@ -4040,6 +4075,64 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + fn detect_and_explain_multiple_crate_versions( + &self, + err: &mut Diag<'_>, + item_def_id: DefId, + hir_id: hir::HirId, + rcvr_ty: Option>, + ) -> bool { + let hir_id = self.tcx.parent_hir_id(hir_id); + let Some(traits) = self.tcx.in_scope_traits(hir_id) else { return false }; + if traits.is_empty() { + return false; + } + let trait_def_id = self.tcx.parent(item_def_id); + let krate = self.tcx.crate_name(trait_def_id.krate); + let name = self.tcx.item_name(trait_def_id); + let candidates: Vec<_> = traits + .iter() + .filter(|c| { + c.def_id.krate != trait_def_id.krate + && self.tcx.crate_name(c.def_id.krate) == krate + && self.tcx.item_name(c.def_id) == name + }) + .map(|c| (c.def_id, c.import_ids.get(0).cloned())) + .collect(); + if candidates.is_empty() { + return false; + } + let item_span = self.tcx.def_span(item_def_id); + let msg = format!( + "there are multiple different versions of crate `{krate}` in the dependency graph", + ); + let trait_span = self.tcx.def_span(trait_def_id); + let mut multi_span: MultiSpan = trait_span.into(); + multi_span.push_span_label(trait_span, format!("this is the trait that is needed")); + let descr = self.tcx.associated_item(item_def_id).descr(); + let rcvr_ty = + rcvr_ty.map(|t| format!("`{t}`")).unwrap_or_else(|| "the receiver".to_string()); + multi_span + .push_span_label(item_span, format!("the {descr} is available for {rcvr_ty} here")); + for (def_id, import_def_id) in candidates { + if let Some(import_def_id) = import_def_id { + multi_span.push_span_label( + self.tcx.def_span(import_def_id), + format!( + "`{name}` imported here doesn't correspond to the right version of crate \ + `{krate}`", + ), + ); + } + multi_span.push_span_label( + self.tcx.def_span(def_id), + format!("this is the trait that was imported"), + ); + } + err.span_note(multi_span, msg); + true + } + /// issue #102320, for `unwrap_or` with closure as argument, suggest `unwrap_or_else` /// FIXME: currently not working for suggesting `map_or_else`, see #102408 pub(crate) fn suggest_else_fn_with_closure( @@ -4130,19 +4223,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } #[derive(Copy, Clone, Debug)] -pub enum SelfSource<'a> { +enum SelfSource<'a> { QPath(&'a hir::Ty<'a>), MethodCall(&'a hir::Expr<'a> /* rcvr */), } #[derive(Copy, Clone, PartialEq, Eq)] -pub struct TraitInfo { +pub(crate) struct TraitInfo { pub def_id: DefId, } /// Retrieves all traits in this crate and any dependent crates, /// and wraps them into `TraitInfo` for custom sorting. -pub fn all_traits(tcx: TyCtxt<'_>) -> Vec { +pub(crate) fn all_traits(tcx: TyCtxt<'_>) -> Vec { tcx.all_traits().map(|def_id| TraitInfo { def_id }).collect() } diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index c54f6cfd099..fb0d30d5b0e 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -25,7 +25,7 @@ use crate::Expectation; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Checks a `a = b` - pub fn check_binop_assign( + pub(crate) fn check_binop_assign( &self, expr: &'tcx hir::Expr<'tcx>, op: hir::BinOp, @@ -84,7 +84,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } /// Checks a potentially overloaded binary operator. - pub fn check_binop( + pub(crate) fn check_binop( &self, expr: &'tcx hir::Expr<'tcx>, op: hir::BinOp, @@ -770,7 +770,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn check_user_unop( + pub(crate) fn check_user_unop( &self, ex: &'tcx hir::Expr<'tcx>, operand_ty: Ty<'tcx>, diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index c4f74adb420..206de455cd5 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -944,7 +944,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn check_dereferenceable( + fn check_dereferenceable( &self, span: Span, expected: Ty<'tcx>, @@ -1336,7 +1336,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // More generally, the expected type wants a tuple variant with one field of an // N-arity-tuple, e.g., `V_i((p_0, .., p_N))`. Meanwhile, the user supplied a pattern // with the subpatterns directly in the tuple variant pattern, e.g., `V_i(p_0, .., p_N)`. - let missing_parentheses = match (&expected.kind(), fields, had_err) { + let missing_parentheses = match (expected.kind(), fields, had_err) { // #67037: only do this if we could successfully type-check the expected type against // the tuple struct pattern. Otherwise the args could get out of range on e.g., // `let P() = U;` where `P != U` with `struct P(T);`. diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs index ad04b6b8b1d..bb227272584 100644 --- a/compiler/rustc_hir_typeck/src/place_op.rs +++ b/compiler/rustc_hir_typeck/src/place_op.rs @@ -246,7 +246,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// always know whether a place needs to be mutable or not in the first pass. /// This happens whether there is an implicit mutable reborrow, e.g. when the type /// is used as the receiver of a method call. - pub fn convert_place_derefs_to_mutable(&self, expr: &hir::Expr<'_>) { + pub(crate) fn convert_place_derefs_to_mutable(&self, expr: &hir::Expr<'_>) { // Gather up expressions we want to munge. let mut exprs = vec![expr]; diff --git a/compiler/rustc_hir_typeck/src/rvalue_scopes.rs b/compiler/rustc_hir_typeck/src/rvalue_scopes.rs index f22a13d292e..fb0fe23be65 100644 --- a/compiler/rustc_hir_typeck/src/rvalue_scopes.rs +++ b/compiler/rustc_hir_typeck/src/rvalue_scopes.rs @@ -65,7 +65,7 @@ fn record_rvalue_scope( } } -pub fn resolve_rvalue_scopes<'a, 'tcx>( +pub(crate) fn resolve_rvalue_scopes<'a, 'tcx>( fcx: &'a FnCtxt<'a, 'tcx>, scope_tree: &'a ScopeTree, def_id: DefId, diff --git a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs index a43164589b5..e6b8da3e5d6 100644 --- a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs +++ b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs @@ -77,7 +77,7 @@ impl<'tcx> Deref for TypeckRootCtxt<'tcx> { } impl<'tcx> TypeckRootCtxt<'tcx> { - pub fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { + pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { let hir_owner = tcx.local_def_id_to_hir_id(def_id).owner; let infcx = tcx.infer_ctxt().ignoring_regions().with_opaque_type_inference(def_id).build(); @@ -124,7 +124,7 @@ impl<'tcx> TypeckRootCtxt<'tcx> { infer_ok.value } - pub fn update_infer_var_info(&self, obligation: &PredicateObligation<'tcx>) { + fn update_infer_var_info(&self, obligation: &PredicateObligation<'tcx>) { let infer_var_info = &mut self.infer_var_info.borrow_mut(); // (*) binder skipped diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 55f002291f0..5350affb3bc 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -74,7 +74,7 @@ enum PlaceAncestryRelation { type InferredCaptureInformation<'tcx> = Vec<(Place<'tcx>, ty::CaptureInfo)>; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { - pub fn closure_analyze(&self, body: &'tcx hir::Body<'tcx>) { + pub(crate) fn closure_analyze(&self, body: &'tcx hir::Body<'tcx>) { InferBorrowKindVisitor { fcx: self }.visit_body(body); // it's our job to process these. diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 0327a3097ec..0853ed9b05b 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -35,7 +35,7 @@ use crate::FnCtxt; // resolve_type_vars_in_body, which creates a new TypeTables which // doesn't contain any inference types. impl<'a, 'tcx> FnCtxt<'a, 'tcx> { - pub fn resolve_type_vars_in_body( + pub(crate) fn resolve_type_vars_in_body( &self, body: &'tcx hir::Body<'tcx>, ) -> &'tcx ty::TypeckResults<'tcx> { diff --git a/compiler/rustc_incremental/messages.ftl b/compiler/rustc_incremental/messages.ftl index de2177ebb6e..2a65101d360 100644 --- a/compiler/rustc_incremental/messages.ftl +++ b/compiler/rustc_incremental/messages.ftl @@ -99,6 +99,4 @@ incremental_unrecognized_depnode = unrecognized `DepNode` variant: {$name} incremental_unrecognized_depnode_label = dep-node label `{$label}` not recognized -incremental_write_dep_graph = failed to write dependency graph to `{$path}`: {$err} - incremental_write_new = failed to write {$name} to `{$path}`: {$err} diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs index b29ba59c9f3..46f30526d2a 100644 --- a/compiler/rustc_incremental/src/assert_dep_graph.rs +++ b/compiler/rustc_incremental/src/assert_dep_graph.rs @@ -55,7 +55,7 @@ use {rustc_ast as ast, rustc_graphviz as dot, rustc_hir as hir}; use crate::errors; #[allow(missing_docs)] -pub fn assert_dep_graph(tcx: TyCtxt<'_>) { +pub(crate) fn assert_dep_graph(tcx: TyCtxt<'_>) { tcx.dep_graph.with_ignore(|| { if tcx.sess.opts.unstable_opts.dump_dep_graph { tcx.dep_graph.with_query(dump_graph); @@ -261,7 +261,7 @@ fn dump_graph(query: &DepGraphQuery) { } #[allow(missing_docs)] -pub struct GraphvizDepGraph(FxIndexSet, Vec<(DepKind, DepKind)>); +struct GraphvizDepGraph(FxIndexSet, Vec<(DepKind, DepKind)>); impl<'a> dot::GraphWalk<'a> for GraphvizDepGraph { type Node = DepKind; diff --git a/compiler/rustc_incremental/src/errors.rs b/compiler/rustc_incremental/src/errors.rs index f8910030634..cb21f975878 100644 --- a/compiler/rustc_incremental/src/errors.rs +++ b/compiler/rustc_incremental/src/errors.rs @@ -6,7 +6,7 @@ use rustc_span::{Span, Symbol}; #[derive(Diagnostic)] #[diag(incremental_unrecognized_depnode)] -pub struct UnrecognizedDepNode { +pub(crate) struct UnrecognizedDepNode { #[primary_span] pub span: Span, pub name: Symbol, @@ -14,28 +14,28 @@ pub struct UnrecognizedDepNode { #[derive(Diagnostic)] #[diag(incremental_missing_depnode)] -pub struct MissingDepNode { +pub(crate) struct MissingDepNode { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(incremental_missing_if_this_changed)] -pub struct MissingIfThisChanged { +pub(crate) struct MissingIfThisChanged { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(incremental_ok)] -pub struct Ok { +pub(crate) struct Ok { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(incremental_no_path)] -pub struct NoPath { +pub(crate) struct NoPath { #[primary_span] pub span: Span, pub target: Symbol, @@ -44,7 +44,7 @@ pub struct NoPath { #[derive(Diagnostic)] #[diag(incremental_assertion_auto)] -pub struct AssertionAuto<'a> { +pub(crate) struct AssertionAuto<'a> { #[primary_span] pub span: Span, pub name: &'a str, @@ -53,7 +53,7 @@ pub struct AssertionAuto<'a> { #[derive(Diagnostic)] #[diag(incremental_undefined_clean_dirty_assertions_item)] -pub struct UndefinedCleanDirtyItem { +pub(crate) struct UndefinedCleanDirtyItem { #[primary_span] pub span: Span, pub kind: String, @@ -61,7 +61,7 @@ pub struct UndefinedCleanDirtyItem { #[derive(Diagnostic)] #[diag(incremental_undefined_clean_dirty_assertions)] -pub struct UndefinedCleanDirty { +pub(crate) struct UndefinedCleanDirty { #[primary_span] pub span: Span, pub kind: String, @@ -69,7 +69,7 @@ pub struct UndefinedCleanDirty { #[derive(Diagnostic)] #[diag(incremental_repeated_depnode_label)] -pub struct RepeatedDepNodeLabel<'a> { +pub(crate) struct RepeatedDepNodeLabel<'a> { #[primary_span] pub span: Span, pub label: &'a str, @@ -77,7 +77,7 @@ pub struct RepeatedDepNodeLabel<'a> { #[derive(Diagnostic)] #[diag(incremental_unrecognized_depnode_label)] -pub struct UnrecognizedDepNodeLabel<'a> { +pub(crate) struct UnrecognizedDepNodeLabel<'a> { #[primary_span] pub span: Span, pub label: &'a str, @@ -85,7 +85,7 @@ pub struct UnrecognizedDepNodeLabel<'a> { #[derive(Diagnostic)] #[diag(incremental_not_dirty)] -pub struct NotDirty<'a> { +pub(crate) struct NotDirty<'a> { #[primary_span] pub span: Span, pub dep_node_str: &'a str, @@ -93,7 +93,7 @@ pub struct NotDirty<'a> { #[derive(Diagnostic)] #[diag(incremental_not_clean)] -pub struct NotClean<'a> { +pub(crate) struct NotClean<'a> { #[primary_span] pub span: Span, pub dep_node_str: &'a str, @@ -101,7 +101,7 @@ pub struct NotClean<'a> { #[derive(Diagnostic)] #[diag(incremental_not_loaded)] -pub struct NotLoaded<'a> { +pub(crate) struct NotLoaded<'a> { #[primary_span] pub span: Span, pub dep_node_str: &'a str, @@ -109,7 +109,7 @@ pub struct NotLoaded<'a> { #[derive(Diagnostic)] #[diag(incremental_unknown_item)] -pub struct UnknownItem { +pub(crate) struct UnknownItem { #[primary_span] pub span: Span, pub name: Symbol, @@ -117,14 +117,14 @@ pub struct UnknownItem { #[derive(Diagnostic)] #[diag(incremental_no_cfg)] -pub struct NoCfg { +pub(crate) struct NoCfg { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(incremental_associated_value_expected_for)] -pub struct AssociatedValueExpectedFor { +pub(crate) struct AssociatedValueExpectedFor { #[primary_span] pub span: Span, pub ident: Ident, @@ -132,21 +132,21 @@ pub struct AssociatedValueExpectedFor { #[derive(Diagnostic)] #[diag(incremental_associated_value_expected)] -pub struct AssociatedValueExpected { +pub(crate) struct AssociatedValueExpected { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(incremental_unchecked_clean)] -pub struct UncheckedClean { +pub(crate) struct UncheckedClean { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(incremental_delete_old)] -pub struct DeleteOld<'a> { +pub(crate) struct DeleteOld<'a> { pub name: &'a str, pub path: PathBuf, pub err: std::io::Error, @@ -154,7 +154,7 @@ pub struct DeleteOld<'a> { #[derive(Diagnostic)] #[diag(incremental_create_new)] -pub struct CreateNew<'a> { +pub(crate) struct CreateNew<'a> { pub name: &'a str, pub path: PathBuf, pub err: std::io::Error, @@ -162,7 +162,7 @@ pub struct CreateNew<'a> { #[derive(Diagnostic)] #[diag(incremental_write_new)] -pub struct WriteNew<'a> { +pub(crate) struct WriteNew<'a> { pub name: &'a str, pub path: PathBuf, pub err: std::io::Error, @@ -170,14 +170,14 @@ pub struct WriteNew<'a> { #[derive(Diagnostic)] #[diag(incremental_canonicalize_path)] -pub struct CanonicalizePath { +pub(crate) struct CanonicalizePath { pub path: PathBuf, pub err: std::io::Error, } #[derive(Diagnostic)] #[diag(incremental_create_incr_comp_dir)] -pub struct CreateIncrCompDir<'a> { +pub(crate) struct CreateIncrCompDir<'a> { pub tag: &'a str, pub path: &'a Path, pub err: std::io::Error, @@ -185,103 +185,96 @@ pub struct CreateIncrCompDir<'a> { #[derive(Diagnostic)] #[diag(incremental_create_lock)] -pub struct CreateLock<'a> { +pub(crate) struct CreateLock<'a> { pub lock_err: std::io::Error, pub session_dir: &'a Path, #[note(incremental_lock_unsupported)] - pub is_unsupported_lock: Option<()>, + pub is_unsupported_lock: bool, #[help(incremental_cargo_help_1)] #[help(incremental_cargo_help_2)] - pub is_cargo: Option<()>, + pub is_cargo: bool, } #[derive(Diagnostic)] #[diag(incremental_delete_lock)] -pub struct DeleteLock<'a> { +pub(crate) struct DeleteLock<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] #[diag(incremental_hard_link_failed)] -pub struct HardLinkFailed<'a> { +pub(crate) struct HardLinkFailed<'a> { pub path: &'a Path, } #[derive(Diagnostic)] #[diag(incremental_delete_partial)] -pub struct DeletePartial<'a> { +pub(crate) struct DeletePartial<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] #[diag(incremental_delete_full)] -pub struct DeleteFull<'a> { +pub(crate) struct DeleteFull<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] #[diag(incremental_finalize)] -pub struct Finalize<'a> { +pub(crate) struct Finalize<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] #[diag(incremental_invalid_gc_failed)] -pub struct InvalidGcFailed<'a> { +pub(crate) struct InvalidGcFailed<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] #[diag(incremental_finalized_gc_failed)] -pub struct FinalizedGcFailed<'a> { +pub(crate) struct FinalizedGcFailed<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] #[diag(incremental_session_gc_failed)] -pub struct SessionGcFailed<'a> { +pub(crate) struct SessionGcFailed<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] #[diag(incremental_assert_not_loaded)] -pub struct AssertNotLoaded; +pub(crate) struct AssertNotLoaded; #[derive(Diagnostic)] #[diag(incremental_assert_loaded)] -pub struct AssertLoaded; +pub(crate) struct AssertLoaded; #[derive(Diagnostic)] #[diag(incremental_delete_incompatible)] -pub struct DeleteIncompatible { +pub(crate) struct DeleteIncompatible { pub path: PathBuf, pub err: std::io::Error, } #[derive(Diagnostic)] #[diag(incremental_load_dep_graph)] -pub struct LoadDepGraph { +pub(crate) struct LoadDepGraph { pub path: PathBuf, pub err: std::io::Error, } -#[derive(Diagnostic)] -#[diag(incremental_write_dep_graph)] -pub struct WriteDepGraph<'a> { - pub path: &'a Path, - pub err: std::io::Error, -} - #[derive(Diagnostic)] #[diag(incremental_move_dep_graph)] -pub struct MoveDepGraph<'a> { +pub(crate) struct MoveDepGraph<'a> { pub from: &'a Path, pub to: &'a Path, pub err: std::io::Error, @@ -289,14 +282,14 @@ pub struct MoveDepGraph<'a> { #[derive(Diagnostic)] #[diag(incremental_create_dep_graph)] -pub struct CreateDepGraph<'a> { +pub(crate) struct CreateDepGraph<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] #[diag(incremental_copy_workproduct_to_cache)] -pub struct CopyWorkProductToCache<'a> { +pub(crate) struct CopyWorkProductToCache<'a> { pub from: &'a Path, pub to: &'a Path, pub err: std::io::Error, @@ -304,13 +297,13 @@ pub struct CopyWorkProductToCache<'a> { #[derive(Diagnostic)] #[diag(incremental_delete_workproduct)] -pub struct DeleteWorkProduct<'a> { +pub(crate) struct DeleteWorkProduct<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] #[diag(incremental_corrupt_file)] -pub struct CorruptFile<'a> { +pub(crate) struct CorruptFile<'a> { pub path: &'a Path, } diff --git a/compiler/rustc_incremental/src/lib.rs b/compiler/rustc_incremental/src/lib.rs index fcdcb08eed6..c79d108183c 100644 --- a/compiler/rustc_incremental/src/lib.rs +++ b/compiler/rustc_incremental/src/lib.rs @@ -6,6 +6,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end mod assert_dep_graph; diff --git a/compiler/rustc_incremental/src/persist/data.rs b/compiler/rustc_incremental/src/persist/data.rs index 81e5410978d..d962dc866f4 100644 --- a/compiler/rustc_incremental/src/persist/data.rs +++ b/compiler/rustc_incremental/src/persist/data.rs @@ -4,7 +4,7 @@ use rustc_macros::{Decodable, Encodable}; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; #[derive(Debug, Encodable, Decodable)] -pub struct SerializedWorkProduct { +pub(crate) struct SerializedWorkProduct { /// node that produced the work-product pub id: WorkProductId, diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs index 1e02324f404..88cb82f0f37 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs @@ -133,7 +133,7 @@ struct Assertion { loaded_from_disk: Labels, } -pub fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) { +pub(crate) fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) { if !tcx.sess.opts.unstable_opts.query_dep_graph { return; } @@ -174,7 +174,7 @@ pub fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) { }) } -pub struct DirtyCleanVisitor<'tcx> { +struct DirtyCleanVisitor<'tcx> { tcx: TyCtxt<'tcx>, checked_attrs: FxHashSet, } @@ -429,7 +429,7 @@ fn expect_associated_value(tcx: TyCtxt<'_>, item: &NestedMetaItem) -> Symbol { /// A visitor that collects all `#[rustc_clean]` attributes from /// the HIR. It is used to verify that we really ran checks for all annotated /// nodes. -pub struct FindAllAttrs<'tcx> { +struct FindAllAttrs<'tcx> { tcx: TyCtxt<'tcx>, found_attrs: Vec<&'tcx Attribute>, } diff --git a/compiler/rustc_incremental/src/persist/file_format.rs b/compiler/rustc_incremental/src/persist/file_format.rs index 174414d0c85..f834c48cbf8 100644 --- a/compiler/rustc_incremental/src/persist/file_format.rs +++ b/compiler/rustc_incremental/src/persist/file_format.rs @@ -89,7 +89,7 @@ where /// incompatible version of the compiler. /// - Returns `Err(..)` if some kind of IO error occurred while reading the /// file. -pub fn read_file( +pub(crate) fn read_file( path: &Path, report_incremental_info: bool, is_nightly_build: bool, diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index 5f85e622e89..feb25a9a89d 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -157,7 +157,7 @@ pub(crate) fn work_products_path(sess: &Session) -> PathBuf { } /// Returns the path to a session's query cache. -pub fn query_cache_path(sess: &Session) -> PathBuf { +pub(crate) fn query_cache_path(sess: &Session) -> PathBuf { in_incr_comp_dir_sess(sess, QUERY_CACHE_FILENAME) } @@ -486,12 +486,12 @@ fn lock_directory( // the lock should be exclusive Ok(lock) => Ok((lock, lock_file_path)), Err(lock_err) => { - let is_unsupported_lock = flock::Lock::error_unsupported(&lock_err).then_some(()); + let is_unsupported_lock = flock::Lock::error_unsupported(&lock_err); Err(sess.dcx().emit_err(errors::CreateLock { lock_err, session_dir, is_unsupported_lock, - is_cargo: rustc_session::utils::was_invoked_from_cargo().then_some(()), + is_cargo: rustc_session::utils::was_invoked_from_cargo(), })) } } @@ -851,7 +851,7 @@ fn delete_old(sess: &Session, path: &Path) { debug!("garbage_collect_session_directories() - deleting `{}`", path.display()); if let Err(err) = safe_remove_dir_all(path) { - sess.dcx().emit_warn(errors::SessionGcFailed { path: path, err }); + sess.dcx().emit_warn(errors::SessionGcFailed { path, err }); } else { delete_session_dir_lock_file(sess, &lock_file_path(path)); } diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs index b5e4f02a8d1..f773b5b46ad 100644 --- a/compiler/rustc_index/src/lib.rs +++ b/compiler/rustc_index/src/lib.rs @@ -1,7 +1,9 @@ // tidy-alphabetical-start #![cfg_attr(all(feature = "nightly", test), feature(stmt_expr_attributes))] #![cfg_attr(feature = "nightly", allow(internal_features))] -#![cfg_attr(feature = "nightly", feature(extend_one, new_uninit, step_trait, test))] +#![cfg_attr(feature = "nightly", feature(extend_one, step_trait, test))] +#![cfg_attr(feature = "nightly", feature(new_zeroed_alloc))] +#![warn(unreachable_pub)] // tidy-alphabetical-end pub mod bit_set; diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs index 7438c97eb58..1cb8bc861af 100644 --- a/compiler/rustc_index/src/vec.rs +++ b/compiler/rustc_index/src/vec.rs @@ -188,6 +188,11 @@ impl IndexVec { let min_new_len = elem.index() + 1; self.raw.resize_with(min_new_len, fill_value); } + + #[inline] + pub fn append(&mut self, other: &mut Self) { + self.raw.append(&mut other.raw); + } } /// `IndexVec` is often used as a map, so it provides some map-like APIs. diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index 1a5c0137219..76ea9c3433d 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -3,7 +3,7 @@ use rustc_span::Span; #[derive(Diagnostic)] #[diag(infer_opaque_hidden_type)] -pub struct OpaqueHiddenTypeDiag { +pub(crate) struct OpaqueHiddenTypeDiag { #[primary_span] #[label] pub span: Span, diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 3bcb92d8029..db5139172b0 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -438,7 +438,7 @@ impl<'cx, 'tcx> TypeFolder> for Canonicalizer<'cx, 'tcx> { | ty::RawPtr(..) | ty::Ref(..) | ty::FnDef(..) - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::Dynamic(..) | ty::Never | ty::Tuple(..) diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index f35a8162d96..95888beb6b1 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -167,7 +167,7 @@ impl<'tcx> InferCtxtLike for InferCtxt<'tcx> { } fn sub_regions(&self, sub: ty::Region<'tcx>, sup: ty::Region<'tcx>) { - self.sub_regions(SubregionOrigin::RelateRegionParamBound(DUMMY_SP), sub, sup) + self.sub_regions(SubregionOrigin::RelateRegionParamBound(DUMMY_SP, None), sub, sup) } fn register_ty_outlives(&self, ty: Ty<'tcx>, r: ty::Region<'tcx>) { diff --git a/compiler/rustc_infer/src/infer/free_regions.rs b/compiler/rustc_infer/src/infer/free_regions.rs index 0dde3082d48..9a5674369da 100644 --- a/compiler/rustc_infer/src/infer/free_regions.rs +++ b/compiler/rustc_infer/src/infer/free_regions.rs @@ -18,11 +18,11 @@ pub(crate) struct RegionRelations<'a, 'tcx> { } impl<'a, 'tcx> RegionRelations<'a, 'tcx> { - pub fn new(tcx: TyCtxt<'tcx>, free_regions: &'a FreeRegionMap<'tcx>) -> Self { + pub(crate) fn new(tcx: TyCtxt<'tcx>, free_regions: &'a FreeRegionMap<'tcx>) -> Self { Self { tcx, free_regions } } - pub fn lub_param_regions(&self, r_a: Region<'tcx>, r_b: Region<'tcx>) -> Region<'tcx> { + pub(crate) fn lub_param_regions(&self, r_a: Region<'tcx>, r_b: Region<'tcx>) -> Region<'tcx> { self.free_regions.lub_param_regions(self.tcx, r_a, r_b) } } @@ -80,7 +80,7 @@ impl<'tcx> FreeRegionMap<'tcx> { /// cases, this is more conservative than necessary, in order to /// avoid making arbitrary choices. See /// `TransitiveRelation::postdom_upper_bound` for more details. - pub fn lub_param_regions( + pub(crate) fn lub_param_regions( &self, tcx: TyCtxt<'tcx>, r_a: Region<'tcx>, diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs index c2c0c7a41fe..e5533213400 100644 --- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs +++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs @@ -43,7 +43,7 @@ pub(crate) fn resolve<'tcx>( /// Contains the result of lexical region resolution. Offers methods /// to lookup up the final value of a region variable. #[derive(Clone)] -pub struct LexicalRegionResolutions<'tcx> { +pub(crate) struct LexicalRegionResolutions<'tcx> { pub(crate) values: IndexVec>, } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index f2fc25a2d2e..5aa7f259685 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -390,7 +390,7 @@ pub enum SubregionOrigin<'tcx> { /// The given region parameter was instantiated with a region /// that must outlive some other region. - RelateRegionParamBound(Span), + RelateRegionParamBound(Span, Option>), /// Creating a pointer `b` to contents of another reference. Reborrow(Span), @@ -859,7 +859,7 @@ impl<'tcx> InferCtxt<'tcx> { ) { self.enter_forall(predicate, |ty::OutlivesPredicate(r_a, r_b)| { let origin = SubregionOrigin::from_obligation_cause(cause, || { - RelateRegionParamBound(cause.span) + RelateRegionParamBound(cause.span, None) }); self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b` }) @@ -1685,7 +1685,7 @@ impl<'tcx> SubregionOrigin<'tcx> { Subtype(ref a) => a.span(), RelateObjectBound(a) => a, RelateParamBound(a, ..) => a, - RelateRegionParamBound(a) => a, + RelateRegionParamBound(a, _) => a, Reborrow(a) => a, ReferenceOutlivesReferent(_, a) => a, CompareImplItemObligation { span, .. } => span, @@ -1726,6 +1726,10 @@ impl<'tcx> SubregionOrigin<'tcx> { SubregionOrigin::AscribeUserTypeProvePredicate(span) } + traits::ObligationCauseCode::ObjectTypeBound(ty, _reg) => { + SubregionOrigin::RelateRegionParamBound(cause.span, Some(ty)) + } + _ => default(), } } diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index 542104fa10b..6fa10a95313 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -705,7 +705,7 @@ impl<'tcx> TypeRelation> for Generalizer<'_, 'tcx> { /// not only the generalized type, but also a bool flag /// indicating whether further WF checks are needed. #[derive(Debug)] -pub struct Generalization { +struct Generalization { /// When generalizing `::Assoc` or /// `::Assoc>>::Assoc` /// for `?0` generalization returns an inference diff --git a/compiler/rustc_infer/src/infer/relate/lattice.rs b/compiler/rustc_infer/src/infer/relate/lattice.rs index f555fedbb5b..1eafbb9acb3 100644 --- a/compiler/rustc_infer/src/infer/relate/lattice.rs +++ b/compiler/rustc_infer/src/infer/relate/lattice.rs @@ -29,7 +29,7 @@ use crate::traits::ObligationCause; /// /// GLB moves "down" the lattice (to smaller values); LUB moves /// "up" the lattice (to bigger values). -pub trait LatticeDir<'f, 'tcx>: PredicateEmittingRelation> { +pub(crate) trait LatticeDir<'f, 'tcx>: PredicateEmittingRelation> { fn infcx(&self) -> &'f InferCtxt<'tcx>; fn cause(&self) -> &ObligationCause<'tcx>; diff --git a/compiler/rustc_infer/src/infer/snapshot/fudge.rs b/compiler/rustc_infer/src/infer/snapshot/fudge.rs index bc954054ea2..fdf55447f79 100644 --- a/compiler/rustc_infer/src/infer/snapshot/fudge.rs +++ b/compiler/rustc_infer/src/infer/snapshot/fudge.rs @@ -170,7 +170,7 @@ impl<'tcx> InferCtxt<'tcx> { } } -pub struct InferenceFudger<'a, 'tcx> { +struct InferenceFudger<'a, 'tcx> { infcx: &'a InferCtxt<'tcx>, type_vars: (Range, Vec), int_vars: Range, diff --git a/compiler/rustc_infer/src/infer/snapshot/undo_log.rs b/compiler/rustc_infer/src/infer/snapshot/undo_log.rs index 50a0d3bf214..366af913ddc 100644 --- a/compiler/rustc_infer/src/infer/snapshot/undo_log.rs +++ b/compiler/rustc_infer/src/infer/snapshot/undo_log.rs @@ -158,7 +158,7 @@ impl<'tcx> InferCtxtInner<'tcx> { } impl<'tcx> InferCtxtUndoLogs<'tcx> { - pub fn start_snapshot(&mut self) -> Snapshot<'tcx> { + pub(crate) fn start_snapshot(&mut self) -> Snapshot<'tcx> { self.num_open_snapshots += 1; Snapshot { undo_len: self.logs.len(), _marker: PhantomData } } diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index 25ac8ba974b..94aa2ddd92f 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -27,9 +27,8 @@ #![feature(iterator_try_collect)] #![feature(let_chains)] #![feature(rustdoc_internals)] -#![feature(try_blocks)] -#![feature(yeet_expr)] #![recursion_limit = "512"] // For rustdoc +#![warn(unreachable_pub)] // tidy-alphabetical-end #[macro_use] diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index 4f34c139545..3a05b576a97 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -22,7 +22,7 @@ pub use self::engine::{FromSolverError, ScrubbedTraitError, TraitEngine}; pub(crate) use self::project::UndoLog; pub use self::project::{ MismatchedProjectionTypes, Normalized, NormalizedTerm, ProjectionCache, ProjectionCacheEntry, - ProjectionCacheKey, ProjectionCacheStorage, Reveal, + ProjectionCacheKey, ProjectionCacheStorage, }; pub use self::ImplSource::*; pub use self::SelectionError::*; diff --git a/compiler/rustc_infer/src/traits/project.rs b/compiler/rustc_infer/src/traits/project.rs index 9ed557ec40b..3d4ec9e51db 100644 --- a/compiler/rustc_infer/src/traits/project.rs +++ b/compiler/rustc_infer/src/traits/project.rs @@ -2,7 +2,7 @@ use rustc_data_structures::snapshot_map::{self, SnapshotMapRef, SnapshotMapStorage}; use rustc_data_structures::undo_log::Rollback; -pub use rustc_middle::traits::{EvaluationResult, Reveal}; +use rustc_middle::traits::EvaluationResult; use rustc_middle::ty; use super::PredicateObligation; diff --git a/compiler/rustc_interface/src/callbacks.rs b/compiler/rustc_interface/src/callbacks.rs index 786e2bb511f..f66b9eb3a28 100644 --- a/compiler/rustc_interface/src/callbacks.rs +++ b/compiler/rustc_interface/src/callbacks.rs @@ -18,11 +18,19 @@ use rustc_query_system::dep_graph::dep_node::default_dep_kind_debug; use rustc_query_system::dep_graph::{DepContext, DepKind, DepNode}; fn track_span_parent(def_id: rustc_span::def_id::LocalDefId) { - tls::with_opt(|tcx| { - if let Some(tcx) = tcx { - let _span = tcx.source_span(def_id); - // Sanity check: relative span's parent must be an absolute span. - debug_assert_eq!(_span.data_untracked().parent, None); + tls::with_context_opt(|icx| { + if let Some(icx) = icx { + // `track_span_parent` gets called a lot from HIR lowering code. + // Skip doing anything if we aren't tracking dependencies. + let tracks_deps = match icx.task_deps { + TaskDepsRef::Allow(..) => true, + TaskDepsRef::EvalAlways | TaskDepsRef::Ignore | TaskDepsRef::Forbid => false, + }; + if tracks_deps { + let _span = icx.tcx.source_span(def_id); + // Sanity check: relative span's parent must be an absolute span. + debug_assert_eq!(_span.data_untracked().parent, None); + } } }) } diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs index e37b30749ab..3b6c2acaf30 100644 --- a/compiler/rustc_interface/src/lib.rs +++ b/compiler/rustc_interface/src/lib.rs @@ -1,8 +1,8 @@ // tidy-alphabetical-start #![feature(decl_macro)] #![feature(let_chains)] -#![feature(thread_spawn_unchecked)] #![feature(try_blocks)] +#![warn(unreachable_pub)] // tidy-alphabetical-end mod callbacks; diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 96a6f52d60b..779b98d073d 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -784,7 +784,20 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { } ); }); + rustc_hir_analysis::check_crate(tcx); + sess.time("MIR_coroutine_by_move_body", || { + tcx.hir().par_body_owners(|def_id| { + if tcx.needs_coroutine_by_move_body_def_id(def_id) { + tcx.ensure_with_value().coroutine_by_move_body_def_id(def_id); + } + }); + }); + // Freeze definitions as we don't add new ones at this point. + // We need to wait until now since we synthesize a by-move body + // This improves performance by allowing lock-free access to them. + tcx.untracked().definitions.freeze(); + sess.time("MIR_borrow_checking", || { tcx.hir().par_body_owners(|def_id| { // Run unsafety check because it's responsible for stealing and @@ -816,6 +829,7 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { ); } }); + sess.time("layout_testing", || layout_test::test_layout(tcx)); sess.time("abi_testing", || abi_test::test_abi(tcx)); diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index c5d56c15c6e..44e07b36b61 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -98,7 +98,7 @@ impl<'tcx> Queries<'tcx> { self.parse.compute(|| passes::parse(&self.compiler.sess)) } - pub fn global_ctxt(&'tcx self) -> Result>> { + pub fn global_ctxt(&'tcx self) -> Result>> { self.gcx.compute(|| { let krate = self.parse()?.steal(); diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 34f2dca7c42..486136a2bcc 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -774,6 +774,7 @@ fn test_unstable_options_tracking_hash() { tracked!(direct_access_external_data, Some(true)); tracked!(dual_proc_macros, true); tracked!(dwarf_version, Some(5)); + tracked!(embed_source, true); tracked!(emit_thin_lto, false); tracked!(export_executable_symbols, true); tracked!(fewer_names, Some(true)); diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index 2116ba6c079..31fdd2d7cec 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -23,6 +23,7 @@ // We want to be able to build this crate with a stable compiler, // so no `#![feature]` attributes should be added. #![deny(unstable_features)] +#![warn(unreachable_pub)] // tidy-alphabetical-end mod cursor; diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 7a394a6d6c1..08a50050a36 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -361,6 +361,11 @@ lint_improper_ctypes_box = box cannot be represented as a single pointer lint_improper_ctypes_char_help = consider using `u32` or `libc::wchar_t` instead lint_improper_ctypes_char_reason = the `char` type has no C equivalent + +lint_improper_ctypes_cstr_help = + consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` +lint_improper_ctypes_cstr_reason = `CStr`/`CString` do not have a guaranteed layout + lint_improper_ctypes_dyn = trait objects have no C equivalent lint_improper_ctypes_enum_repr_help = @@ -758,6 +763,9 @@ lint_suspicious_double_ref_clone = lint_suspicious_double_ref_deref = using `.deref()` on a double reference, which returns `{$ty}` instead of dereferencing the inner type +lint_tail_expr_drop_order = these values and local bindings have significant drop implementation that will have a different drop order from that of Edition 2021 + .label = these values have significant drop implementation and will observe changes in drop order under Edition 2024 + lint_trailing_semi_macro = trailing semicolon in macro used in expression position .note1 = macro invocations at the end of a block are treated as expressions .note2 = to ignore the value produced by the macro, add a semicolon after the invocation of `{$name}` diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 6b36944b208..d8482567bbe 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1330,7 +1330,7 @@ impl UnreachablePub { BuiltinUnreachablePub { what, suggestion: (vis_span, applicability), - help: exportable.then_some(()), + help: exportable, }, ); } @@ -1853,7 +1853,7 @@ impl KeywordIdents { if !prev_dollar { self.check_ident_token(cx, UnderMacro(true), ident); } - } else if token.kind == TokenKind::Dollar { + } else if *token == TokenKind::Dollar { prev_dollar = true; continue; } @@ -1925,8 +1925,8 @@ impl ExplicitOutlivesRequirements { fn lifetimes_outliving_lifetime<'tcx>( tcx: TyCtxt<'tcx>, inferred_outlives: impl Iterator, Span)>, - item: DefId, - lifetime: DefId, + item: LocalDefId, + lifetime: LocalDefId, ) -> Vec> { let item_generics = tcx.generics_of(item); @@ -1934,7 +1934,7 @@ impl ExplicitOutlivesRequirements { .filter_map(|(clause, _)| match clause.kind().skip_binder() { ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => match *a { ty::ReEarlyParam(ebr) - if item_generics.region_param(ebr, tcx).def_id == lifetime => + if item_generics.region_param(ebr, tcx).def_id == lifetime.to_def_id() => { Some(b) } @@ -1982,7 +1982,7 @@ impl ExplicitOutlivesRequirements { let is_inferred = match tcx.named_bound_var(lifetime.hir_id) { Some(ResolvedArg::EarlyBound(def_id)) => inferred_outlives .iter() - .any(|r| matches!(**r, ty::ReEarlyParam(ebr) if { item_generics.region_param(ebr, tcx).def_id == def_id })), + .any(|r| matches!(**r, ty::ReEarlyParam(ebr) if { item_generics.region_param(ebr, tcx).def_id == def_id.to_def_id() })), _ => false, }; @@ -2097,7 +2097,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { inferred_outlives .iter() .filter(|(_, span)| !predicate.span.contains(*span)), - item.owner_id.to_def_id(), + item.owner_id.def_id, region_def_id, ), &predicate.bounds, diff --git a/compiler/rustc_lint/src/drop_forget_useless.rs b/compiler/rustc_lint/src/drop_forget_useless.rs index 2060858cc8a..a9de258e005 100644 --- a/compiler/rustc_lint/src/drop_forget_useless.rs +++ b/compiler/rustc_lint/src/drop_forget_useless.rs @@ -151,10 +151,11 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetUseless { && let Node::Stmt(stmt) = node && let StmtKind::Semi(e) = stmt.kind && e.hir_id == expr.hir_id + && let Some(arg_span) = arg.span.find_ancestor_inside(expr.span) { UseLetUnderscoreIgnoreSuggestion::Suggestion { - start_span: expr.span.shrink_to_lo().until(arg.span), - end_span: arg.span.shrink_to_hi().until(expr.span.shrink_to_hi()), + start_span: expr.span.shrink_to_lo().until(arg_span), + end_span: arg_span.shrink_to_hi().until(expr.span.shrink_to_hi()), } } else { UseLetUnderscoreIgnoreSuggestion::Note diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 6fb0a624644..0ee9dda1fef 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -413,7 +413,7 @@ pub fn check_ast_node<'a>( } } -pub fn check_ast_node_inner<'a, T: EarlyLintPass>( +fn check_ast_node_inner<'a, T: EarlyLintPass>( sess: &Session, check_node: impl EarlyCheckNode<'a>, context: EarlyContext<'_>, diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs index 23e6b73ee37..d109a5c9030 100644 --- a/compiler/rustc_lint/src/errors.rs +++ b/compiler/rustc_lint/src/errors.rs @@ -8,7 +8,7 @@ use crate::fluent_generated as fluent; #[derive(Diagnostic)] #[diag(lint_overruled_attribute, code = E0453)] -pub struct OverruledAttribute<'a> { +pub(crate) struct OverruledAttribute<'a> { #[primary_span] pub span: Span, #[label] @@ -19,7 +19,7 @@ pub struct OverruledAttribute<'a> { pub sub: OverruledAttributeSub, } -pub enum OverruledAttributeSub { +pub(crate) enum OverruledAttributeSub { DefaultSource { id: String }, NodeSource { span: Span, reason: Option }, CommandLineSource, @@ -52,7 +52,7 @@ impl Subdiagnostic for OverruledAttributeSub { #[derive(Diagnostic)] #[diag(lint_malformed_attribute, code = E0452)] -pub struct MalformedAttribute { +pub(crate) struct MalformedAttribute { #[primary_span] pub span: Span, #[subdiagnostic] @@ -60,7 +60,7 @@ pub struct MalformedAttribute { } #[derive(Subdiagnostic)] -pub enum MalformedAttributeSub { +pub(crate) enum MalformedAttributeSub { #[label(lint_bad_attribute_argument)] BadAttributeArgument(#[primary_span] Span), #[label(lint_reason_must_be_string_literal)] @@ -71,18 +71,18 @@ pub enum MalformedAttributeSub { #[derive(Diagnostic)] #[diag(lint_unknown_tool_in_scoped_lint, code = E0710)] -pub struct UnknownToolInScopedLint { +pub(crate) struct UnknownToolInScopedLint { #[primary_span] pub span: Option, pub tool_name: Symbol, pub lint_name: String, #[help] - pub is_nightly_build: Option<()>, + pub is_nightly_build: bool, } #[derive(Diagnostic)] #[diag(lint_builtin_ellipsis_inclusive_range_patterns, code = E0783)] -pub struct BuiltinEllipsisInclusiveRangePatterns { +pub(crate) struct BuiltinEllipsisInclusiveRangePatterns { #[primary_span] pub span: Span, #[suggestion(style = "short", code = "{replace}", applicability = "machine-applicable")] @@ -92,20 +92,20 @@ pub struct BuiltinEllipsisInclusiveRangePatterns { #[derive(Subdiagnostic)] #[note(lint_requested_level)] -pub struct RequestedLevel<'a> { +pub(crate) struct RequestedLevel<'a> { pub level: Level, pub lint_name: &'a str, } #[derive(Diagnostic)] #[diag(lint_unsupported_group, code = E0602)] -pub struct UnsupportedGroup { +pub(crate) struct UnsupportedGroup { pub lint_group: String, } #[derive(Diagnostic)] #[diag(lint_check_name_unknown_tool, code = E0602)] -pub struct CheckNameUnknownTool<'a> { +pub(crate) struct CheckNameUnknownTool<'a> { pub tool_name: Symbol, #[subdiagnostic] pub sub: RequestedLevel<'a>, diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs index 35af694213d..42b33f9882d 100644 --- a/compiler/rustc_lint/src/expect.rs +++ b/compiler/rustc_lint/src/expect.rs @@ -24,7 +24,7 @@ fn check_expectations(tcx: TyCtxt<'_>, tool_filter: Option) { && tool_filter.map_or(true, |filter| expectation.lint_tool == Some(filter)) { let rationale = expectation.reason.map(|rationale| ExpectationNote { rationale }); - let note = expectation.is_unfulfilled_lint_expectations.then_some(()); + let note = expectation.is_unfulfilled_lint_expectations; tcx.emit_node_span_lint( UNFULFILLED_LINT_EXPECTATIONS, *hir_id, diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs index 6cb5263ac54..2793d48dc51 100644 --- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs +++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs @@ -1,5 +1,5 @@ use hir::{Expr, Pat}; -use rustc_hir as hir; +use rustc_hir::{self as hir, LangItem}; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::ObligationCause; use rustc_middle::ty; @@ -126,7 +126,10 @@ fn extract_iterator_next_call<'tcx>( ) -> Option<&'tcx Expr<'tcx>> { // This won't work for `Iterator::next(iter)`, is this an issue? if let hir::ExprKind::MethodCall(_, recv, _, _) = expr.kind - && cx.typeck_results().type_dependent_def_id(expr.hir_id) == cx.tcx.lang_items().next_fn() + && cx + .typeck_results() + .type_dependent_def_id(expr.hir_id) + .is_some_and(|def_id| cx.tcx.is_lang_item(def_id, LangItem::IteratorNext)) { Some(recv) } else { diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs index e914169f4c3..8824e1dfe50 100644 --- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs +++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs @@ -10,7 +10,9 @@ use rustc_middle::middle::resolve_bound_vars::ResolvedArg; use rustc_middle::ty::{ self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, }; +use rustc_session::lint::FutureIncompatibilityReason; use rustc_session::{declare_lint, declare_lint_pass}; +use rustc_span::edition::Edition; use rustc_span::Span; use crate::{fluent_generated as fluent, LateContext, LateLintPass}; @@ -27,8 +29,6 @@ declare_lint! { /// ### Example /// /// ```rust,compile_fail - /// # #![feature(precise_capturing)] - /// # #![allow(incomplete_features)] /// # #![deny(impl_trait_overcaptures)] /// # use std::fmt::Display; /// let mut x = vec![]; @@ -56,11 +56,10 @@ declare_lint! { pub IMPL_TRAIT_OVERCAPTURES, Allow, "`impl Trait` will capture more lifetimes than possibly intended in edition 2024", - @feature_gate = precise_capturing; - //@future_incompatible = FutureIncompatibleInfo { - // reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2024), - // reference: "", - //}; + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2024), + reference: "", + }; } declare_lint! { @@ -75,8 +74,7 @@ declare_lint! { /// ### Example /// /// ```rust,compile_fail - /// # #![feature(precise_capturing, lifetime_capture_rules_2024)] - /// # #![allow(incomplete_features)] + /// # #![feature(lifetime_capture_rules_2024)] /// # #![deny(impl_trait_redundant_captures)] /// fn test<'a>(x: &'a i32) -> impl Sized + use<'a> { x } /// ``` @@ -90,7 +88,6 @@ declare_lint! { pub IMPL_TRAIT_REDUNDANT_CAPTURES, Warn, "redundant precise-capturing `use<...>` syntax on an `impl Trait`", - @feature_gate = precise_capturing; } declare_lint_pass!( @@ -305,16 +302,17 @@ impl<'tcx> TypeVisitor> for VisitOpaqueTypes<'tcx> { Some( ResolvedArg::EarlyBound(def_id) | ResolvedArg::LateBound(_, _, def_id), ) => { - if self.tcx.def_kind(self.tcx.parent(def_id)) == DefKind::OpaqueTy { + if self.tcx.def_kind(self.tcx.local_parent(def_id)) == DefKind::OpaqueTy + { let def_id = self .tcx - .map_opaque_lifetime_to_parent_lifetime(def_id.expect_local()) + .map_opaque_lifetime_to_parent_lifetime(def_id) .opt_param_def_id(self.tcx, self.parent_def_id.to_def_id()) .expect("variable should have been duplicated from parent"); explicitly_captured.insert(def_id); } else { - explicitly_captured.insert(def_id); + explicitly_captured.insert(def_id.to_def_id()); } } _ => { diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 044c9413f0b..65571815019 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -8,7 +8,7 @@ use rustc_hir::{ BinOp, BinOpKind, Expr, ExprKind, GenericArg, HirId, Impl, Item, ItemKind, Node, Pat, PatKind, Path, PathSegment, QPath, Ty, TyKind, }; -use rustc_middle::ty::{self, Ty as MiddleTy}; +use rustc_middle::ty::{self, GenericArgsRef, Ty as MiddleTy}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::symbol::{kw, sym, Symbol}; @@ -415,14 +415,17 @@ declare_lint_pass!(Diagnostics => [UNTRANSLATABLE_DIAGNOSTIC, DIAGNOSTIC_OUTSIDE impl LateLintPass<'_> for Diagnostics { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { + let collect_args_tys_and_spans = |args: &[Expr<'_>], reserve_one_extra: bool| { + let mut result = Vec::with_capacity(args.len() + usize::from(reserve_one_extra)); + result.extend(args.iter().map(|arg| (cx.typeck_results().expr_ty(arg), arg.span))); + result + }; // Only check function calls and method calls. - let (span, def_id, fn_gen_args, call_tys) = match expr.kind { + let (span, def_id, fn_gen_args, arg_tys_and_spans) = match expr.kind { ExprKind::Call(callee, args) => { match cx.typeck_results().node_type(callee.hir_id).kind() { &ty::FnDef(def_id, fn_gen_args) => { - let call_tys: Vec<_> = - args.iter().map(|arg| cx.typeck_results().expr_ty(arg)).collect(); - (callee.span, def_id, fn_gen_args, call_tys) + (callee.span, def_id, fn_gen_args, collect_args_tys_and_spans(args, false)) } _ => return, // occurs for fns passed as args } @@ -432,38 +435,40 @@ impl LateLintPass<'_> for Diagnostics { else { return; }; - let mut call_tys: Vec<_> = - args.iter().map(|arg| cx.typeck_results().expr_ty(arg)).collect(); - call_tys.insert(0, cx.tcx.types.self_param); // dummy inserted for `self` - (span, def_id, fn_gen_args, call_tys) + let mut args = collect_args_tys_and_spans(args, true); + args.insert(0, (cx.tcx.types.self_param, _recv.span)); // dummy inserted for `self` + (span, def_id, fn_gen_args, args) } _ => return, }; - // Is the callee marked with `#[rustc_lint_diagnostics]`? - let has_attr = ty::Instance::try_resolve(cx.tcx, cx.param_env, def_id, fn_gen_args) - .ok() - .flatten() - .is_some_and(|inst| cx.tcx.has_attr(inst.def_id(), sym::rustc_lint_diagnostics)); + Self::diagnostic_outside_of_impl(cx, span, expr.hir_id, def_id, fn_gen_args); + Self::untranslatable_diagnostic(cx, def_id, &arg_tys_and_spans); + } +} - // Closure: is the type `{D,Subd}iagMessage`? - let is_diag_message = |ty: MiddleTy<'_>| { - if let Some(adt_def) = ty.ty_adt_def() - && let Some(name) = cx.tcx.get_diagnostic_name(adt_def.did()) - && matches!(name, sym::DiagMessage | sym::SubdiagMessage) - { - true - } else { - false - } - }; +impl Diagnostics { + // Is the type `{D,Subd}iagMessage`? + fn is_diag_message<'cx>(cx: &LateContext<'cx>, ty: MiddleTy<'cx>) -> bool { + if let Some(adt_def) = ty.ty_adt_def() + && let Some(name) = cx.tcx.get_diagnostic_name(adt_def.did()) + && matches!(name, sym::DiagMessage | sym::SubdiagMessage) + { + true + } else { + false + } + } - // Does the callee have one or more `impl Into<{D,Subd}iagMessage>` parameters? - let mut impl_into_diagnostic_message_params = vec![]; + fn untranslatable_diagnostic<'cx>( + cx: &LateContext<'cx>, + def_id: DefId, + arg_tys_and_spans: &[(MiddleTy<'cx>, Span)], + ) { let fn_sig = cx.tcx.fn_sig(def_id).instantiate_identity().skip_binder(); let predicates = cx.tcx.predicates_of(def_id).instantiate_identity(cx.tcx).predicates; for (i, ¶m_ty) in fn_sig.inputs().iter().enumerate() { - if let ty::Param(p) = param_ty.kind() { + if let ty::Param(sig_param) = param_ty.kind() { // It is a type parameter. Check if it is `impl Into<{D,Subd}iagMessage>`. for pred in predicates.iter() { if let Some(trait_pred) = pred.as_trait_clause() @@ -471,27 +476,53 @@ impl LateLintPass<'_> for Diagnostics { && trait_ref.self_ty() == param_ty // correct predicate for the param? && cx.tcx.is_diagnostic_item(sym::Into, trait_ref.def_id) && let ty1 = trait_ref.args.type_at(1) - && is_diag_message(ty1) + && Self::is_diag_message(cx, ty1) { - impl_into_diagnostic_message_params.push((i, p.name)); + // Calls to methods with an `impl Into<{D,Subd}iagMessage>` parameter must be passed an arg + // with type `{D,Subd}iagMessage` or `impl Into<{D,Subd}iagMessage>`. Otherwise, emit an + // `UNTRANSLATABLE_DIAGNOSTIC` lint. + let (arg_ty, arg_span) = arg_tys_and_spans[i]; + + // Is the arg type `{Sub,D}iagMessage`or `impl Into<{Sub,D}iagMessage>`? + let is_translatable = Self::is_diag_message(cx, arg_ty) + || matches!(arg_ty.kind(), ty::Param(arg_param) if arg_param.name == sig_param.name); + if !is_translatable { + cx.emit_span_lint( + UNTRANSLATABLE_DIAGNOSTIC, + arg_span, + UntranslatableDiag, + ); + } } } } } + } - // Is the callee interesting? - if !has_attr && impl_into_diagnostic_message_params.is_empty() { + fn diagnostic_outside_of_impl<'cx>( + cx: &LateContext<'cx>, + span: Span, + current_id: HirId, + def_id: DefId, + fn_gen_args: GenericArgsRef<'cx>, + ) { + // Is the callee marked with `#[rustc_lint_diagnostics]`? + let Some(inst) = + ty::Instance::try_resolve(cx.tcx, cx.param_env, def_id, fn_gen_args).ok().flatten() + else { return; - } + }; + let has_attr = cx.tcx.has_attr(inst.def_id(), sym::rustc_lint_diagnostics); + if !has_attr { + return; + }; - // Is the parent method marked with `#[rustc_lint_diagnostics]`? - let mut parent_has_attr = false; - for (hir_id, _parent) in cx.tcx.hir().parent_iter(expr.hir_id) { + for (hir_id, _parent) in cx.tcx.hir().parent_iter(current_id) { if let Some(owner_did) = hir_id.as_owner() && cx.tcx.has_attr(owner_did, sym::rustc_lint_diagnostics) { - parent_has_attr = true; - break; + // The parent method is marked with `#[rustc_lint_diagnostics]` + return; } } @@ -500,37 +531,22 @@ impl LateLintPass<'_> for Diagnostics { // - inside a parent function that is itself marked with `#[rustc_lint_diagnostics]`. // // Otherwise, emit a `DIAGNOSTIC_OUTSIDE_OF_IMPL` lint. - if has_attr && !parent_has_attr { - let mut is_inside_appropriate_impl = false; - for (_hir_id, parent) in cx.tcx.hir().parent_iter(expr.hir_id) { - debug!(?parent); - if let Node::Item(Item { kind: ItemKind::Impl(impl_), .. }) = parent - && let Impl { of_trait: Some(of_trait), .. } = impl_ - && let Some(def_id) = of_trait.trait_def_id() - && let Some(name) = cx.tcx.get_diagnostic_name(def_id) - && matches!(name, sym::Diagnostic | sym::Subdiagnostic | sym::LintDiagnostic) - { - is_inside_appropriate_impl = true; - break; - } - } - debug!(?is_inside_appropriate_impl); - if !is_inside_appropriate_impl { - cx.emit_span_lint(DIAGNOSTIC_OUTSIDE_OF_IMPL, span, DiagOutOfImpl); + let mut is_inside_appropriate_impl = false; + for (_hir_id, parent) in cx.tcx.hir().parent_iter(current_id) { + debug!(?parent); + if let Node::Item(Item { kind: ItemKind::Impl(impl_), .. }) = parent + && let Impl { of_trait: Some(of_trait), .. } = impl_ + && let Some(def_id) = of_trait.trait_def_id() + && let Some(name) = cx.tcx.get_diagnostic_name(def_id) + && matches!(name, sym::Diagnostic | sym::Subdiagnostic | sym::LintDiagnostic) + { + is_inside_appropriate_impl = true; + break; } } - - // Calls to methods with an `impl Into<{D,Subd}iagMessage>` parameter must be passed an arg - // with type `{D,Subd}iagMessage` or `impl Into<{D,Subd}iagMessage>`. Otherwise, emit an - // `UNTRANSLATABLE_DIAGNOSTIC` lint. - for (param_i, param_i_p_name) in impl_into_diagnostic_message_params { - // Is the arg type `{Sub,D}iagMessage`or `impl Into<{Sub,D}iagMessage>`? - let arg_ty = call_tys[param_i]; - let is_translatable = is_diag_message(arg_ty) - || matches!(arg_ty.kind(), ty::Param(p) if p.name == param_i_p_name); - if !is_translatable { - cx.emit_span_lint(UNTRANSLATABLE_DIAGNOSTIC, span, UntranslatableDiag); - } + debug!(?is_inside_appropriate_impl); + if !is_inside_appropriate_impl { + cx.emit_span_lint(DIAGNOSTIC_OUTSIDE_OF_IMPL, span, DiagOutOfImpl); } } } diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index 638b623510e..cb369d99a84 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -47,7 +47,7 @@ macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({ /// Implements the AST traversal for late lint passes. `T` provides the /// `check_*` methods. -pub struct LateContextAndPass<'tcx, T: LateLintPass<'tcx>> { +struct LateContextAndPass<'tcx, T: LateLintPass<'tcx>> { context: LateContext<'tcx>, pass: T, } diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 44117e5d7a5..07ac63ec96c 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -936,7 +936,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { span: tool_ident.map(|ident| ident.span), tool_name: tool_name.unwrap(), lint_name: pprust::path_to_string(&meta_item.path), - is_nightly_build: sess.is_nightly_build().then_some(()), + is_nightly_build: sess.is_nightly_build(), }); continue; } @@ -1103,7 +1103,7 @@ pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { shallow_lint_levels_on, lint_expectations, ..*providers }; } -pub fn parse_lint_and_tool_name(lint_name: &str) -> (Option, &str) { +pub(crate) fn parse_lint_and_tool_name(lint_name: &str) -> (Option, &str) { match lint_name.split_once("::") { Some((tool_name, lint_name)) => { let tool_name = Symbol::intern(tool_name); diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 4f3933d461b..c5a5c5b30af 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -39,6 +39,7 @@ #![feature(rustc_attrs)] #![feature(rustdoc_internals)] #![feature(trait_upcasting)] +#![warn(unreachable_pub)] // tidy-alphabetical-end mod async_closures; @@ -78,6 +79,7 @@ mod ptr_nulls; mod redundant_semicolon; mod reference_casting; mod shadowed_into_iter; +mod tail_expr_drop_order; mod traits; mod types; mod unit_bindings; @@ -115,6 +117,7 @@ use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use shadowed_into_iter::ShadowedIntoIter; pub use shadowed_into_iter::{ARRAY_INTO_ITER, BOXED_SLICE_INTO_ITER}; +use tail_expr_drop_order::TailExprDropOrder; use traits::*; use types::*; use unit_bindings::*; @@ -238,6 +241,7 @@ late_lint_methods!( AsyncFnInTrait: AsyncFnInTrait, NonLocalDefinitions: NonLocalDefinitions::default(), ImplTraitOvercaptures: ImplTraitOvercaptures, + TailExprDropOrder: TailExprDropOrder, ] ] ); @@ -569,7 +573,8 @@ fn register_builtins(store: &mut LintStore) { "byte_slice_in_packed_struct_with_derive", "converted into hard error, see issue #107457 \ for more information", - ) + ); + store.register_removed("writes_through_immutable_pointer", "converted into hard error"); } fn register_internals(store: &mut LintStore) { diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 03962d796f4..c6bcb1f3e83 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -26,7 +26,7 @@ use crate::{fluent_generated as fluent, LateContext}; // array_into_iter.rs #[derive(LintDiagnostic)] #[diag(lint_shadowed_into_iter)] -pub struct ShadowedIntoIterDiag { +pub(crate) struct ShadowedIntoIterDiag { pub target: &'static str, pub edition: &'static str, #[suggestion(lint_use_iter_suggestion, code = "iter", applicability = "machine-applicable")] @@ -36,7 +36,7 @@ pub struct ShadowedIntoIterDiag { } #[derive(Subdiagnostic)] -pub enum ShadowedIntoIterDiagSub { +pub(crate) enum ShadowedIntoIterDiagSub { #[suggestion(lint_remove_into_iter_suggestion, code = "", applicability = "maybe-incorrect")] RemoveIntoIter { #[primary_span] @@ -57,7 +57,7 @@ pub enum ShadowedIntoIterDiagSub { // builtin.rs #[derive(LintDiagnostic)] #[diag(lint_builtin_while_true)] -pub struct BuiltinWhileTrue { +pub(crate) struct BuiltinWhileTrue { #[suggestion(style = "short", code = "{replace}", applicability = "machine-applicable")] pub suggestion: Span, pub replace: String, @@ -65,7 +65,7 @@ pub struct BuiltinWhileTrue { #[derive(LintDiagnostic)] #[diag(lint_builtin_non_shorthand_field_patterns)] -pub struct BuiltinNonShorthandFieldPatterns { +pub(crate) struct BuiltinNonShorthandFieldPatterns { pub ident: Ident, #[suggestion(code = "{prefix}{ident}", applicability = "machine-applicable")] pub suggestion: Span, @@ -73,7 +73,7 @@ pub struct BuiltinNonShorthandFieldPatterns { } #[derive(LintDiagnostic)] -pub enum BuiltinUnsafe { +pub(crate) enum BuiltinUnsafe { #[diag(lint_builtin_allow_internal_unsafe)] AllowInternalUnsafe, #[diag(lint_builtin_unsafe_block)] @@ -121,16 +121,16 @@ pub enum BuiltinUnsafe { #[derive(LintDiagnostic)] #[diag(lint_builtin_missing_doc)] -pub struct BuiltinMissingDoc<'a> { +pub(crate) struct BuiltinMissingDoc<'a> { pub article: &'a str, pub desc: &'a str, } #[derive(LintDiagnostic)] #[diag(lint_builtin_missing_copy_impl)] -pub struct BuiltinMissingCopyImpl; +pub(crate) struct BuiltinMissingCopyImpl; -pub struct BuiltinMissingDebugImpl<'a> { +pub(crate) struct BuiltinMissingDebugImpl<'a> { pub tcx: TyCtxt<'a>, pub def_id: DefId, } @@ -145,7 +145,7 @@ impl<'a> LintDiagnostic<'a, ()> for BuiltinMissingDebugImpl<'_> { #[derive(LintDiagnostic)] #[diag(lint_builtin_anonymous_params)] -pub struct BuiltinAnonymousParams<'a> { +pub(crate) struct BuiltinAnonymousParams<'a> { #[suggestion(code = "_: {ty_snip}")] pub suggestion: (Span, Applicability), pub ty_snip: &'a str, @@ -154,7 +154,7 @@ pub struct BuiltinAnonymousParams<'a> { // FIXME(davidtwco) translatable deprecated attr #[derive(LintDiagnostic)] #[diag(lint_builtin_deprecated_attr_link)] -pub struct BuiltinDeprecatedAttrLink<'a> { +pub(crate) struct BuiltinDeprecatedAttrLink<'a> { pub name: Symbol, pub reason: &'a str, pub link: &'a str, @@ -163,7 +163,7 @@ pub struct BuiltinDeprecatedAttrLink<'a> { } #[derive(Subdiagnostic)] -pub enum BuiltinDeprecatedAttrLinkSuggestion<'a> { +pub(crate) enum BuiltinDeprecatedAttrLinkSuggestion<'a> { #[suggestion(lint_msg_suggestion, code = "", applicability = "machine-applicable")] Msg { #[primary_span] @@ -179,7 +179,7 @@ pub enum BuiltinDeprecatedAttrLinkSuggestion<'a> { #[derive(LintDiagnostic)] #[diag(lint_builtin_deprecated_attr_used)] -pub struct BuiltinDeprecatedAttrUsed { +pub(crate) struct BuiltinDeprecatedAttrUsed { pub name: String, #[suggestion( lint_builtin_deprecated_attr_default_suggestion, @@ -192,7 +192,7 @@ pub struct BuiltinDeprecatedAttrUsed { #[derive(LintDiagnostic)] #[diag(lint_builtin_unused_doc_comment)] -pub struct BuiltinUnusedDocComment<'a> { +pub(crate) struct BuiltinUnusedDocComment<'a> { pub kind: &'a str, #[label] pub label: Span, @@ -201,7 +201,7 @@ pub struct BuiltinUnusedDocComment<'a> { } #[derive(Subdiagnostic)] -pub enum BuiltinUnusedDocCommentSub { +pub(crate) enum BuiltinUnusedDocCommentSub { #[help(lint_plain_help)] PlainHelp, #[help(lint_block_help)] @@ -210,7 +210,7 @@ pub enum BuiltinUnusedDocCommentSub { #[derive(LintDiagnostic)] #[diag(lint_builtin_no_mangle_generic)] -pub struct BuiltinNoMangleGeneric { +pub(crate) struct BuiltinNoMangleGeneric { // Use of `#[no_mangle]` suggests FFI intent; correct // fix may be to monomorphize source by hand #[suggestion(style = "short", code = "", applicability = "maybe-incorrect")] @@ -219,21 +219,21 @@ pub struct BuiltinNoMangleGeneric { #[derive(LintDiagnostic)] #[diag(lint_builtin_const_no_mangle)] -pub struct BuiltinConstNoMangle { +pub(crate) struct BuiltinConstNoMangle { #[suggestion(code = "pub static", applicability = "machine-applicable")] pub suggestion: Span, } #[derive(LintDiagnostic)] #[diag(lint_builtin_mutable_transmutes)] -pub struct BuiltinMutablesTransmutes; +pub(crate) struct BuiltinMutablesTransmutes; #[derive(LintDiagnostic)] #[diag(lint_builtin_unstable_features)] -pub struct BuiltinUnstableFeatures; +pub(crate) struct BuiltinUnstableFeatures; // lint_ungated_async_fn_track_caller -pub struct BuiltinUngatedAsyncFnTrackCaller<'a> { +pub(crate) struct BuiltinUngatedAsyncFnTrackCaller<'a> { pub label: Span, pub session: &'a Session, } @@ -252,22 +252,22 @@ impl<'a> LintDiagnostic<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> { #[derive(LintDiagnostic)] #[diag(lint_builtin_unreachable_pub)] -pub struct BuiltinUnreachablePub<'a> { +pub(crate) struct BuiltinUnreachablePub<'a> { pub what: &'a str, #[suggestion(code = "pub(crate)")] pub suggestion: (Span, Applicability), #[help] - pub help: Option<()>, + pub help: bool, } #[derive(LintDiagnostic)] #[diag(lint_macro_expr_fragment_specifier_2024_migration)] -pub struct MacroExprFragment2024 { +pub(crate) struct MacroExprFragment2024 { #[suggestion(code = "expr_2021", applicability = "machine-applicable")] pub suggestion: Span, } -pub struct BuiltinTypeAliasBounds<'a, 'hir> { +pub(crate) struct BuiltinTypeAliasBounds<'a, 'hir> { pub in_where_clause: bool, pub label: Span, pub enable_feat_help: bool, @@ -338,13 +338,13 @@ impl<'a> LintDiagnostic<'a, ()> for BuiltinTypeAliasBounds<'_, '_> { #[derive(LintDiagnostic)] #[diag(lint_builtin_trivial_bounds)] -pub struct BuiltinTrivialBounds<'a> { +pub(crate) struct BuiltinTrivialBounds<'a> { pub predicate_kind_name: &'a str, pub predicate: Clause<'a>, } #[derive(LintDiagnostic)] -pub enum BuiltinEllipsisInclusiveRangePatternsLint { +pub(crate) enum BuiltinEllipsisInclusiveRangePatternsLint { #[diag(lint_builtin_ellipsis_inclusive_range_patterns)] Parenthesise { #[suggestion(code = "{replace}", applicability = "machine-applicable")] @@ -360,7 +360,7 @@ pub enum BuiltinEllipsisInclusiveRangePatternsLint { #[derive(LintDiagnostic)] #[diag(lint_builtin_keyword_idents)] -pub struct BuiltinKeywordIdents { +pub(crate) struct BuiltinKeywordIdents { pub kw: Ident, pub next: Edition, #[suggestion(code = "r#{kw}", applicability = "machine-applicable")] @@ -369,7 +369,7 @@ pub struct BuiltinKeywordIdents { #[derive(LintDiagnostic)] #[diag(lint_builtin_explicit_outlives)] -pub struct BuiltinExplicitOutlives { +pub(crate) struct BuiltinExplicitOutlives { pub count: usize, #[subdiagnostic] pub suggestion: BuiltinExplicitOutlivesSuggestion, @@ -377,7 +377,7 @@ pub struct BuiltinExplicitOutlives { #[derive(Subdiagnostic)] #[multipart_suggestion(lint_suggestion)] -pub struct BuiltinExplicitOutlivesSuggestion { +pub(crate) struct BuiltinExplicitOutlivesSuggestion { #[suggestion_part(code = "")] pub spans: Vec, #[applicability] @@ -386,7 +386,7 @@ pub struct BuiltinExplicitOutlivesSuggestion { #[derive(LintDiagnostic)] #[diag(lint_builtin_incomplete_features)] -pub struct BuiltinIncompleteFeatures { +pub(crate) struct BuiltinIncompleteFeatures { pub name: Symbol, #[subdiagnostic] pub note: Option, @@ -397,21 +397,21 @@ pub struct BuiltinIncompleteFeatures { #[derive(LintDiagnostic)] #[diag(lint_builtin_internal_features)] #[note] -pub struct BuiltinInternalFeatures { +pub(crate) struct BuiltinInternalFeatures { pub name: Symbol, } #[derive(Subdiagnostic)] #[help(lint_help)] -pub struct BuiltinIncompleteFeaturesHelp; +pub(crate) struct BuiltinIncompleteFeaturesHelp; #[derive(Subdiagnostic)] #[note(lint_note)] -pub struct BuiltinFeatureIssueNote { +pub(crate) struct BuiltinFeatureIssueNote { pub n: NonZero, } -pub struct BuiltinUnpermittedTypeInit<'a> { +pub(crate) struct BuiltinUnpermittedTypeInit<'a> { pub msg: DiagMessage, pub ty: Ty<'a>, pub label: Span, @@ -436,7 +436,7 @@ impl<'a> LintDiagnostic<'a, ()> for BuiltinUnpermittedTypeInit<'_> { } // FIXME(davidtwco): make translatable -pub struct BuiltinUnpermittedTypeInitSub { +pub(crate) struct BuiltinUnpermittedTypeInitSub { pub err: InitError, } @@ -463,7 +463,7 @@ impl Subdiagnostic for BuiltinUnpermittedTypeInitSub { } #[derive(LintDiagnostic)] -pub enum BuiltinClashingExtern<'a> { +pub(crate) enum BuiltinClashingExtern<'a> { #[diag(lint_builtin_clashing_extern_same_name)] SameName { this: Symbol, @@ -489,7 +489,7 @@ pub enum BuiltinClashingExtern<'a> { } // FIXME(davidtwco): translatable expected/found -pub struct BuiltinClashingExternSub<'a> { +pub(crate) struct BuiltinClashingExternSub<'a> { pub tcx: TyCtxt<'a>, pub expected: Ty<'a>, pub found: Ty<'a>, @@ -511,7 +511,7 @@ impl Subdiagnostic for BuiltinClashingExternSub<'_> { #[derive(LintDiagnostic)] #[diag(lint_builtin_deref_nullptr)] -pub struct BuiltinDerefNullptr { +pub(crate) struct BuiltinDerefNullptr { #[label] pub label: Span, } @@ -519,7 +519,7 @@ pub struct BuiltinDerefNullptr { // FIXME: migrate fluent::lint::builtin_asm_labels #[derive(LintDiagnostic)] -pub enum BuiltinSpecialModuleNameUsed { +pub(crate) enum BuiltinSpecialModuleNameUsed { #[diag(lint_builtin_special_module_name_used_lib)] #[note] #[help] @@ -532,7 +532,7 @@ pub enum BuiltinSpecialModuleNameUsed { // deref_into_dyn_supertrait.rs #[derive(LintDiagnostic)] #[diag(lint_supertrait_as_deref_target)] -pub struct SupertraitAsDerefTarget<'a> { +pub(crate) struct SupertraitAsDerefTarget<'a> { pub self_ty: Ty<'a>, pub supertrait_principal: PolyExistentialTraitRef<'a>, pub target_principal: PolyExistentialTraitRef<'a>, @@ -544,7 +544,7 @@ pub struct SupertraitAsDerefTarget<'a> { #[derive(Subdiagnostic)] #[label(lint_label2)] -pub struct SupertraitAsDerefTargetLabel { +pub(crate) struct SupertraitAsDerefTargetLabel { #[primary_span] pub label: Span, } @@ -552,7 +552,7 @@ pub struct SupertraitAsDerefTargetLabel { // enum_intrinsics_non_enums.rs #[derive(LintDiagnostic)] #[diag(lint_enum_intrinsics_mem_discriminant)] -pub struct EnumIntrinsicsMemDiscriminate<'a> { +pub(crate) struct EnumIntrinsicsMemDiscriminate<'a> { pub ty_param: Ty<'a>, #[note] pub note: Span, @@ -561,29 +561,29 @@ pub struct EnumIntrinsicsMemDiscriminate<'a> { #[derive(LintDiagnostic)] #[diag(lint_enum_intrinsics_mem_variant)] #[note] -pub struct EnumIntrinsicsMemVariant<'a> { +pub(crate) struct EnumIntrinsicsMemVariant<'a> { pub ty_param: Ty<'a>, } // expect.rs #[derive(LintDiagnostic)] #[diag(lint_expectation)] -pub struct Expectation { +pub(crate) struct Expectation { #[subdiagnostic] pub rationale: Option, #[note] - pub note: Option<()>, + pub note: bool, } #[derive(Subdiagnostic)] #[note(lint_rationale)] -pub struct ExpectationNote { +pub(crate) struct ExpectationNote { pub rationale: Symbol, } // ptr_nulls.rs #[derive(LintDiagnostic)] -pub enum PtrNullChecksDiag<'a> { +pub(crate) enum PtrNullChecksDiag<'a> { #[diag(lint_ptr_null_checks_fn_ptr)] #[help(lint_help)] FnPtr { @@ -604,7 +604,7 @@ pub enum PtrNullChecksDiag<'a> { // for_loops_over_fallibles.rs #[derive(LintDiagnostic)] #[diag(lint_for_loops_over_fallibles)] -pub struct ForLoopsOverFalliblesDiag<'a> { +pub(crate) struct ForLoopsOverFalliblesDiag<'a> { pub article: &'static str, pub ref_prefix: &'static str, pub ty: &'static str, @@ -617,7 +617,7 @@ pub struct ForLoopsOverFalliblesDiag<'a> { } #[derive(Subdiagnostic)] -pub enum ForLoopsOverFalliblesLoopSub<'a> { +pub(crate) enum ForLoopsOverFalliblesLoopSub<'a> { #[suggestion(lint_remove_next, code = ".by_ref()", applicability = "maybe-incorrect")] RemoveNext { #[primary_span] @@ -636,14 +636,14 @@ pub enum ForLoopsOverFalliblesLoopSub<'a> { #[derive(Subdiagnostic)] #[suggestion(lint_use_question_mark, code = "?", applicability = "maybe-incorrect")] -pub struct ForLoopsOverFalliblesQuestionMark { +pub(crate) struct ForLoopsOverFalliblesQuestionMark { #[primary_span] pub suggestion: Span, } #[derive(Subdiagnostic)] #[multipart_suggestion(lint_suggestion, applicability = "maybe-incorrect")] -pub struct ForLoopsOverFalliblesSuggestion<'a> { +pub(crate) struct ForLoopsOverFalliblesSuggestion<'a> { pub var: &'a str, #[suggestion_part(code = "if let {var}(")] pub start_span: Span, @@ -652,7 +652,7 @@ pub struct ForLoopsOverFalliblesSuggestion<'a> { } #[derive(Subdiagnostic)] -pub enum UseLetUnderscoreIgnoreSuggestion { +pub(crate) enum UseLetUnderscoreIgnoreSuggestion { #[note(lint_use_let_underscore_ignore_suggestion)] Note, #[multipart_suggestion( @@ -671,7 +671,7 @@ pub enum UseLetUnderscoreIgnoreSuggestion { // drop_forget_useless.rs #[derive(LintDiagnostic)] #[diag(lint_dropping_references)] -pub struct DropRefDiag<'a> { +pub(crate) struct DropRefDiag<'a> { pub arg_ty: Ty<'a>, #[label] pub label: Span, @@ -681,7 +681,7 @@ pub struct DropRefDiag<'a> { #[derive(LintDiagnostic)] #[diag(lint_dropping_copy_types)] -pub struct DropCopyDiag<'a> { +pub(crate) struct DropCopyDiag<'a> { pub arg_ty: Ty<'a>, #[label] pub label: Span, @@ -691,7 +691,7 @@ pub struct DropCopyDiag<'a> { #[derive(LintDiagnostic)] #[diag(lint_forgetting_references)] -pub struct ForgetRefDiag<'a> { +pub(crate) struct ForgetRefDiag<'a> { pub arg_ty: Ty<'a>, #[label] pub label: Span, @@ -701,7 +701,7 @@ pub struct ForgetRefDiag<'a> { #[derive(LintDiagnostic)] #[diag(lint_forgetting_copy_types)] -pub struct ForgetCopyDiag<'a> { +pub(crate) struct ForgetCopyDiag<'a> { pub arg_ty: Ty<'a>, #[label] pub label: Span, @@ -711,7 +711,7 @@ pub struct ForgetCopyDiag<'a> { #[derive(LintDiagnostic)] #[diag(lint_undropped_manually_drops)] -pub struct UndroppedManuallyDropsDiag<'a> { +pub(crate) struct UndroppedManuallyDropsDiag<'a> { pub arg_ty: Ty<'a>, #[label] pub label: Span, @@ -721,7 +721,7 @@ pub struct UndroppedManuallyDropsDiag<'a> { #[derive(Subdiagnostic)] #[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] -pub struct UndroppedManuallyDropsSuggestion { +pub(crate) struct UndroppedManuallyDropsSuggestion { #[suggestion_part(code = "std::mem::ManuallyDrop::into_inner(")] pub start_span: Span, #[suggestion_part(code = ")")] @@ -730,7 +730,7 @@ pub struct UndroppedManuallyDropsSuggestion { // invalid_from_utf8.rs #[derive(LintDiagnostic)] -pub enum InvalidFromUtf8Diag { +pub(crate) enum InvalidFromUtf8Diag { #[diag(lint_invalid_from_utf8_unchecked)] Unchecked { method: String, @@ -749,14 +749,14 @@ pub enum InvalidFromUtf8Diag { // reference_casting.rs #[derive(LintDiagnostic)] -pub enum InvalidReferenceCastingDiag<'tcx> { +pub(crate) enum InvalidReferenceCastingDiag<'tcx> { #[diag(lint_invalid_reference_casting_borrow_as_mut)] #[note(lint_invalid_reference_casting_note_book)] BorrowAsMut { #[label] orig_cast: Option, #[note(lint_invalid_reference_casting_note_ty_has_interior_mutability)] - ty_has_interior_mutability: Option<()>, + ty_has_interior_mutability: bool, }, #[diag(lint_invalid_reference_casting_assign_to_ref)] #[note(lint_invalid_reference_casting_note_book)] @@ -764,7 +764,7 @@ pub enum InvalidReferenceCastingDiag<'tcx> { #[label] orig_cast: Option, #[note(lint_invalid_reference_casting_note_ty_has_interior_mutability)] - ty_has_interior_mutability: Option<()>, + ty_has_interior_mutability: bool, }, #[diag(lint_invalid_reference_casting_bigger_layout)] #[note(lint_layout)] @@ -784,7 +784,7 @@ pub enum InvalidReferenceCastingDiag<'tcx> { #[derive(LintDiagnostic)] #[diag(lint_hidden_unicode_codepoints)] #[note] -pub struct HiddenUnicodeCodepointsDiag<'a> { +pub(crate) struct HiddenUnicodeCodepointsDiag<'a> { pub label: &'a str, pub count: usize, #[label] @@ -795,7 +795,7 @@ pub struct HiddenUnicodeCodepointsDiag<'a> { pub sub: HiddenUnicodeCodepointsDiagSub, } -pub struct HiddenUnicodeCodepointsDiagLabels { +pub(crate) struct HiddenUnicodeCodepointsDiagLabels { pub spans: Vec<(char, Span)>, } @@ -811,7 +811,7 @@ impl Subdiagnostic for HiddenUnicodeCodepointsDiagLabels { } } -pub enum HiddenUnicodeCodepointsDiagSub { +pub(crate) enum HiddenUnicodeCodepointsDiagSub { Escape { spans: Vec<(char, Span)> }, NoEscape { spans: Vec<(char, Span)> }, } @@ -866,7 +866,7 @@ impl Subdiagnostic for HiddenUnicodeCodepointsDiagSub { #[derive(LintDiagnostic)] #[diag(lint_map_unit_fn)] #[note] -pub struct MappingToUnit { +pub(crate) struct MappingToUnit { #[label(lint_function_label)] pub function_label: Span, #[label(lint_argument_label)] @@ -882,7 +882,7 @@ pub struct MappingToUnit { #[derive(LintDiagnostic)] #[diag(lint_default_hash_types)] #[note] -pub struct DefaultHashTypesDiag<'a> { +pub(crate) struct DefaultHashTypesDiag<'a> { pub preferred: &'a str, pub used: Symbol, } @@ -890,17 +890,17 @@ pub struct DefaultHashTypesDiag<'a> { #[derive(LintDiagnostic)] #[diag(lint_query_instability)] #[note] -pub struct QueryInstability { +pub(crate) struct QueryInstability { pub query: Symbol, } #[derive(LintDiagnostic)] #[diag(lint_span_use_eq_ctxt)] -pub struct SpanUseEqCtxtDiag; +pub(crate) struct SpanUseEqCtxtDiag; #[derive(LintDiagnostic)] #[diag(lint_tykind_kind)] -pub struct TykindKind { +pub(crate) struct TykindKind { #[suggestion(code = "ty", applicability = "maybe-incorrect")] pub suggestion: Span, } @@ -908,11 +908,11 @@ pub struct TykindKind { #[derive(LintDiagnostic)] #[diag(lint_tykind)] #[help] -pub struct TykindDiag; +pub(crate) struct TykindDiag; #[derive(LintDiagnostic)] #[diag(lint_ty_qualified)] -pub struct TyQualified { +pub(crate) struct TyQualified { pub ty: String, #[suggestion(code = "{ty}", applicability = "maybe-incorrect")] pub suggestion: Span, @@ -920,7 +920,7 @@ pub struct TyQualified { #[derive(LintDiagnostic)] #[diag(lint_non_glob_import_type_ir_inherent)] -pub struct NonGlobImportTypeIrInherent { +pub(crate) struct NonGlobImportTypeIrInherent { #[suggestion(code = "{snippet}", applicability = "maybe-incorrect")] pub suggestion: Option, pub snippet: &'static str, @@ -929,32 +929,32 @@ pub struct NonGlobImportTypeIrInherent { #[derive(LintDiagnostic)] #[diag(lint_lintpass_by_hand)] #[help] -pub struct LintPassByHand; +pub(crate) struct LintPassByHand; #[derive(LintDiagnostic)] #[diag(lint_non_existent_doc_keyword)] #[help] -pub struct NonExistentDocKeyword { +pub(crate) struct NonExistentDocKeyword { pub keyword: Symbol, } #[derive(LintDiagnostic)] #[diag(lint_diag_out_of_impl)] -pub struct DiagOutOfImpl; +pub(crate) struct DiagOutOfImpl; #[derive(LintDiagnostic)] #[diag(lint_untranslatable_diag)] -pub struct UntranslatableDiag; +pub(crate) struct UntranslatableDiag; #[derive(LintDiagnostic)] #[diag(lint_bad_opt_access)] -pub struct BadOptAccessDiag<'a> { +pub(crate) struct BadOptAccessDiag<'a> { pub msg: &'a str, } // let_underscore.rs #[derive(LintDiagnostic)] -pub enum NonBindingLet { +pub(crate) enum NonBindingLet { #[diag(lint_non_binding_let_on_sync_lock)] SyncLock { #[label] @@ -969,7 +969,7 @@ pub enum NonBindingLet { }, } -pub struct NonBindingLetSub { +pub(crate) struct NonBindingLetSub { pub suggestion: Span, pub drop_fn_start_end: Option<(Span, Span)>, pub is_assign_desugar: bool, @@ -1012,7 +1012,7 @@ impl Subdiagnostic for NonBindingLetSub { // levels.rs #[derive(LintDiagnostic)] #[diag(lint_overruled_attribute)] -pub struct OverruledAttributeLint<'a> { +pub(crate) struct OverruledAttributeLint<'a> { #[label] pub overruled: Span, pub lint_level: &'a str, @@ -1023,7 +1023,7 @@ pub struct OverruledAttributeLint<'a> { #[derive(LintDiagnostic)] #[diag(lint_deprecated_lint_name)] -pub struct DeprecatedLintName<'a> { +pub(crate) struct DeprecatedLintName<'a> { pub name: String, #[suggestion(code = "{replace}", applicability = "machine-applicable")] pub suggestion: Span, @@ -1033,7 +1033,7 @@ pub struct DeprecatedLintName<'a> { #[derive(LintDiagnostic)] #[diag(lint_deprecated_lint_name)] #[help] -pub struct DeprecatedLintNameFromCommandLine<'a> { +pub(crate) struct DeprecatedLintNameFromCommandLine<'a> { pub name: String, pub replace: &'a str, #[subdiagnostic] @@ -1042,14 +1042,14 @@ pub struct DeprecatedLintNameFromCommandLine<'a> { #[derive(LintDiagnostic)] #[diag(lint_renamed_lint)] -pub struct RenamedLint<'a> { +pub(crate) struct RenamedLint<'a> { pub name: &'a str, #[subdiagnostic] pub suggestion: RenamedLintSuggestion<'a>, } #[derive(Subdiagnostic)] -pub enum RenamedLintSuggestion<'a> { +pub(crate) enum RenamedLintSuggestion<'a> { #[suggestion(lint_suggestion, code = "{replace}", applicability = "machine-applicable")] WithSpan { #[primary_span] @@ -1062,7 +1062,7 @@ pub enum RenamedLintSuggestion<'a> { #[derive(LintDiagnostic)] #[diag(lint_renamed_lint)] -pub struct RenamedLintFromCommandLine<'a> { +pub(crate) struct RenamedLintFromCommandLine<'a> { pub name: &'a str, #[subdiagnostic] pub suggestion: RenamedLintSuggestion<'a>, @@ -1072,14 +1072,14 @@ pub struct RenamedLintFromCommandLine<'a> { #[derive(LintDiagnostic)] #[diag(lint_removed_lint)] -pub struct RemovedLint<'a> { +pub(crate) struct RemovedLint<'a> { pub name: &'a str, pub reason: &'a str, } #[derive(LintDiagnostic)] #[diag(lint_removed_lint)] -pub struct RemovedLintFromCommandLine<'a> { +pub(crate) struct RemovedLintFromCommandLine<'a> { pub name: &'a str, pub reason: &'a str, #[subdiagnostic] @@ -1088,14 +1088,14 @@ pub struct RemovedLintFromCommandLine<'a> { #[derive(LintDiagnostic)] #[diag(lint_unknown_lint)] -pub struct UnknownLint { +pub(crate) struct UnknownLint { pub name: String, #[subdiagnostic] pub suggestion: Option, } #[derive(Subdiagnostic)] -pub enum UnknownLintSuggestion { +pub(crate) enum UnknownLintSuggestion { #[suggestion(lint_suggestion, code = "{replace}", applicability = "maybe-incorrect")] WithSpan { #[primary_span] @@ -1109,7 +1109,7 @@ pub enum UnknownLintSuggestion { #[derive(LintDiagnostic)] #[diag(lint_unknown_lint, code = E0602)] -pub struct UnknownLintFromCommandLine<'a> { +pub(crate) struct UnknownLintFromCommandLine<'a> { pub name: String, #[subdiagnostic] pub suggestion: Option, @@ -1119,7 +1119,7 @@ pub struct UnknownLintFromCommandLine<'a> { #[derive(LintDiagnostic)] #[diag(lint_ignored_unless_crate_specified)] -pub struct IgnoredUnlessCrateSpecified<'a> { +pub(crate) struct IgnoredUnlessCrateSpecified<'a> { pub level: &'a str, pub name: Symbol, } @@ -1129,7 +1129,7 @@ pub struct IgnoredUnlessCrateSpecified<'a> { #[diag(lint_cstring_ptr)] #[note] #[help] -pub struct CStringPtr { +pub(crate) struct CStringPtr { #[label(lint_as_ptr_label)] pub as_ptr: Span, #[label(lint_unwrap_label)] @@ -1139,19 +1139,19 @@ pub struct CStringPtr { // multiple_supertrait_upcastable.rs #[derive(LintDiagnostic)] #[diag(lint_multiple_supertrait_upcastable)] -pub struct MultipleSupertraitUpcastable { +pub(crate) struct MultipleSupertraitUpcastable { pub ident: Ident, } // non_ascii_idents.rs #[derive(LintDiagnostic)] #[diag(lint_identifier_non_ascii_char)] -pub struct IdentifierNonAsciiChar; +pub(crate) struct IdentifierNonAsciiChar; #[derive(LintDiagnostic)] #[diag(lint_identifier_uncommon_codepoints)] #[note] -pub struct IdentifierUncommonCodepoints { +pub(crate) struct IdentifierUncommonCodepoints { pub codepoints: Vec, pub codepoints_len: usize, pub identifier_type: &'static str, @@ -1159,7 +1159,7 @@ pub struct IdentifierUncommonCodepoints { #[derive(LintDiagnostic)] #[diag(lint_confusable_identifier_pair)] -pub struct ConfusableIdentifierPair { +pub(crate) struct ConfusableIdentifierPair { pub existing_sym: Symbol, pub sym: Symbol, #[label(lint_other_use)] @@ -1172,13 +1172,13 @@ pub struct ConfusableIdentifierPair { #[diag(lint_mixed_script_confusables)] #[note(lint_includes_note)] #[note] -pub struct MixedScriptConfusables { +pub(crate) struct MixedScriptConfusables { pub set: String, pub includes: String, } // non_fmt_panic.rs -pub struct NonFmtPanicUnused { +pub(crate) struct NonFmtPanicUnused { pub count: usize, pub suggestion: Option, } @@ -1209,7 +1209,7 @@ impl<'a> LintDiagnostic<'a, ()> for NonFmtPanicUnused { #[derive(LintDiagnostic)] #[diag(lint_non_fmt_panic_braces)] #[note] -pub struct NonFmtPanicBraces { +pub(crate) struct NonFmtPanicBraces { pub count: usize, #[suggestion(code = "\"{{}}\", ", applicability = "machine-applicable")] pub suggestion: Option, @@ -1218,7 +1218,7 @@ pub struct NonFmtPanicBraces { // nonstandard_style.rs #[derive(LintDiagnostic)] #[diag(lint_non_camel_case_type)] -pub struct NonCamelCaseType<'a> { +pub(crate) struct NonCamelCaseType<'a> { pub sort: &'a str, pub name: &'a str, #[subdiagnostic] @@ -1226,7 +1226,7 @@ pub struct NonCamelCaseType<'a> { } #[derive(Subdiagnostic)] -pub enum NonCamelCaseTypeSub { +pub(crate) enum NonCamelCaseTypeSub { #[label(lint_label)] Label { #[primary_span] @@ -1242,7 +1242,7 @@ pub enum NonCamelCaseTypeSub { #[derive(LintDiagnostic)] #[diag(lint_non_snake_case)] -pub struct NonSnakeCaseDiag<'a> { +pub(crate) struct NonSnakeCaseDiag<'a> { pub sort: &'a str, pub name: &'a str, pub sc: String, @@ -1250,7 +1250,7 @@ pub struct NonSnakeCaseDiag<'a> { pub sub: NonSnakeCaseDiagSub, } -pub enum NonSnakeCaseDiagSub { +pub(crate) enum NonSnakeCaseDiagSub { Label { span: Span }, Help, RenameOrConvertSuggestion { span: Span, suggestion: Ident }, @@ -1302,7 +1302,7 @@ impl Subdiagnostic for NonSnakeCaseDiagSub { #[derive(LintDiagnostic)] #[diag(lint_non_upper_case_global)] -pub struct NonUpperCaseGlobal<'a> { +pub(crate) struct NonUpperCaseGlobal<'a> { pub sort: &'a str, pub name: &'a str, #[subdiagnostic] @@ -1310,7 +1310,7 @@ pub struct NonUpperCaseGlobal<'a> { } #[derive(Subdiagnostic)] -pub enum NonUpperCaseGlobalSub { +pub(crate) enum NonUpperCaseGlobalSub { #[label(lint_label)] Label { #[primary_span] @@ -1328,7 +1328,7 @@ pub enum NonUpperCaseGlobalSub { #[derive(LintDiagnostic)] #[diag(lint_noop_method_call)] #[note] -pub struct NoopMethodCallDiag<'a> { +pub(crate) struct NoopMethodCallDiag<'a> { pub method: Symbol, pub orig_ty: Ty<'a>, pub trait_: Symbol, @@ -1344,18 +1344,18 @@ pub struct NoopMethodCallDiag<'a> { #[derive(LintDiagnostic)] #[diag(lint_suspicious_double_ref_deref)] -pub struct SuspiciousDoubleRefDerefDiag<'a> { +pub(crate) struct SuspiciousDoubleRefDerefDiag<'a> { pub ty: Ty<'a>, } #[derive(LintDiagnostic)] #[diag(lint_suspicious_double_ref_clone)] -pub struct SuspiciousDoubleRefCloneDiag<'a> { +pub(crate) struct SuspiciousDoubleRefCloneDiag<'a> { pub ty: Ty<'a>, } // non_local_defs.rs -pub enum NonLocalDefinitionsDiag { +pub(crate) enum NonLocalDefinitionsDiag { Impl { depth: u32, body_kind_descr: &'static str, @@ -1487,7 +1487,7 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag { #[derive(Subdiagnostic)] #[note(lint_non_local_definitions_cargo_update)] -pub struct NonLocalDefinitionsCargoUpdateNote { +pub(crate) struct NonLocalDefinitionsCargoUpdateNote { pub macro_kind: &'static str, pub macro_name: Symbol, pub crate_name: Symbol, @@ -1497,7 +1497,7 @@ pub struct NonLocalDefinitionsCargoUpdateNote { #[derive(LintDiagnostic)] #[diag(lint_ambiguous_negative_literals)] #[note(lint_example)] -pub struct AmbiguousNegativeLiteralsDiag { +pub(crate) struct AmbiguousNegativeLiteralsDiag { #[subdiagnostic] pub negative_literal: AmbiguousNegativeLiteralsNegativeLiteralSuggestion, #[subdiagnostic] @@ -1506,7 +1506,7 @@ pub struct AmbiguousNegativeLiteralsDiag { #[derive(Subdiagnostic)] #[multipart_suggestion(lint_negative_literal, applicability = "maybe-incorrect")] -pub struct AmbiguousNegativeLiteralsNegativeLiteralSuggestion { +pub(crate) struct AmbiguousNegativeLiteralsNegativeLiteralSuggestion { #[suggestion_part(code = "(")] pub start_span: Span, #[suggestion_part(code = ")")] @@ -1515,7 +1515,7 @@ pub struct AmbiguousNegativeLiteralsNegativeLiteralSuggestion { #[derive(Subdiagnostic)] #[multipart_suggestion(lint_current_behavior, applicability = "maybe-incorrect")] -pub struct AmbiguousNegativeLiteralsCurrentBehaviorSuggestion { +pub(crate) struct AmbiguousNegativeLiteralsCurrentBehaviorSuggestion { #[suggestion_part(code = "(")] pub start_span: Span, #[suggestion_part(code = ")")] @@ -1525,7 +1525,7 @@ pub struct AmbiguousNegativeLiteralsCurrentBehaviorSuggestion { // pass_by_value.rs #[derive(LintDiagnostic)] #[diag(lint_pass_by_value)] -pub struct PassByValueDiag { +pub(crate) struct PassByValueDiag { pub ty: String, #[suggestion(code = "{ty}", applicability = "maybe-incorrect")] pub suggestion: Span, @@ -1534,14 +1534,14 @@ pub struct PassByValueDiag { // redundant_semicolon.rs #[derive(LintDiagnostic)] #[diag(lint_redundant_semicolons)] -pub struct RedundantSemicolonsDiag { +pub(crate) struct RedundantSemicolonsDiag { pub multiple: bool, #[suggestion(code = "", applicability = "maybe-incorrect")] pub suggestion: Span, } // traits.rs -pub struct DropTraitConstraintsDiag<'a> { +pub(crate) struct DropTraitConstraintsDiag<'a> { pub predicate: Clause<'a>, pub tcx: TyCtxt<'a>, pub def_id: DefId, @@ -1556,7 +1556,7 @@ impl<'a> LintDiagnostic<'a, ()> for DropTraitConstraintsDiag<'_> { } } -pub struct DropGlue<'a> { +pub(crate) struct DropGlue<'a> { pub tcx: TyCtxt<'a>, pub def_id: DefId, } @@ -1572,14 +1572,14 @@ impl<'a> LintDiagnostic<'a, ()> for DropGlue<'_> { // types.rs #[derive(LintDiagnostic)] #[diag(lint_range_endpoint_out_of_range)] -pub struct RangeEndpointOutOfRange<'a> { +pub(crate) struct RangeEndpointOutOfRange<'a> { pub ty: &'a str, #[subdiagnostic] pub sub: UseInclusiveRange<'a>, } #[derive(Subdiagnostic)] -pub enum UseInclusiveRange<'a> { +pub(crate) enum UseInclusiveRange<'a> { #[suggestion( lint_range_use_inclusive_range, code = "{start}..={literal}{suffix}", @@ -1605,7 +1605,7 @@ pub enum UseInclusiveRange<'a> { #[derive(LintDiagnostic)] #[diag(lint_overflowing_bin_hex)] -pub struct OverflowingBinHex<'a> { +pub(crate) struct OverflowingBinHex<'a> { pub ty: &'a str, pub lit: String, pub dec: u128, @@ -1618,7 +1618,7 @@ pub struct OverflowingBinHex<'a> { pub sign_bit_sub: Option>, } -pub enum OverflowingBinHexSign { +pub(crate) enum OverflowingBinHexSign { Positive, Negative, } @@ -1642,7 +1642,7 @@ impl Subdiagnostic for OverflowingBinHexSign { } #[derive(Subdiagnostic)] -pub enum OverflowingBinHexSub<'a> { +pub(crate) enum OverflowingBinHexSub<'a> { #[suggestion( lint_suggestion, code = "{sans_suffix}{suggestion_ty}", @@ -1664,7 +1664,7 @@ pub enum OverflowingBinHexSub<'a> { code = "{lit_no_suffix}{uint_ty} as {int_ty}", applicability = "maybe-incorrect" )] -pub struct OverflowingBinHexSignBitSub<'a> { +pub(crate) struct OverflowingBinHexSignBitSub<'a> { #[primary_span] pub span: Span, pub lit_no_suffix: &'a str, @@ -1676,7 +1676,7 @@ pub struct OverflowingBinHexSignBitSub<'a> { #[derive(LintDiagnostic)] #[diag(lint_overflowing_int)] #[note] -pub struct OverflowingInt<'a> { +pub(crate) struct OverflowingInt<'a> { pub ty: &'a str, pub lit: String, pub min: i128, @@ -1687,13 +1687,13 @@ pub struct OverflowingInt<'a> { #[derive(Subdiagnostic)] #[help(lint_help)] -pub struct OverflowingIntHelp<'a> { +pub(crate) struct OverflowingIntHelp<'a> { pub suggestion_ty: &'a str, } #[derive(LintDiagnostic)] #[diag(lint_only_cast_u8_to_char)] -pub struct OnlyCastu8ToChar { +pub(crate) struct OnlyCastu8ToChar { #[suggestion(code = "'\\u{{{literal:X}}}'", applicability = "machine-applicable")] pub span: Span, pub literal: u128, @@ -1702,7 +1702,7 @@ pub struct OnlyCastu8ToChar { #[derive(LintDiagnostic)] #[diag(lint_overflowing_uint)] #[note] -pub struct OverflowingUInt<'a> { +pub(crate) struct OverflowingUInt<'a> { pub ty: &'a str, pub lit: String, pub min: u128, @@ -1712,17 +1712,17 @@ pub struct OverflowingUInt<'a> { #[derive(LintDiagnostic)] #[diag(lint_overflowing_literal)] #[note] -pub struct OverflowingLiteral<'a> { +pub(crate) struct OverflowingLiteral<'a> { pub ty: &'a str, pub lit: String, } #[derive(LintDiagnostic)] #[diag(lint_unused_comparisons)] -pub struct UnusedComparisons; +pub(crate) struct UnusedComparisons; #[derive(LintDiagnostic)] -pub enum InvalidNanComparisons { +pub(crate) enum InvalidNanComparisons { #[diag(lint_invalid_nan_comparisons_eq_ne)] EqNe { #[subdiagnostic] @@ -1733,7 +1733,7 @@ pub enum InvalidNanComparisons { } #[derive(Subdiagnostic)] -pub enum InvalidNanComparisonsSuggestion { +pub(crate) enum InvalidNanComparisonsSuggestion { #[multipart_suggestion( lint_suggestion, style = "verbose", @@ -1752,7 +1752,7 @@ pub enum InvalidNanComparisonsSuggestion { } #[derive(LintDiagnostic)] -pub enum AmbiguousWidePointerComparisons<'a> { +pub(crate) enum AmbiguousWidePointerComparisons<'a> { #[diag(lint_ambiguous_wide_pointer_comparisons)] Spanful { #[subdiagnostic] @@ -1773,7 +1773,7 @@ pub enum AmbiguousWidePointerComparisons<'a> { // FIXME(#53934): make machine-applicable again applicability = "maybe-incorrect" )] -pub struct AmbiguousWidePointerComparisonsAddrMetadataSuggestion<'a> { +pub(crate) struct AmbiguousWidePointerComparisonsAddrMetadataSuggestion<'a> { pub ne: &'a str, pub deref_left: &'a str, pub deref_right: &'a str, @@ -1788,7 +1788,7 @@ pub struct AmbiguousWidePointerComparisonsAddrMetadataSuggestion<'a> { } #[derive(Subdiagnostic)] -pub enum AmbiguousWidePointerComparisonsAddrSuggestion<'a> { +pub(crate) enum AmbiguousWidePointerComparisonsAddrSuggestion<'a> { #[multipart_suggestion( lint_addr_suggestion, style = "verbose", @@ -1832,7 +1832,7 @@ pub enum AmbiguousWidePointerComparisonsAddrSuggestion<'a> { }, } -pub struct ImproperCTypes<'a> { +pub(crate) struct ImproperCTypes<'a> { pub ty: Ty<'a>, pub desc: &'a str, pub label: Span, @@ -1860,29 +1860,29 @@ impl<'a> LintDiagnostic<'a, ()> for ImproperCTypes<'_> { #[derive(LintDiagnostic)] #[diag(lint_variant_size_differences)] -pub struct VariantSizeDifferencesDiag { +pub(crate) struct VariantSizeDifferencesDiag { pub largest: u64, } #[derive(LintDiagnostic)] #[diag(lint_atomic_ordering_load)] #[help] -pub struct AtomicOrderingLoad; +pub(crate) struct AtomicOrderingLoad; #[derive(LintDiagnostic)] #[diag(lint_atomic_ordering_store)] #[help] -pub struct AtomicOrderingStore; +pub(crate) struct AtomicOrderingStore; #[derive(LintDiagnostic)] #[diag(lint_atomic_ordering_fence)] #[help] -pub struct AtomicOrderingFence; +pub(crate) struct AtomicOrderingFence; #[derive(LintDiagnostic)] #[diag(lint_atomic_ordering_invalid)] #[help] -pub struct InvalidAtomicOrderingDiag { +pub(crate) struct InvalidAtomicOrderingDiag { pub method: Symbol, #[label] pub fail_order_arg_span: Span, @@ -1891,7 +1891,7 @@ pub struct InvalidAtomicOrderingDiag { // unused.rs #[derive(LintDiagnostic)] #[diag(lint_unused_op)] -pub struct UnusedOp<'a> { +pub(crate) struct UnusedOp<'a> { pub op: &'a str, #[label] pub label: Span, @@ -1900,7 +1900,7 @@ pub struct UnusedOp<'a> { } #[derive(Subdiagnostic)] -pub enum UnusedOpSuggestion { +pub(crate) enum UnusedOpSuggestion { #[suggestion( lint_suggestion, style = "verbose", @@ -1922,7 +1922,7 @@ pub enum UnusedOpSuggestion { #[derive(LintDiagnostic)] #[diag(lint_unused_result)] -pub struct UnusedResult<'a> { +pub(crate) struct UnusedResult<'a> { pub ty: Ty<'a>, } @@ -1931,7 +1931,7 @@ pub struct UnusedResult<'a> { #[derive(LintDiagnostic)] #[diag(lint_unused_closure)] #[note] -pub struct UnusedClosure<'a> { +pub(crate) struct UnusedClosure<'a> { pub count: usize, pub pre: &'a str, pub post: &'a str, @@ -1942,7 +1942,7 @@ pub struct UnusedClosure<'a> { #[derive(LintDiagnostic)] #[diag(lint_unused_coroutine)] #[note] -pub struct UnusedCoroutine<'a> { +pub(crate) struct UnusedCoroutine<'a> { pub count: usize, pub pre: &'a str, pub post: &'a str, @@ -1950,7 +1950,7 @@ pub struct UnusedCoroutine<'a> { // FIXME(davidtwco): this isn't properly translatable because of the pre/post // strings -pub struct UnusedDef<'a, 'b> { +pub(crate) struct UnusedDef<'a, 'b> { pub pre: &'a str, pub post: &'a str, pub cx: &'a LateContext<'b>, @@ -1961,7 +1961,7 @@ pub struct UnusedDef<'a, 'b> { #[derive(Subdiagnostic)] -pub enum UnusedDefSuggestion { +pub(crate) enum UnusedDefSuggestion { #[suggestion( lint_suggestion, style = "verbose", @@ -2000,13 +2000,13 @@ impl<'a> LintDiagnostic<'a, ()> for UnusedDef<'_, '_> { #[derive(LintDiagnostic)] #[diag(lint_path_statement_drop)] -pub struct PathStatementDrop { +pub(crate) struct PathStatementDrop { #[subdiagnostic] pub sub: PathStatementDropSub, } #[derive(Subdiagnostic)] -pub enum PathStatementDropSub { +pub(crate) enum PathStatementDropSub { #[suggestion(lint_suggestion, code = "drop({snippet});", applicability = "machine-applicable")] Suggestion { #[primary_span] @@ -2022,11 +2022,11 @@ pub enum PathStatementDropSub { #[derive(LintDiagnostic)] #[diag(lint_path_statement_no_effect)] -pub struct PathStatementNoEffect; +pub(crate) struct PathStatementNoEffect; #[derive(LintDiagnostic)] #[diag(lint_unused_delim)] -pub struct UnusedDelim<'a> { +pub(crate) struct UnusedDelim<'a> { pub delim: &'static str, pub item: &'a str, #[subdiagnostic] @@ -2035,7 +2035,7 @@ pub struct UnusedDelim<'a> { #[derive(Subdiagnostic)] #[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] -pub struct UnusedDelimSuggestion { +pub(crate) struct UnusedDelimSuggestion { #[suggestion_part(code = "{start_replace}")] pub start_span: Span, pub start_replace: &'static str, @@ -2046,19 +2046,19 @@ pub struct UnusedDelimSuggestion { #[derive(LintDiagnostic)] #[diag(lint_unused_import_braces)] -pub struct UnusedImportBracesDiag { +pub(crate) struct UnusedImportBracesDiag { pub node: Symbol, } #[derive(LintDiagnostic)] #[diag(lint_unused_allocation)] -pub struct UnusedAllocationDiag; +pub(crate) struct UnusedAllocationDiag; #[derive(LintDiagnostic)] #[diag(lint_unused_allocation_mut)] -pub struct UnusedAllocationMutDiag; +pub(crate) struct UnusedAllocationMutDiag; -pub struct AsyncFnInTraitDiag { +pub(crate) struct AsyncFnInTraitDiag { pub sugg: Option>, } @@ -2074,13 +2074,13 @@ impl<'a> LintDiagnostic<'a, ()> for AsyncFnInTraitDiag { #[derive(LintDiagnostic)] #[diag(lint_unit_bindings)] -pub struct UnitBindingsDiag { +pub(crate) struct UnitBindingsDiag { #[label] pub label: Span, } #[derive(LintDiagnostic)] -pub enum InvalidAsmLabel { +pub(crate) enum InvalidAsmLabel { #[diag(lint_invalid_asm_label_named)] #[help] #[note] @@ -2110,7 +2110,7 @@ pub enum InvalidAsmLabel { } #[derive(Subdiagnostic)] -pub enum UnexpectedCfgCargoHelp { +pub(crate) enum UnexpectedCfgCargoHelp { #[help(lint_unexpected_cfg_add_cargo_feature)] #[help(lint_unexpected_cfg_add_cargo_toml_lint_cfg)] LintCfg { cargo_toml_lint_cfg: String }, @@ -2127,13 +2127,13 @@ impl UnexpectedCfgCargoHelp { ) } - pub fn lint_cfg(unescaped: &str) -> Self { + pub(crate) fn lint_cfg(unescaped: &str) -> Self { UnexpectedCfgCargoHelp::LintCfg { cargo_toml_lint_cfg: Self::cargo_toml_lint_cfg(unescaped), } } - pub fn lint_cfg_and_build_rs(unescaped: &str, escaped: &str) -> Self { + pub(crate) fn lint_cfg_and_build_rs(unescaped: &str, escaped: &str) -> Self { UnexpectedCfgCargoHelp::LintCfgAndBuildRs { cargo_toml_lint_cfg: Self::cargo_toml_lint_cfg(unescaped), build_rs_println: format!("println!(\"cargo::rustc-check-cfg={escaped}\");"), @@ -2143,19 +2143,19 @@ impl UnexpectedCfgCargoHelp { #[derive(Subdiagnostic)] #[help(lint_unexpected_cfg_add_cmdline_arg)] -pub struct UnexpectedCfgRustcHelp { +pub(crate) struct UnexpectedCfgRustcHelp { pub cmdline_arg: String, } impl UnexpectedCfgRustcHelp { - pub fn new(unescaped: &str) -> Self { + pub(crate) fn new(unescaped: &str) -> Self { Self { cmdline_arg: format!("--check-cfg={unescaped}") } } } #[derive(LintDiagnostic)] #[diag(lint_unexpected_cfg_name)] -pub struct UnexpectedCfgName { +pub(crate) struct UnexpectedCfgName { #[subdiagnostic] pub code_sugg: unexpected_cfg_name::CodeSuggestion, #[subdiagnostic] @@ -2164,13 +2164,13 @@ pub struct UnexpectedCfgName { pub name: Symbol, } -pub mod unexpected_cfg_name { +pub(crate) mod unexpected_cfg_name { use rustc_errors::DiagSymbolList; use rustc_macros::Subdiagnostic; use rustc_span::{Span, Symbol}; #[derive(Subdiagnostic)] - pub enum CodeSuggestion { + pub(crate) enum CodeSuggestion { #[help(lint_unexpected_cfg_define_features)] DefineFeatures, #[suggestion( @@ -2227,7 +2227,7 @@ pub mod unexpected_cfg_name { #[derive(Subdiagnostic)] #[help(lint_unexpected_cfg_name_expected_values)] - pub struct ExpectedValues { + pub(crate) struct ExpectedValues { pub best_match: Symbol, pub possibilities: DiagSymbolList, } @@ -2238,7 +2238,7 @@ pub mod unexpected_cfg_name { applicability = "maybe-incorrect", code = "{code}" )] - pub struct FoundWithSimilarValue { + pub(crate) struct FoundWithSimilarValue { #[primary_span] pub span: Span, pub code: String, @@ -2246,13 +2246,13 @@ pub mod unexpected_cfg_name { #[derive(Subdiagnostic)] #[help_once(lint_unexpected_cfg_name_expected_names)] - pub struct ExpectedNames { + pub(crate) struct ExpectedNames { pub possibilities: DiagSymbolList, pub and_more: usize, } #[derive(Subdiagnostic)] - pub enum InvocationHelp { + pub(crate) enum InvocationHelp { #[note(lint_unexpected_cfg_doc_cargo)] Cargo { #[subdiagnostic] @@ -2265,7 +2265,7 @@ pub mod unexpected_cfg_name { #[derive(LintDiagnostic)] #[diag(lint_unexpected_cfg_value)] -pub struct UnexpectedCfgValue { +pub(crate) struct UnexpectedCfgValue { #[subdiagnostic] pub code_sugg: unexpected_cfg_value::CodeSuggestion, #[subdiagnostic] @@ -2275,13 +2275,13 @@ pub struct UnexpectedCfgValue { pub value: String, } -pub mod unexpected_cfg_value { +pub(crate) mod unexpected_cfg_value { use rustc_errors::DiagSymbolList; use rustc_macros::Subdiagnostic; use rustc_span::{Span, Symbol}; #[derive(Subdiagnostic)] - pub enum CodeSuggestion { + pub(crate) enum CodeSuggestion { ChangeValue { #[subdiagnostic] expected_values: ExpectedValues, @@ -2305,7 +2305,7 @@ pub mod unexpected_cfg_value { } #[derive(Subdiagnostic)] - pub enum ChangeValueSuggestion { + pub(crate) enum ChangeValueSuggestion { #[suggestion( lint_unexpected_cfg_value_similar_name, code = r#""{best_match}""#, @@ -2334,7 +2334,7 @@ pub mod unexpected_cfg_value { code = "", applicability = "maybe-incorrect" )] - pub struct RemoveValueSuggestion { + pub(crate) struct RemoveValueSuggestion { #[primary_span] pub span: Span, } @@ -2345,14 +2345,14 @@ pub mod unexpected_cfg_value { code = "", applicability = "maybe-incorrect" )] - pub struct RemoveConditionSuggestion { + pub(crate) struct RemoveConditionSuggestion { #[primary_span] pub span: Span, } #[derive(Subdiagnostic)] #[note(lint_unexpected_cfg_value_expected_values)] - pub struct ExpectedValues { + pub(crate) struct ExpectedValues { pub name: Symbol, pub have_none_possibility: bool, pub possibilities: DiagSymbolList, @@ -2360,7 +2360,7 @@ pub mod unexpected_cfg_value { } #[derive(Subdiagnostic)] - pub enum InvocationHelp { + pub(crate) enum InvocationHelp { #[note(lint_unexpected_cfg_doc_cargo)] Cargo(#[subdiagnostic] Option), #[note(lint_unexpected_cfg_doc_rustc)] @@ -2368,7 +2368,7 @@ pub mod unexpected_cfg_value { } #[derive(Subdiagnostic)] - pub enum CargoHelp { + pub(crate) enum CargoHelp { #[help(lint_unexpected_cfg_value_add_feature)] AddFeature { value: Symbol, @@ -2383,7 +2383,7 @@ pub mod unexpected_cfg_value { #[diag(lint_unexpected_builtin_cfg)] #[note(lint_controlled_by)] #[note(lint_incoherent)] -pub struct UnexpectedBuiltinCfg { +pub(crate) struct UnexpectedBuiltinCfg { pub(crate) cfg: String, pub(crate) cfg_name: Symbol, pub(crate) controlled_by: &'static str, @@ -2392,15 +2392,15 @@ pub struct UnexpectedBuiltinCfg { #[derive(LintDiagnostic)] #[diag(lint_macro_use_deprecated)] #[help] -pub struct MacroUseDeprecated; +pub(crate) struct MacroUseDeprecated; #[derive(LintDiagnostic)] #[diag(lint_unused_macro_use)] -pub struct UnusedMacroUse; +pub(crate) struct UnusedMacroUse; #[derive(LintDiagnostic)] #[diag(lint_private_extern_crate_reexport, code = E0365)] -pub struct PrivateExternCrateReexport { +pub(crate) struct PrivateExternCrateReexport { pub ident: Ident, #[suggestion(code = "pub ", style = "verbose", applicability = "maybe-incorrect")] pub sugg: Span, @@ -2408,28 +2408,28 @@ pub struct PrivateExternCrateReexport { #[derive(LintDiagnostic)] #[diag(lint_unused_label)] -pub struct UnusedLabel; +pub(crate) struct UnusedLabel; #[derive(LintDiagnostic)] #[diag(lint_macro_is_private)] -pub struct MacroIsPrivate { +pub(crate) struct MacroIsPrivate { pub ident: Ident, } #[derive(LintDiagnostic)] #[diag(lint_unused_macro_definition)] -pub struct UnusedMacroDefinition { +pub(crate) struct UnusedMacroDefinition { pub name: Symbol, } #[derive(LintDiagnostic)] #[diag(lint_macro_rule_never_used)] -pub struct MacroRuleNeverUsed { +pub(crate) struct MacroRuleNeverUsed { pub n: usize, pub name: Symbol, } -pub struct UnstableFeature { +pub(crate) struct UnstableFeature { pub msg: DiagMessage, } @@ -2441,81 +2441,81 @@ impl<'a> LintDiagnostic<'a, ()> for UnstableFeature { #[derive(LintDiagnostic)] #[diag(lint_avoid_intel_syntax)] -pub struct AvoidIntelSyntax; +pub(crate) struct AvoidIntelSyntax; #[derive(LintDiagnostic)] #[diag(lint_avoid_att_syntax)] -pub struct AvoidAttSyntax; +pub(crate) struct AvoidAttSyntax; #[derive(LintDiagnostic)] #[diag(lint_incomplete_include)] -pub struct IncompleteInclude; +pub(crate) struct IncompleteInclude; #[derive(LintDiagnostic)] #[diag(lint_unnameable_test_items)] -pub struct UnnameableTestItems; +pub(crate) struct UnnameableTestItems; #[derive(LintDiagnostic)] #[diag(lint_duplicate_macro_attribute)] -pub struct DuplicateMacroAttribute; +pub(crate) struct DuplicateMacroAttribute; #[derive(LintDiagnostic)] #[diag(lint_cfg_attr_no_attributes)] -pub struct CfgAttrNoAttributes; +pub(crate) struct CfgAttrNoAttributes; #[derive(LintDiagnostic)] #[diag(lint_crate_type_in_cfg_attr_deprecated)] -pub struct CrateTypeInCfgAttr; +pub(crate) struct CrateTypeInCfgAttr; #[derive(LintDiagnostic)] #[diag(lint_crate_name_in_cfg_attr_deprecated)] -pub struct CrateNameInCfgAttr; +pub(crate) struct CrateNameInCfgAttr; #[derive(LintDiagnostic)] #[diag(lint_missing_fragment_specifier)] -pub struct MissingFragmentSpecifier; +pub(crate) struct MissingFragmentSpecifier; #[derive(LintDiagnostic)] #[diag(lint_metavariable_still_repeating)] -pub struct MetaVariableStillRepeating { +pub(crate) struct MetaVariableStillRepeating { pub name: MacroRulesNormalizedIdent, } #[derive(LintDiagnostic)] #[diag(lint_metavariable_wrong_operator)] -pub struct MetaVariableWrongOperator; +pub(crate) struct MetaVariableWrongOperator; #[derive(LintDiagnostic)] #[diag(lint_duplicate_matcher_binding)] -pub struct DuplicateMatcherBinding; +pub(crate) struct DuplicateMatcherBinding; #[derive(LintDiagnostic)] #[diag(lint_unknown_macro_variable)] -pub struct UnknownMacroVariable { +pub(crate) struct UnknownMacroVariable { pub name: MacroRulesNormalizedIdent, } #[derive(LintDiagnostic)] #[diag(lint_unused_crate_dependency)] #[help] -pub struct UnusedCrateDependency { +pub(crate) struct UnusedCrateDependency { pub extern_crate: Symbol, pub local_crate: Symbol, } #[derive(LintDiagnostic)] #[diag(lint_wasm_c_abi)] -pub struct WasmCAbi; +pub(crate) struct WasmCAbi; #[derive(LintDiagnostic)] #[diag(lint_ill_formed_attribute_input)] -pub struct IllFormedAttributeInput { +pub(crate) struct IllFormedAttributeInput { pub num_suggestions: usize, pub suggestions: DiagArgValue, } #[derive(LintDiagnostic)] -pub enum InnerAttributeUnstable { +pub(crate) enum InnerAttributeUnstable { #[diag(lint_inner_macro_attribute_unstable)] InnerMacroAttribute, #[diag(lint_custom_inner_attribute_unstable)] @@ -2524,7 +2524,7 @@ pub enum InnerAttributeUnstable { #[derive(LintDiagnostic)] #[diag(lint_unknown_diagnostic_attribute)] -pub struct UnknownDiagnosticAttribute { +pub(crate) struct UnknownDiagnosticAttribute { #[subdiagnostic] pub typo: Option, } @@ -2536,7 +2536,7 @@ pub struct UnknownDiagnosticAttribute { code = "{typo_name}", applicability = "machine-applicable" )] -pub struct UnknownDiagnosticAttributeTypoSugg { +pub(crate) struct UnknownDiagnosticAttributeTypoSugg { #[primary_span] pub span: Span, pub typo_name: Symbol, @@ -2545,7 +2545,7 @@ pub struct UnknownDiagnosticAttributeTypoSugg { #[derive(LintDiagnostic)] #[diag(lint_unicode_text_flow)] #[note] -pub struct UnicodeTextFlow { +pub(crate) struct UnicodeTextFlow { #[label] pub comment_span: Span, #[subdiagnostic] @@ -2558,7 +2558,7 @@ pub struct UnicodeTextFlow { #[derive(Subdiagnostic)] #[label(lint_label_comment_char)] -pub struct UnicodeCharNoteSub { +pub(crate) struct UnicodeCharNoteSub { #[primary_span] pub span: Span, pub c_debug: String, @@ -2566,21 +2566,21 @@ pub struct UnicodeCharNoteSub { #[derive(Subdiagnostic)] #[multipart_suggestion(lint_suggestion, applicability = "machine-applicable", style = "hidden")] -pub struct UnicodeTextFlowSuggestion { +pub(crate) struct UnicodeTextFlowSuggestion { #[suggestion_part(code = "")] pub spans: Vec, } #[derive(LintDiagnostic)] #[diag(lint_abs_path_with_module)] -pub struct AbsPathWithModule { +pub(crate) struct AbsPathWithModule { #[subdiagnostic] pub sugg: AbsPathWithModuleSugg, } #[derive(Subdiagnostic)] #[suggestion(lint_suggestion, code = "{replacement}")] -pub struct AbsPathWithModuleSugg { +pub(crate) struct AbsPathWithModuleSugg { #[primary_span] pub span: Span, #[applicability] @@ -2590,7 +2590,7 @@ pub struct AbsPathWithModuleSugg { #[derive(LintDiagnostic)] #[diag(lint_proc_macro_derive_resolution_fallback)] -pub struct ProcMacroDeriveResolutionFallback { +pub(crate) struct ProcMacroDeriveResolutionFallback { #[label] pub span: Span, pub ns: Namespace, @@ -2599,28 +2599,28 @@ pub struct ProcMacroDeriveResolutionFallback { #[derive(LintDiagnostic)] #[diag(lint_macro_expanded_macro_exports_accessed_by_absolute_paths)] -pub struct MacroExpandedMacroExportsAccessedByAbsolutePaths { +pub(crate) struct MacroExpandedMacroExportsAccessedByAbsolutePaths { #[note] pub definition: Span, } #[derive(LintDiagnostic)] #[diag(lint_hidden_lifetime_parameters)] -pub struct ElidedLifetimesInPaths { +pub(crate) struct ElidedLifetimesInPaths { #[subdiagnostic] pub subdiag: ElidedLifetimeInPathSubdiag, } #[derive(LintDiagnostic)] #[diag(lint_invalid_crate_type_value)] -pub struct UnknownCrateTypes { +pub(crate) struct UnknownCrateTypes { #[subdiagnostic] pub sugg: Option, } #[derive(Subdiagnostic)] #[suggestion(lint_suggestion, code = r#""{candidate}""#, applicability = "maybe-incorrect")] -pub struct UnknownCrateTypesSub { +pub(crate) struct UnknownCrateTypesSub { #[primary_span] pub span: Span, pub candidate: Symbol, @@ -2628,7 +2628,7 @@ pub struct UnknownCrateTypesSub { #[derive(LintDiagnostic)] #[diag(lint_unused_imports)] -pub struct UnusedImports { +pub(crate) struct UnusedImports { #[subdiagnostic] pub sugg: UnusedImportsSugg, #[help] @@ -2639,7 +2639,7 @@ pub struct UnusedImports { } #[derive(Subdiagnostic)] -pub enum UnusedImportsSugg { +pub(crate) enum UnusedImportsSugg { #[suggestion( lint_suggestion_remove_whole_use, applicability = "machine-applicable", @@ -2664,7 +2664,7 @@ pub enum UnusedImportsSugg { #[derive(LintDiagnostic)] #[diag(lint_redundant_import)] -pub struct RedundantImport { +pub(crate) struct RedundantImport { #[subdiagnostic] pub subs: Vec, @@ -2672,7 +2672,7 @@ pub struct RedundantImport { } #[derive(Subdiagnostic)] -pub enum RedundantImportSub { +pub(crate) enum RedundantImportSub { #[label(lint_label_imported_here)] ImportedHere(#[primary_span] Span), #[label(lint_label_defined_here)] @@ -2686,13 +2686,13 @@ pub enum RedundantImportSub { #[derive(LintDiagnostic)] #[diag(lint_unused_doc_comment)] #[help] -pub struct UnusedDocComment { +pub(crate) struct UnusedDocComment { #[label] pub span: Span, } #[derive(LintDiagnostic)] -pub enum PatternsInFnsWithoutBody { +pub(crate) enum PatternsInFnsWithoutBody { #[diag(lint_pattern_in_foreign)] Foreign { #[subdiagnostic] @@ -2707,7 +2707,7 @@ pub enum PatternsInFnsWithoutBody { #[derive(Subdiagnostic)] #[suggestion(lint_remove_mut_from_pattern, code = "{ident}", applicability = "machine-applicable")] -pub struct PatternsInFnsWithoutBodySub { +pub(crate) struct PatternsInFnsWithoutBodySub { #[primary_span] pub span: Span, @@ -2717,7 +2717,7 @@ pub struct PatternsInFnsWithoutBodySub { #[derive(LintDiagnostic)] #[diag(lint_extern_without_abi)] #[help] -pub struct MissingAbi { +pub(crate) struct MissingAbi { #[label] pub span: Span, @@ -2726,14 +2726,14 @@ pub struct MissingAbi { #[derive(LintDiagnostic)] #[diag(lint_legacy_derive_helpers)] -pub struct LegacyDeriveHelpers { +pub(crate) struct LegacyDeriveHelpers { #[label] pub span: Span, } #[derive(LintDiagnostic)] #[diag(lint_or_patterns_back_compat)] -pub struct OrPatternsBackCompat { +pub(crate) struct OrPatternsBackCompat { #[suggestion(code = "{suggestion}", applicability = "machine-applicable")] pub span: Span, pub suggestion: String, @@ -2741,7 +2741,7 @@ pub struct OrPatternsBackCompat { #[derive(LintDiagnostic)] #[diag(lint_reserved_prefix)] -pub struct ReservedPrefix { +pub(crate) struct ReservedPrefix { #[label] pub label: Span, #[suggestion(code = " ", applicability = "machine-applicable")] @@ -2752,7 +2752,7 @@ pub struct ReservedPrefix { #[derive(LintDiagnostic)] #[diag(lint_unused_builtin_attribute)] -pub struct UnusedBuiltinAttribute { +pub(crate) struct UnusedBuiltinAttribute { #[note] pub invoc_span: Span, @@ -2762,7 +2762,7 @@ pub struct UnusedBuiltinAttribute { #[derive(LintDiagnostic)] #[diag(lint_trailing_semi_macro)] -pub struct TrailingMacro { +pub(crate) struct TrailingMacro { #[note(lint_note1)] #[note(lint_note2)] pub is_trailing: bool, @@ -2772,14 +2772,14 @@ pub struct TrailingMacro { #[derive(LintDiagnostic)] #[diag(lint_break_with_label_and_loop)] -pub struct BreakWithLabelAndLoop { +pub(crate) struct BreakWithLabelAndLoop { #[subdiagnostic] pub sub: BreakWithLabelAndLoopSub, } #[derive(Subdiagnostic)] #[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] -pub struct BreakWithLabelAndLoopSub { +pub(crate) struct BreakWithLabelAndLoopSub { #[suggestion_part(code = "(")] pub left: Span, #[suggestion_part(code = ")")] @@ -2789,13 +2789,13 @@ pub struct BreakWithLabelAndLoopSub { #[derive(LintDiagnostic)] #[diag(lint_deprecated_where_clause_location)] #[note] -pub struct DeprecatedWhereClauseLocation { +pub(crate) struct DeprecatedWhereClauseLocation { #[subdiagnostic] pub suggestion: DeprecatedWhereClauseLocationSugg, } #[derive(Subdiagnostic)] -pub enum DeprecatedWhereClauseLocationSugg { +pub(crate) enum DeprecatedWhereClauseLocationSugg { #[multipart_suggestion(lint_suggestion_move_to_end, applicability = "machine-applicable")] MoveToEnd { #[suggestion_part(code = "")] @@ -2814,14 +2814,14 @@ pub enum DeprecatedWhereClauseLocationSugg { #[derive(LintDiagnostic)] #[diag(lint_missing_unsafe_on_extern)] -pub struct MissingUnsafeOnExtern { +pub(crate) struct MissingUnsafeOnExtern { #[suggestion(code = "unsafe ", applicability = "machine-applicable")] pub suggestion: Span, } #[derive(LintDiagnostic)] #[diag(lint_single_use_lifetime)] -pub struct SingleUseLifetime { +pub(crate) struct SingleUseLifetime { #[label(lint_label_param)] pub param_span: Span, #[label(lint_label_use)] @@ -2834,7 +2834,7 @@ pub struct SingleUseLifetime { #[derive(Subdiagnostic)] #[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] -pub struct SingleUseLifetimeSugg { +pub(crate) struct SingleUseLifetimeSugg { #[suggestion_part(code = "")] pub deletion_span: Option, #[suggestion_part(code = "{replace_lt}")] @@ -2845,7 +2845,7 @@ pub struct SingleUseLifetimeSugg { #[derive(LintDiagnostic)] #[diag(lint_unused_lifetime)] -pub struct UnusedLifetime { +pub(crate) struct UnusedLifetime { #[suggestion(code = "", applicability = "machine-applicable")] pub deletion_span: Option, @@ -2854,7 +2854,7 @@ pub struct UnusedLifetime { #[derive(LintDiagnostic)] #[diag(lint_named_argument_used_positionally)] -pub struct NamedArgumentUsedPositionally { +pub(crate) struct NamedArgumentUsedPositionally { #[label(lint_label_named_arg)] pub named_arg_sp: Span, #[label(lint_label_position_arg)] @@ -2869,21 +2869,21 @@ pub struct NamedArgumentUsedPositionally { #[derive(LintDiagnostic)] #[diag(lint_byte_slice_in_packed_struct_with_derive)] #[help] -pub struct ByteSliceInPackedStructWithDerive { +pub(crate) struct ByteSliceInPackedStructWithDerive { // FIXME: make this translatable pub ty: String, } #[derive(LintDiagnostic)] #[diag(lint_unused_extern_crate)] -pub struct UnusedExternCrate { +pub(crate) struct UnusedExternCrate { #[suggestion(code = "", applicability = "machine-applicable")] pub removal_span: Span, } #[derive(LintDiagnostic)] #[diag(lint_extern_crate_not_idiomatic)] -pub struct ExternCrateNotIdiomatic { +pub(crate) struct ExternCrateNotIdiomatic { #[suggestion(style = "verbose", code = "{code}", applicability = "machine-applicable")] pub span: Span, @@ -2891,7 +2891,7 @@ pub struct ExternCrateNotIdiomatic { } // FIXME: make this translatable -pub struct AmbiguousGlobImports { +pub(crate) struct AmbiguousGlobImports { pub ambiguity: AmbiguityErrorDiag, } @@ -2904,7 +2904,7 @@ impl<'a, G: EmissionGuarantee> LintDiagnostic<'a, G> for AmbiguousGlobImports { #[derive(LintDiagnostic)] #[diag(lint_ambiguous_glob_reexport)] -pub struct AmbiguousGlobReexports { +pub(crate) struct AmbiguousGlobReexports { #[label(lint_label_first_reexport)] pub first_reexport: Span, #[label(lint_label_duplicate_reexport)] @@ -2917,7 +2917,7 @@ pub struct AmbiguousGlobReexports { #[derive(LintDiagnostic)] #[diag(lint_hidden_glob_reexport)] -pub struct HiddenGlobReexports { +pub(crate) struct HiddenGlobReexports { #[note(lint_note_glob_reexport)] pub glob_reexport: Span, #[note(lint_note_private_item)] @@ -2930,14 +2930,14 @@ pub struct HiddenGlobReexports { #[derive(LintDiagnostic)] #[diag(lint_unnecessary_qualification)] -pub struct UnusedQualifications { +pub(crate) struct UnusedQualifications { #[suggestion(style = "verbose", code = "", applicability = "machine-applicable")] pub removal_span: Span, } #[derive(LintDiagnostic)] #[diag(lint_associated_const_elided_lifetime)] -pub struct AssociatedConstElidedLifetime { +pub(crate) struct AssociatedConstElidedLifetime { #[suggestion(style = "verbose", code = "{code}", applicability = "machine-applicable")] pub span: Span, @@ -2949,7 +2949,7 @@ pub struct AssociatedConstElidedLifetime { #[derive(LintDiagnostic)] #[diag(lint_redundant_import_visibility)] -pub struct RedundantImportVisibility { +pub(crate) struct RedundantImportVisibility { #[note] pub span: Span, #[help] @@ -2961,7 +2961,7 @@ pub struct RedundantImportVisibility { #[derive(LintDiagnostic)] #[diag(lint_unsafe_attr_outside_unsafe)] -pub struct UnsafeAttrOutsideUnsafe { +pub(crate) struct UnsafeAttrOutsideUnsafe { #[label] pub span: Span, #[subdiagnostic] @@ -2973,7 +2973,7 @@ pub struct UnsafeAttrOutsideUnsafe { lint_unsafe_attr_outside_unsafe_suggestion, applicability = "machine-applicable" )] -pub struct UnsafeAttrOutsideUnsafeSuggestion { +pub(crate) struct UnsafeAttrOutsideUnsafeSuggestion { #[suggestion_part(code = "unsafe(")] pub left: Span, #[suggestion_part(code = ")")] @@ -2983,6 +2983,6 @@ pub struct UnsafeAttrOutsideUnsafeSuggestion { #[derive(LintDiagnostic)] #[diag(lint_out_of_scope_macro_calls)] #[help] -pub struct OutOfScopeMacroCalls { +pub(crate) struct OutOfScopeMacroCalls { pub path: String, } diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index 5ad677995da..13a3c741fe3 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -55,7 +55,7 @@ declare_lint! { } #[derive(Default)] -pub struct NonLocalDefinitions { +pub(crate) struct NonLocalDefinitions { body_depth: u32, } diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index d7fd41c0ad7..d81052b5e24 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -17,13 +17,13 @@ use crate::lints::{ use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; #[derive(PartialEq)] -pub enum MethodLateContext { +pub(crate) enum MethodLateContext { TraitAutoImpl, TraitImpl, PlainImpl, } -pub fn method_context(cx: &LateContext<'_>, id: LocalDefId) -> MethodLateContext { +pub(crate) fn method_context(cx: &LateContext<'_>, id: LocalDefId) -> MethodLateContext { let item = cx.tcx.associated_item(id); match item.container { ty::TraitContainer => MethodLateContext::TraitAutoImpl, diff --git a/compiler/rustc_lint/src/reference_casting.rs b/compiler/rustc_lint/src/reference_casting.rs index 5e8c39c0023..45d97403d60 100644 --- a/compiler/rustc_lint/src/reference_casting.rs +++ b/compiler/rustc_lint/src/reference_casting.rs @@ -54,8 +54,6 @@ impl<'tcx> LateLintPass<'tcx> for InvalidReferenceCasting { && let Some(ty_has_interior_mutability) = is_cast_from_ref_to_mut_ptr(cx, init, &mut peel_casts) { - let ty_has_interior_mutability = ty_has_interior_mutability.then_some(()); - cx.emit_span_lint( INVALID_REFERENCE_CASTING, expr.span, diff --git a/compiler/rustc_lint/src/shadowed_into_iter.rs b/compiler/rustc_lint/src/shadowed_into_iter.rs index 4fe35a6a0a3..bb9c7d85c2e 100644 --- a/compiler/rustc_lint/src/shadowed_into_iter.rs +++ b/compiler/rustc_lint/src/shadowed_into_iter.rs @@ -65,7 +65,7 @@ declare_lint! { } #[derive(Copy, Clone)] -pub struct ShadowedIntoIter; +pub(crate) struct ShadowedIntoIter; impl_lint_pass!(ShadowedIntoIter => [ARRAY_INTO_ITER, BOXED_SLICE_INTO_ITER]); diff --git a/compiler/rustc_lint/src/tail_expr_drop_order.rs b/compiler/rustc_lint/src/tail_expr_drop_order.rs new file mode 100644 index 00000000000..f9ecc8c9806 --- /dev/null +++ b/compiler/rustc_lint/src/tail_expr_drop_order.rs @@ -0,0 +1,306 @@ +use std::mem::swap; + +use rustc_ast::UnOp; +use rustc_hir::def::Res; +use rustc_hir::intravisit::{self, Visitor}; +use rustc_hir::{self as hir, Block, Expr, ExprKind, LetStmt, Pat, PatKind, QPath, StmtKind}; +use rustc_macros::LintDiagnostic; +use rustc_middle::ty; +use rustc_session::lint::FutureIncompatibilityReason; +use rustc_session::{declare_lint, declare_lint_pass}; +use rustc_span::edition::Edition; +use rustc_span::Span; + +use crate::{LateContext, LateLintPass}; + +declare_lint! { + /// The `tail_expr_drop_order` lint looks for those values generated at the tail expression location, that of type + /// with a significant `Drop` implementation, such as locks. + /// In case there are also local variables of type with significant `Drop` implementation as well, + /// this lint warns you of a potential transposition in the drop order. + /// Your discretion on the new drop order introduced by Edition 2024 is required. + /// + /// ### Example + /// ```rust,edition2024 + /// #![feature(shorter_tail_lifetimes)] + /// #![warn(tail_expr_drop_order)] + /// struct Droppy(i32); + /// impl Droppy { + /// fn get(&self) -> i32 { + /// self.0 + /// } + /// } + /// impl Drop for Droppy { + /// fn drop(&mut self) { + /// // This is a custom destructor and it induces side-effects that is observable + /// // especially when the drop order at a tail expression changes. + /// println!("loud drop {}", self.0); + /// } + /// } + /// fn edition_2024() -> i32 { + /// let another_droppy = Droppy(0); + /// Droppy(1).get() + /// } + /// fn main() { + /// edition_2024(); + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// In tail expression of blocks or function bodies, + /// values of type with significant `Drop` implementation has an ill-specified drop order + /// before Edition 2024 so that they are dropped only after dropping local variables. + /// Edition 2024 introduces a new rule with drop orders for them, + /// so that they are dropped first before dropping local variables. + /// + /// A significant `Drop::drop` destructor here refers to an explicit, arbitrary + /// implementation of the `Drop` trait on the type, with exceptions including `Vec`, + /// `Box`, `Rc`, `BTreeMap` and `HashMap` that are marked by the compiler otherwise + /// so long that the generic types have no significant destructor recursively. + /// In other words, a type has a significant drop destructor when it has a `Drop` implementation + /// or its destructor invokes a significant destructor on a type. + /// Since we cannot completely reason about the change by just inspecting the existence of + /// a significant destructor, this lint remains only a suggestion and is set to `allow` by default. + /// + /// This lint only points out the issue with `Droppy`, which will be dropped before `another_droppy` + /// does in Edition 2024. + /// No fix will be proposed by this lint. + /// However, the most probable fix is to hoist `Droppy` into its own local variable binding. + /// ```rust + /// struct Droppy(i32); + /// impl Droppy { + /// fn get(&self) -> i32 { + /// self.0 + /// } + /// } + /// fn edition_2024() -> i32 { + /// let value = Droppy(0); + /// let another_droppy = Droppy(1); + /// value.get() + /// } + /// ``` + pub TAIL_EXPR_DROP_ORDER, + Allow, + "Detect and warn on significant change in drop order in tail expression location", + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2024), + reference: "issue #123739 ", + }; +} + +declare_lint_pass!(TailExprDropOrder => [TAIL_EXPR_DROP_ORDER]); + +impl TailExprDropOrder { + fn check_fn_or_closure<'tcx>( + cx: &LateContext<'tcx>, + fn_kind: hir::intravisit::FnKind<'tcx>, + body: &'tcx hir::Body<'tcx>, + def_id: rustc_span::def_id::LocalDefId, + ) { + let mut locals = vec![]; + if matches!(fn_kind, hir::intravisit::FnKind::Closure) { + for &capture in cx.tcx.closure_captures(def_id) { + if matches!(capture.info.capture_kind, ty::UpvarCapture::ByValue) + && capture.place.ty().has_significant_drop(cx.tcx, cx.param_env) + { + locals.push(capture.var_ident.span); + } + } + } + for param in body.params { + if cx + .typeck_results() + .node_type(param.hir_id) + .has_significant_drop(cx.tcx, cx.param_env) + { + locals.push(param.span); + } + } + if let hir::ExprKind::Block(block, _) = body.value.kind { + LintVisitor { cx, locals }.check_block_inner(block); + } else { + LintTailExpr { cx, locals: &locals, is_root_tail_expr: true }.visit_expr(body.value); + } + } +} + +impl<'tcx> LateLintPass<'tcx> for TailExprDropOrder { + fn check_fn( + &mut self, + cx: &LateContext<'tcx>, + fn_kind: hir::intravisit::FnKind<'tcx>, + _: &'tcx hir::FnDecl<'tcx>, + body: &'tcx hir::Body<'tcx>, + _: Span, + def_id: rustc_span::def_id::LocalDefId, + ) { + if cx.tcx.sess.at_least_rust_2024() && cx.tcx.features().shorter_tail_lifetimes { + Self::check_fn_or_closure(cx, fn_kind, body, def_id); + } + } +} + +struct LintVisitor<'tcx, 'a> { + cx: &'a LateContext<'tcx>, + // We only record locals that have significant drops + locals: Vec, +} + +struct LocalCollector<'tcx, 'a> { + cx: &'a LateContext<'tcx>, + locals: &'a mut Vec, +} + +impl<'tcx, 'a> Visitor<'tcx> for LocalCollector<'tcx, 'a> { + type Result = (); + fn visit_pat(&mut self, pat: &'tcx Pat<'tcx>) { + if let PatKind::Binding(_binding_mode, id, ident, pat) = pat.kind { + let ty = self.cx.typeck_results().node_type(id); + if ty.has_significant_drop(self.cx.tcx, self.cx.param_env) { + self.locals.push(ident.span); + } + if let Some(pat) = pat { + self.visit_pat(pat); + } + } else { + intravisit::walk_pat(self, pat); + } + } +} + +impl<'tcx, 'a> Visitor<'tcx> for LintVisitor<'tcx, 'a> { + fn visit_block(&mut self, block: &'tcx Block<'tcx>) { + let mut locals = <_>::default(); + swap(&mut locals, &mut self.locals); + self.check_block_inner(block); + swap(&mut locals, &mut self.locals); + } + fn visit_local(&mut self, local: &'tcx LetStmt<'tcx>) { + LocalCollector { cx: self.cx, locals: &mut self.locals }.visit_local(local); + } +} + +impl<'tcx, 'a> LintVisitor<'tcx, 'a> { + fn check_block_inner(&mut self, block: &Block<'tcx>) { + if !block.span.at_least_rust_2024() { + // We only lint for Edition 2024 onwards + return; + } + let Some(tail_expr) = block.expr else { return }; + for stmt in block.stmts { + match stmt.kind { + StmtKind::Let(let_stmt) => self.visit_local(let_stmt), + StmtKind::Item(_) => {} + StmtKind::Expr(e) | StmtKind::Semi(e) => self.visit_expr(e), + } + } + if self.locals.is_empty() { + return; + } + LintTailExpr { cx: self.cx, locals: &self.locals, is_root_tail_expr: true } + .visit_expr(tail_expr); + } +} + +struct LintTailExpr<'tcx, 'a> { + cx: &'a LateContext<'tcx>, + is_root_tail_expr: bool, + locals: &'a [Span], +} + +impl<'tcx, 'a> LintTailExpr<'tcx, 'a> { + fn expr_eventually_point_into_local(mut expr: &Expr<'tcx>) -> bool { + loop { + match expr.kind { + ExprKind::Index(access, _, _) | ExprKind::Field(access, _) => expr = access, + ExprKind::AddrOf(_, _, referee) | ExprKind::Unary(UnOp::Deref, referee) => { + expr = referee + } + ExprKind::Path(_) + if let ExprKind::Path(QPath::Resolved(_, path)) = expr.kind + && let [local, ..] = path.segments + && let Res::Local(_) = local.res => + { + return true; + } + _ => return false, + } + } + } + + fn expr_generates_nonlocal_droppy_value(&self, expr: &Expr<'tcx>) -> bool { + if Self::expr_eventually_point_into_local(expr) { + return false; + } + self.cx.typeck_results().expr_ty(expr).has_significant_drop(self.cx.tcx, self.cx.param_env) + } +} + +impl<'tcx, 'a> Visitor<'tcx> for LintTailExpr<'tcx, 'a> { + fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { + if self.is_root_tail_expr { + self.is_root_tail_expr = false; + } else if self.expr_generates_nonlocal_droppy_value(expr) { + self.cx.tcx.emit_node_span_lint( + TAIL_EXPR_DROP_ORDER, + expr.hir_id, + expr.span, + TailExprDropOrderLint { spans: self.locals.to_vec() }, + ); + return; + } + match expr.kind { + ExprKind::Match(scrutinee, _, _) => self.visit_expr(scrutinee), + + ExprKind::ConstBlock(_) + | ExprKind::Array(_) + | ExprKind::Break(_, _) + | ExprKind::Continue(_) + | ExprKind::Ret(_) + | ExprKind::Become(_) + | ExprKind::Yield(_, _) + | ExprKind::InlineAsm(_) + | ExprKind::If(_, _, _) + | ExprKind::Loop(_, _, _, _) + | ExprKind::Closure(_) + | ExprKind::DropTemps(_) + | ExprKind::OffsetOf(_, _) + | ExprKind::Assign(_, _, _) + | ExprKind::AssignOp(_, _, _) + | ExprKind::Lit(_) + | ExprKind::Err(_) => {} + + ExprKind::MethodCall(_, _, _, _) + | ExprKind::Call(_, _) + | ExprKind::Type(_, _) + | ExprKind::Tup(_) + | ExprKind::Binary(_, _, _) + | ExprKind::Unary(_, _) + | ExprKind::Path(_) + | ExprKind::Let(_) + | ExprKind::Cast(_, _) + | ExprKind::Field(_, _) + | ExprKind::Index(_, _, _) + | ExprKind::AddrOf(_, _, _) + | ExprKind::Struct(_, _, _) + | ExprKind::Repeat(_, _) => intravisit::walk_expr(self, expr), + + ExprKind::Block(_, _) => { + // We do not lint further because the drop order stays the same inside the block + } + } + } + fn visit_block(&mut self, block: &'tcx Block<'tcx>) { + LintVisitor { cx: self.cx, locals: <_>::default() }.check_block_inner(block); + } +} + +#[derive(LintDiagnostic)] +#[diag(lint_tail_expr_drop_order)] +struct TailExprDropOrderLint { + #[label] + pub spans: Vec, +} diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs index fea96b5366e..a0fe4b5af74 100644 --- a/compiler/rustc_lint/src/traits.rs +++ b/compiler/rustc_lint/src/traits.rs @@ -114,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints { let hir::TyKind::TraitObject(bounds, _lifetime, _syntax) = &ty.kind else { return }; for (bound, modifier) in &bounds[..] { let def_id = bound.trait_ref.trait_def_id(); - if cx.tcx.lang_items().drop_trait() == def_id + if def_id.is_some_and(|def_id| cx.tcx.is_lang_item(def_id, LangItem::Drop)) && *modifier != hir::TraitBoundModifier::Maybe { let Some(def_id) = cx.tcx.get_diagnostic_item(sym::needs_drop) else { return }; diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 51896da893c..f2f7c0eaa4d 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -165,7 +165,7 @@ declare_lint! { } #[derive(Copy, Clone)] -pub struct TypeLimits { +pub(crate) struct TypeLimits { /// Id of the last visited negated expression negated_expr_id: Option, /// Span of the last visited negated expression @@ -180,7 +180,7 @@ impl_lint_pass!(TypeLimits => [ ]); impl TypeLimits { - pub fn new() -> TypeLimits { + pub(crate) fn new() -> TypeLimits { TypeLimits { negated_expr_id: None, negated_expr_span: None } } } @@ -985,6 +985,14 @@ struct ImproperCTypesVisitor<'a, 'tcx> { mode: CItemKind, } +/// Accumulator for recursive ffi type checking +struct CTypesVisitorState<'tcx> { + cache: FxHashSet>, + /// The original type being checked, before we recursed + /// to any other types it contains. + base_ty: Ty<'tcx>, +} + enum FfiResult<'tcx> { FfiSafe, FfiPhantom(Ty<'tcx>), @@ -1000,7 +1008,7 @@ pub(crate) fn nonnull_optimization_guaranteed<'tcx>( /// `repr(transparent)` structs can have a single non-1-ZST field, this function returns that /// field. -pub fn transparent_newtype_field<'a, 'tcx>( +pub(crate) fn transparent_newtype_field<'a, 'tcx>( tcx: TyCtxt<'tcx>, variant: &'a ty::VariantDef, ) -> Option<&'a ty::FieldDef> { @@ -1022,7 +1030,7 @@ fn ty_is_known_nonnull<'tcx>( let ty = tcx.try_normalize_erasing_regions(param_env, ty).unwrap_or(ty); match ty.kind() { - ty::FnPtr(_) => true, + ty::FnPtr(..) => true, ty::Ref(..) => true, ty::Adt(def, _) if def.is_box() && matches!(mode, CItemKind::Definition) => true, ty::Adt(def, args) if def.repr().transparent() && !def.is_union() => { @@ -1213,7 +1221,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { /// Checks if the given field's type is "ffi-safe". fn check_field_type_for_ffi( &self, - cache: &mut FxHashSet>, + acc: &mut CTypesVisitorState<'tcx>, field: &ty::FieldDef, args: GenericArgsRef<'tcx>, ) -> FfiResult<'tcx> { @@ -1223,13 +1231,13 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { .tcx .try_normalize_erasing_regions(self.cx.param_env, field_ty) .unwrap_or(field_ty); - self.check_type_for_ffi(cache, field_ty) + self.check_type_for_ffi(acc, field_ty) } /// Checks if the given `VariantDef`'s field types are "ffi-safe". fn check_variant_for_ffi( &self, - cache: &mut FxHashSet>, + acc: &mut CTypesVisitorState<'tcx>, ty: Ty<'tcx>, def: ty::AdtDef<'tcx>, variant: &ty::VariantDef, @@ -1239,7 +1247,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { let transparent_with_all_zst_fields = if def.repr().transparent() { if let Some(field) = transparent_newtype_field(self.cx.tcx, variant) { // Transparent newtypes have at most one non-ZST field which needs to be checked.. - match self.check_field_type_for_ffi(cache, field, args) { + match self.check_field_type_for_ffi(acc, field, args) { FfiUnsafe { ty, .. } if ty.is_unit() => (), r => return r, } @@ -1257,7 +1265,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { // We can't completely trust `repr(C)` markings, so make sure the fields are actually safe. let mut all_phantom = !variant.fields.is_empty(); for field in &variant.fields { - all_phantom &= match self.check_field_type_for_ffi(cache, field, args) { + all_phantom &= match self.check_field_type_for_ffi(acc, field, args) { FfiSafe => false, // `()` fields are FFI-safe! FfiUnsafe { ty, .. } if ty.is_unit() => false, @@ -1277,7 +1285,11 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { /// Checks if the given type is "ffi-safe" (has a stable, well-defined /// representation which can be exported to C code). - fn check_type_for_ffi(&self, cache: &mut FxHashSet>, ty: Ty<'tcx>) -> FfiResult<'tcx> { + fn check_type_for_ffi( + &self, + acc: &mut CTypesVisitorState<'tcx>, + ty: Ty<'tcx>, + ) -> FfiResult<'tcx> { use FfiResult::*; let tcx = self.cx.tcx; @@ -1286,7 +1298,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { // `struct S(*mut S);`. // FIXME: A recursion limit is necessary as well, for irregular // recursive types. - if !cache.insert(ty) { + if !acc.cache.insert(ty) { return FfiSafe; } @@ -1308,6 +1320,17 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } match def.adt_kind() { AdtKind::Struct | AdtKind::Union => { + if let Some(sym::cstring_type | sym::cstr_type) = + tcx.get_diagnostic_name(def.did()) + && !acc.base_ty.is_mutable_ptr() + { + return FfiUnsafe { + ty, + reason: fluent::lint_improper_ctypes_cstr_reason, + help: Some(fluent::lint_improper_ctypes_cstr_help), + }; + } + if !def.repr().c() && !def.repr().transparent() { return FfiUnsafe { ty, @@ -1354,7 +1377,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { }; } - self.check_variant_for_ffi(cache, ty, def, def.non_enum_variant(), args) + self.check_variant_for_ffi(acc, ty, def, def.non_enum_variant(), args) } AdtKind::Enum => { if def.variants().is_empty() { @@ -1378,7 +1401,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { if let Some(ty) = repr_nullable_ptr(self.cx.tcx, self.cx.param_env, ty, self.mode) { - return self.check_type_for_ffi(cache, ty); + return self.check_type_for_ffi(acc, ty); } return FfiUnsafe { @@ -1399,7 +1422,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { }; } - match self.check_variant_for_ffi(cache, ty, def, variant, args) { + match self.check_variant_for_ffi(acc, ty, def, variant, args) { FfiSafe => (), r => return r, } @@ -1469,11 +1492,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { FfiSafe } - ty::RawPtr(ty, _) | ty::Ref(_, ty, _) => self.check_type_for_ffi(cache, ty), + ty::RawPtr(ty, _) | ty::Ref(_, ty, _) => self.check_type_for_ffi(acc, ty), - ty::Array(inner_ty, _) => self.check_type_for_ffi(cache, inner_ty), + ty::Array(inner_ty, _) => self.check_type_for_ffi(acc, inner_ty), - ty::FnPtr(sig) => { + ty::FnPtr(sig_tys, hdr) => { + let sig = sig_tys.with(hdr); if self.is_internal_abi(sig.abi()) { return FfiUnsafe { ty, @@ -1484,7 +1508,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { let sig = tcx.instantiate_bound_regions_with_erased(sig); for arg in sig.inputs() { - match self.check_type_for_ffi(cache, *arg) { + match self.check_type_for_ffi(acc, *arg) { FfiSafe => {} r => return r, } @@ -1495,7 +1519,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { return FfiSafe; } - self.check_type_for_ffi(cache, ret_ty) + self.check_type_for_ffi(acc, ret_ty) } ty::Foreign(..) => FfiSafe, @@ -1618,7 +1642,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { return; } - match self.check_type_for_ffi(&mut FxHashSet::default(), ty) { + let mut acc = CTypesVisitorState { cache: FxHashSet::default(), base_ty: ty }; + match self.check_type_for_ffi(&mut acc, ty) { FfiResult::FfiSafe => {} FfiResult::FfiPhantom(ty) => { self.emit_ffi_unsafe_type_lint( @@ -1709,8 +1734,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { type Result = ControlFlow>; fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { - if let ty::FnPtr(sig) = ty.kind() - && !self.visitor.is_internal_abi(sig.abi()) + if let ty::FnPtr(_, hdr) = ty.kind() + && !self.visitor.is_internal_abi(hdr.abi) { self.tys.push(ty); } @@ -1733,13 +1758,16 @@ impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDeclarations { let abi = cx.tcx.hir().get_foreign_abi(it.hir_id()); match it.kind { - hir::ForeignItemKind::Fn(decl, _, _, _) if !vis.is_internal_abi(abi) => { - vis.check_foreign_fn(it.owner_id.def_id, decl); + hir::ForeignItemKind::Fn(sig, _, _) => { + if vis.is_internal_abi(abi) { + vis.check_fn(it.owner_id.def_id, sig.decl) + } else { + vis.check_foreign_fn(it.owner_id.def_id, sig.decl); + } } hir::ForeignItemKind::Static(ty, _, _) if !vis.is_internal_abi(abi) => { vis.check_foreign_static(it.owner_id, ty.span); } - hir::ForeignItemKind::Fn(decl, _, _, _) => vis.check_fn(it.owner_id.def_id, decl), hir::ForeignItemKind::Static(..) | hir::ForeignItemKind::Type => (), } } diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 553d9db12c5..c3b80e01c36 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -1019,7 +1019,7 @@ declare_lint! { "`if`, `match`, `while` and `return` do not need parentheses" } -pub struct UnusedParens { +pub(crate) struct UnusedParens { with_self_ty_parens: bool, /// `1 as (i32) < 2` parses to ExprKind::Lt /// `1 as i32 < 2` parses to i32::<2[missing angle bracket] @@ -1027,7 +1027,7 @@ pub struct UnusedParens { } impl UnusedParens { - pub fn new() -> Self { + pub(crate) fn new() -> Self { Self { with_self_ty_parens: false, parens_in_cast_in_lt: Vec::new() } } } diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index c731b03a875..44c72e0c4fe 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -142,7 +142,6 @@ declare_lint_pass! { USELESS_DEPRECATED, WARNINGS, WASM_C_ABI, - WRITES_THROUGH_IMMUTABLE_POINTER, // tidy-alphabetical-end ] } @@ -251,7 +250,7 @@ declare_lint! { Deny, "conflicts between `#[repr(..)]` hints that were previously accepted and used in practice", @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, + reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, reference: "issue #68585 ", }; } @@ -4696,40 +4695,6 @@ declare_lint! { }; } -declare_lint! { - /// The `writes_through_immutable_pointer` lint detects writes through pointers derived from - /// shared references. - /// - /// ### Example - /// - /// ```rust,compile_fail - /// #![feature(const_mut_refs)] - /// const WRITE_AFTER_CAST: () = unsafe { - /// let mut x = 0; - /// let ptr = &x as *const i32 as *mut i32; - /// *ptr = 0; - /// }; - /// ``` - /// - /// {{produces}} - /// - /// ### Explanation - /// - /// Shared references are immutable (when there is no `UnsafeCell` involved), - /// and writing through them or through pointers derived from them is Undefined Behavior. - /// The compiler recently learned to detect such Undefined Behavior during compile-time - /// evaluation, and in the future this will raise a hard error. - /// - /// [future-incompatible]: ../index.md#future-incompatible-lints - pub WRITES_THROUGH_IMMUTABLE_POINTER, - Warn, - "shared references are immutable, and pointers derived from them must not be written to", - @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, - reference: "issue #X ", - }; -} - declare_lint! { /// The `private_macro_use` lint detects private macros that are imported /// with `#[macro_use]`. @@ -4971,7 +4936,6 @@ declare_lint! { /// ### Example /// /// ```rust - /// #![feature(unsafe_attributes)] /// #![warn(unsafe_attr_outside_unsafe)] /// /// #[no_mangle] diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 0f07de43e80..c17b85db3b0 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -1,3 +1,7 @@ +// tidy-alphabetical-start +#![warn(unreachable_pub)] +// tidy-alphabetical-end + use rustc_ast::node_id::NodeId; use rustc_ast::{AttrId, Attribute}; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; diff --git a/compiler/rustc_llvm/Cargo.toml b/compiler/rustc_llvm/Cargo.toml index 83fda7ef07c..1f74aaf9965 100644 --- a/compiler/rustc_llvm/Cargo.toml +++ b/compiler/rustc_llvm/Cargo.toml @@ -10,5 +10,5 @@ libc = "0.2.73" [build-dependencies] # tidy-alphabetical-start -cc = "1.0.97" +cc = "=1.0.105" # FIXME(cc): pinned to keep support for VS2013 # tidy-alphabetical-end diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 283c4fbbb7c..9884ed15b8a 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -1607,8 +1607,13 @@ extern "C" void LLVMRustComputeLTOCacheKey(RustStringRef KeyOut, const auto &ExportList = Data->ExportLists.lookup(ModId); const auto &ResolvedODR = Data->ResolvedODR.lookup(ModId); const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(ModId); +#if LLVM_VERSION_GE(20, 0) + DenseSet CfiFunctionDefs; + DenseSet CfiFunctionDecls; +#else std::set CfiFunctionDefs; std::set CfiFunctionDecls; +#endif // Based on the 'InProcessThinBackend' constructor in LLVM for (auto &Name : Data->Index.cfiFunctionDefs()) @@ -1618,9 +1623,15 @@ extern "C" void LLVMRustComputeLTOCacheKey(RustStringRef KeyOut, CfiFunctionDecls.insert( GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Name))); +#if LLVM_VERSION_GE(20, 0) + Key = llvm::computeLTOCacheKey(conf, Data->Index, ModId, ImportList, + ExportList, ResolvedODR, DefinedGlobals, + CfiFunctionDefs, CfiFunctionDecls); +#else llvm::computeLTOCacheKey(Key, conf, Data->Index, ModId, ImportList, ExportList, ResolvedODR, DefinedGlobals, CfiFunctionDefs, CfiFunctionDecls); +#endif LLVMRustStringWriteImpl(KeyOut, Key.c_str(), Key.size()); } diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 79a68b2ff0e..ed12318c88d 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -913,14 +913,19 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile(LLVMRustDIBuilderRef Builder, const char *Filename, size_t FilenameLen, const char *Directory, size_t DirectoryLen, LLVMRustChecksumKind CSKind, - const char *Checksum, size_t ChecksumLen) { + const char *Checksum, size_t ChecksumLen, + const char *Source, size_t SourceLen) { std::optional llvmCSKind = fromRust(CSKind); std::optional> CSInfo{}; if (llvmCSKind) CSInfo.emplace(*llvmCSKind, StringRef{Checksum, ChecksumLen}); + std::optional oSource{}; + if (Source) + oSource = StringRef(Source, SourceLen); return wrap(Builder->createFile(StringRef(Filename, FilenameLen), - StringRef(Directory, DirectoryLen), CSInfo)); + StringRef(Directory, DirectoryLen), CSInfo, + oSource)); } extern "C" LLVMMetadataRef diff --git a/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp index ccf1a5429e2..d625935d925 100644 --- a/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp @@ -77,22 +77,18 @@ LLVMRustGetSymbols(char *BufPtr, size_t BufLen, void *State, Expected> ObjOrErr = getSymbolicFile(Buf->getMemBufferRef(), Context); if (!ObjOrErr) { - Error E = ObjOrErr.takeError(); - SmallString<0> ErrorBuf; - auto Error = raw_svector_ostream(ErrorBuf); - Error << E << '\0'; - return ErrorCallback(Error.str().data()); + return ErrorCallback(toString(ObjOrErr.takeError()).c_str()); } std::unique_ptr Obj = std::move(*ObjOrErr); + if (Obj == nullptr) { + return 0; + } for (const object::BasicSymbolRef &S : Obj->symbols()) { if (!isArchiveSymbol(S)) continue; if (Error E = S.printName(SymName)) { - SmallString<0> ErrorBuf; - auto Error = raw_svector_ostream(ErrorBuf); - Error << E << '\0'; - return ErrorCallback(Error.str().data()); + return ErrorCallback(toString(std::move(E)).c_str()); } SymName << '\0'; if (void *E = Callback(State, SymNameBuf.str().data())) { diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs index 939e5e4dbd4..3532d50c64e 100644 --- a/compiler/rustc_llvm/src/lib.rs +++ b/compiler/rustc_llvm/src/lib.rs @@ -1,8 +1,10 @@ // tidy-alphabetical-start #![allow(internal_features)] +#![cfg_attr(bootstrap, feature(unsafe_attributes, unsafe_extern_blocks))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end // NOTE: This crate only exists to allow linking on mingw targets. @@ -28,7 +30,7 @@ impl RustString { } /// Appending to a Rust string -- used by RawRustStringOstream. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn LLVMRustStringWriteImpl( sr: &RustString, ptr: *const c_char, @@ -46,7 +48,7 @@ pub fn initialize_available_targets() { ($cfg:meta, $($method:ident),*) => { { #[cfg($cfg)] fn init() { - extern "C" { + unsafe extern "C" { $(fn $method();)* } unsafe { diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index c59f86b0a9b..929bc2df6f6 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -1,7 +1,5 @@ // tidy-alphabetical-start -#![allow(internal_features)] #![allow(rustc::default_hash_types)] -#![feature(allow_internal_unstable)] #![feature(if_let_guard)] #![feature(let_chains)] #![feature(never_type)] diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 25ae7b2bc31..90228db378a 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -1002,11 +1002,7 @@ impl CrateError { if !locator.crate_rejections.via_filename.is_empty() { let mismatches = locator.crate_rejections.via_filename.iter(); for CrateMismatch { path, .. } in mismatches { - dcx.emit_err(errors::CrateLocationUnknownType { - span, - path: path, - crate_name, - }); + dcx.emit_err(errors::CrateLocationUnknownType { span, path, crate_name }); dcx.emit_err(errors::LibFilenameForm { span, dll_prefix: &locator.dll_prefix, @@ -1035,7 +1031,7 @@ impl CrateError { } dcx.emit_err(errors::NewerCrateVersion { span, - crate_name: crate_name, + crate_name, add_info, found_crates, }); diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 8c0ea3eaea9..7321e2c760c 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -962,7 +962,7 @@ impl CrateRoot { } } -impl<'a, 'tcx> CrateMetadataRef<'a> { +impl<'a> CrateMetadataRef<'a> { fn missing(self, descr: &str, id: DefIndex) -> ! { bug!("missing `{descr}` for {:?}", self.local_def_id(id)) } @@ -1036,7 +1036,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .decode((self, sess)) } - fn load_proc_macro(self, id: DefIndex, tcx: TyCtxt<'tcx>) -> SyntaxExtension { + fn load_proc_macro<'tcx>(self, id: DefIndex, tcx: TyCtxt<'tcx>) -> SyntaxExtension { let (name, kind, helper_attrs) = match *self.raw_proc_macro(id) { ProcMacro::CustomDerive { trait_name, attributes, client } => { let helper_attrs = @@ -1070,7 +1070,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { ) } - fn get_explicit_item_bounds( + fn get_explicit_item_bounds<'tcx>( self, index: DefIndex, tcx: TyCtxt<'tcx>, @@ -1084,7 +1084,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { ty::EarlyBinder::bind(&*output) } - fn get_explicit_item_super_predicates( + fn get_explicit_item_super_predicates<'tcx>( self, index: DefIndex, tcx: TyCtxt<'tcx>, @@ -1141,7 +1141,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { ) } - fn get_adt_def(self, item_id: DefIndex, tcx: TyCtxt<'tcx>) -> ty::AdtDef<'tcx> { + fn get_adt_def<'tcx>(self, item_id: DefIndex, tcx: TyCtxt<'tcx>) -> ty::AdtDef<'tcx> { let kind = self.def_kind(item_id); let did = self.local_def_id(item_id); @@ -1225,12 +1225,12 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { /// Iterates over the stability implications in the given crate (when a `#[unstable]` attribute /// has an `implied_by` meta item, then the mapping from the implied feature to the actual /// feature is a stability implication). - fn get_stability_implications(self, tcx: TyCtxt<'tcx>) -> &'tcx [(Symbol, Symbol)] { + fn get_stability_implications<'tcx>(self, tcx: TyCtxt<'tcx>) -> &'tcx [(Symbol, Symbol)] { tcx.arena.alloc_from_iter(self.root.stability_implications.decode(self)) } /// Iterates over the lang items in the given crate. - fn get_lang_items(self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, LangItem)] { + fn get_lang_items<'tcx>(self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, LangItem)] { tcx.arena.alloc_from_iter( self.root .lang_items @@ -1239,7 +1239,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { ) } - fn get_stripped_cfg_items(self, cnum: CrateNum, tcx: TyCtxt<'tcx>) -> &'tcx [StrippedCfgItem] { + fn get_stripped_cfg_items<'tcx>( + self, + cnum: CrateNum, + tcx: TyCtxt<'tcx>, + ) -> &'tcx [StrippedCfgItem] { let item_names = self .root .stripped_cfg_items @@ -1412,7 +1416,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .decode((self, sess)) } - fn get_inherent_implementations_for_type( + fn get_inherent_implementations_for_type<'tcx>( self, tcx: TyCtxt<'tcx>, id: DefIndex, @@ -1439,7 +1443,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { }) } - fn get_incoherent_impls(self, tcx: TyCtxt<'tcx>, simp: SimplifiedType) -> &'tcx [DefId] { + fn get_incoherent_impls<'tcx>(self, tcx: TyCtxt<'tcx>, simp: SimplifiedType) -> &'tcx [DefId] { if let Some(impls) = self.cdata.incoherent_impls.get(&simp) { tcx.arena.alloc_from_iter(impls.decode(self).map(|idx| self.local_def_id(idx))) } else { @@ -1447,7 +1451,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } } - fn get_implementations_of_trait( + fn get_implementations_of_trait<'tcx>( self, tcx: TyCtxt<'tcx>, trait_def_id: DefId, @@ -1487,11 +1491,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .decode((self, sess)) } - fn get_foreign_modules(self, sess: &'a Session) -> impl Iterator + '_ { + fn get_foreign_modules(self, sess: &'a Session) -> impl Iterator + 'a { self.root.foreign_modules.decode((self, sess)) } - fn get_dylib_dependency_formats( + fn get_dylib_dependency_formats<'tcx>( self, tcx: TyCtxt<'tcx>, ) -> &'tcx [(CrateNum, LinkagePreference)] { @@ -1503,11 +1507,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { ) } - fn get_missing_lang_items(self, tcx: TyCtxt<'tcx>) -> &'tcx [LangItem] { + fn get_missing_lang_items<'tcx>(self, tcx: TyCtxt<'tcx>) -> &'tcx [LangItem] { tcx.arena.alloc_from_iter(self.root.lang_items_missing.decode(self)) } - fn exported_symbols( + fn exported_symbols<'tcx>( self, tcx: TyCtxt<'tcx>, ) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] { diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 46039f6e5f6..27625f79108 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -224,6 +224,7 @@ provide! { tcx, def_id, other, cdata, variances_of => { table } fn_sig => { table } codegen_fn_attrs => { table } + struct_target_features => { table } impl_trait_header => { table } const_param_default => { table } object_lifetime_default => { table } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 0d83f8c6c5c..fbcfbd3befa 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -872,7 +872,8 @@ fn should_encode_span(def_kind: DefKind) -> bool { | DefKind::OpaqueTy | DefKind::Field | DefKind::Impl { .. } - | DefKind::Closure => true, + | DefKind::Closure + | DefKind::SyntheticCoroutineBody => true, DefKind::ForeignMod | DefKind::GlobalAsm => false, } } @@ -902,6 +903,7 @@ fn should_encode_attrs(def_kind: DefKind) -> bool { // https://github.com/model-checking/kani and is not a performance // or maintenance issue for us. DefKind::Closure => true, + DefKind::SyntheticCoroutineBody => false, DefKind::TyParam | DefKind::ConstParam | DefKind::Ctor(..) @@ -948,7 +950,8 @@ fn should_encode_expn_that_defined(def_kind: DefKind) -> bool { | DefKind::Field | DefKind::LifetimeParam | DefKind::GlobalAsm - | DefKind::Closure => false, + | DefKind::Closure + | DefKind::SyntheticCoroutineBody => false, } } @@ -984,7 +987,8 @@ fn should_encode_visibility(def_kind: DefKind) -> bool { | DefKind::GlobalAsm | DefKind::Impl { .. } | DefKind::Closure - | DefKind::ExternCrate => false, + | DefKind::ExternCrate + | DefKind::SyntheticCoroutineBody => false, } } @@ -1019,7 +1023,8 @@ fn should_encode_stability(def_kind: DefKind) -> bool { | DefKind::InlineConst | DefKind::GlobalAsm | DefKind::Closure - | DefKind::ExternCrate => false, + | DefKind::ExternCrate + | DefKind::SyntheticCoroutineBody => false, } } @@ -1061,6 +1066,7 @@ fn should_encode_mir( } // Coroutines require optimized MIR to compute layout. DefKind::Closure if tcx.is_coroutine(def_id.to_def_id()) => (false, true), + DefKind::SyntheticCoroutineBody => (false, true), // Full-fledged functions + closures DefKind::AssocFn | DefKind::Fn | DefKind::Closure => { let generics = tcx.generics_of(def_id); @@ -1109,7 +1115,8 @@ fn should_encode_variances<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: Def | DefKind::InlineConst | DefKind::GlobalAsm | DefKind::Closure - | DefKind::ExternCrate => false, + | DefKind::ExternCrate + | DefKind::SyntheticCoroutineBody => false, DefKind::TyAlias => tcx.type_alias_is_lazy(def_id), } } @@ -1137,7 +1144,8 @@ fn should_encode_generics(def_kind: DefKind) -> bool { | DefKind::Impl { .. } | DefKind::Field | DefKind::TyParam - | DefKind::Closure => true, + | DefKind::Closure + | DefKind::SyntheticCoroutineBody => true, DefKind::Mod | DefKind::ForeignMod | DefKind::ConstParam @@ -1168,7 +1176,8 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) -> | DefKind::Closure | DefKind::ConstParam | DefKind::AnonConst - | DefKind::InlineConst => true, + | DefKind::InlineConst + | DefKind::SyntheticCoroutineBody => true, DefKind::OpaqueTy => { let origin = tcx.opaque_type_origin(def_id); @@ -1240,7 +1249,8 @@ fn should_encode_fn_sig(def_kind: DefKind) -> bool { | DefKind::Use | DefKind::LifetimeParam | DefKind::GlobalAsm - | DefKind::ExternCrate => false, + | DefKind::ExternCrate + | DefKind::SyntheticCoroutineBody => false, } } @@ -1277,7 +1287,8 @@ fn should_encode_constness(def_kind: DefKind) -> bool { | DefKind::Use | DefKind::LifetimeParam | DefKind::GlobalAsm - | DefKind::ExternCrate => false, + | DefKind::ExternCrate + | DefKind::SyntheticCoroutineBody => false, } } @@ -1310,7 +1321,8 @@ fn should_encode_const(def_kind: DefKind) -> bool { | DefKind::Use | DefKind::LifetimeParam | DefKind::GlobalAsm - | DefKind::ExternCrate => false, + | DefKind::ExternCrate + | DefKind::SyntheticCoroutineBody => false, } } @@ -1380,6 +1392,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if def_kind.has_codegen_attrs() { record!(self.tables.codegen_fn_attrs[def_id] <- self.tcx.codegen_fn_attrs(def_id)); } + if def_kind.has_struct_target_features() { + record_array!(self.tables.struct_target_features[def_id] <- self.tcx.struct_target_features(def_id)); + } if should_encode_visibility(def_kind) { let vis = self.tcx.local_visibility(local_id).map_id(|def_id| def_id.local_def_index); @@ -1458,7 +1473,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record!(self.tables.associated_type_for_effects[def_id] <- assoc_def_id); } } - if def_kind == DefKind::Closure + if let DefKind::Closure | DefKind::SyntheticCoroutineBody = def_kind && let Some(coroutine_kind) = self.tcx.coroutine_kind(def_id) { self.tables.coroutine_kind.set(def_id.index, Some(coroutine_kind)) diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index c1b77172983..aec728d4262 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -19,7 +19,7 @@ use rustc_macros::{ Decodable, Encodable, MetadataDecodable, MetadataEncodable, TyDecodable, TyEncodable, }; use rustc_middle::metadata::ModChild; -use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; +use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrs, TargetFeature}; use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; use rustc_middle::middle::lib_features::FeatureStability; @@ -427,6 +427,7 @@ define_tables! { variances_of: Table>, fn_sig: Table>>>, codegen_fn_attrs: Table>, + struct_target_features: Table>, impl_trait_header: Table>>, const_param_default: Table>>>, object_lifetime_default: Table>, diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index 617372a97b5..3a6f3543317 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -171,6 +171,7 @@ fixed_size_enum! { ( Macro(MacroKind::Bang) ) ( Macro(MacroKind::Attr) ) ( Macro(MacroKind::Derive) ) + ( SyntheticCoroutineBody ) } } diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index e3d7dff3c66..7050a06b8dc 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -35,7 +35,6 @@ macro_rules! arena_types { )>, [] crate_for_resolver: rustc_data_structures::steal::Steal<(rustc_ast::Crate, rustc_ast::AttrVec)>, [] resolutions: rustc_middle::ty::ResolverGlobalCtxt, - [decode] code_region: rustc_middle::mir::coverage::CodeRegion, [] const_allocs: rustc_middle::mir::interpret::Allocation, [] region_scope_tree: rustc_middle::middle::region::ScopeTree, // Required for the incremental on-disk cache @@ -61,10 +60,6 @@ macro_rules! arena_types { [] dtorck_constraint: rustc_middle::traits::query::DropckConstraint<'tcx>, [] candidate_step: rustc_middle::traits::query::CandidateStep<'tcx>, [] autoderef_bad_ty: rustc_middle::traits::query::MethodAutoderefBadTy<'tcx>, - [] canonical_goal_evaluation: - rustc_type_ir::solve::inspect::CanonicalGoalEvaluationStep< - rustc_middle::ty::TyCtxt<'tcx> - >, [] query_region_constraints: rustc_middle::infer::canonical::QueryRegionConstraints<'tcx>, [] type_op_subtype: rustc_middle::infer::canonical::Canonical<'tcx, diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs index 61348cdce23..5c2aa0005d4 100644 --- a/compiler/rustc_middle/src/error.rs +++ b/compiler/rustc_middle/src/error.rs @@ -160,7 +160,7 @@ pub struct TypeLengthLimit { pub span: Span, pub shrunk: String, #[note(middle_written_to_path)] - pub was_written: Option<()>, + pub was_written: bool, pub path: PathBuf, pub type_length: usize, } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index edab6b5ebde..3d346b9cc5d 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -307,7 +307,7 @@ impl<'hir> Map<'hir> { } DefKind::InlineConst => BodyOwnerKind::Const { inline: true }, DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => BodyOwnerKind::Fn, - DefKind::Closure => BodyOwnerKind::Closure, + DefKind::Closure | DefKind::SyntheticCoroutineBody => BodyOwnerKind::Closure, DefKind::Static { safety: _, mutability, nested: false } => { BodyOwnerKind::Static(mutability) } @@ -554,53 +554,43 @@ impl<'hir> Map<'hir> { /// } /// ``` pub fn get_fn_id_for_return_block(self, id: HirId) -> Option { - let mut iter = self.parent_iter(id).peekable(); - let mut ignore_tail = false; - if let Node::Expr(Expr { kind: ExprKind::Ret(_), .. }) = self.tcx.hir_node(id) { - // When dealing with `return` statements, we don't care about climbing only tail - // expressions. - ignore_tail = true; - } + let enclosing_body_owner = self.tcx.local_def_id_to_hir_id(self.enclosing_body_owner(id)); - let mut prev_hir_id = None; - while let Some((hir_id, node)) = iter.next() { - if let (Some((_, next_node)), false) = (iter.peek(), ignore_tail) { - match next_node { - Node::Block(Block { expr: None, .. }) => return None, - // The current node is not the tail expression of its parent. - Node::Block(Block { expr: Some(e), .. }) if hir_id != e.hir_id => return None, + // Return `None` if the `id` expression is not the returned value of the enclosing body + let mut iter = [id].into_iter().chain(self.parent_id_iter(id)).peekable(); + while let Some(cur_id) = iter.next() { + if enclosing_body_owner == cur_id { + break; + } + + // A return statement is always the value returned from the enclosing body regardless of + // what the parent expressions are. + if let Node::Expr(Expr { kind: ExprKind::Ret(_), .. }) = self.tcx.hir_node(cur_id) { + break; + } + + // If the current expression's value doesnt get used as the parent expressions value then return `None` + if let Some(&parent_id) = iter.peek() { + match self.tcx.hir_node(parent_id) { + // The current node is not the tail expression of the block expression parent expr. + Node::Block(Block { expr: Some(e), .. }) if cur_id != e.hir_id => return None, Node::Block(Block { expr: Some(e), .. }) if matches!(e.kind, ExprKind::If(_, _, None)) => { return None; } + + // The current expression's value does not pass up through these parent expressions + Node::Block(Block { expr: None, .. }) + | Node::Expr(Expr { kind: ExprKind::Loop(..), .. }) + | Node::LetStmt(..) => return None, + _ => {} } } - match node { - Node::Item(_) - | Node::ForeignItem(_) - | Node::TraitItem(_) - | Node::Expr(Expr { kind: ExprKind::Closure(_), .. }) - | Node::ImplItem(_) - // The input node `id` must be enclosed in the method's body as opposed - // to some other place such as its return type (fixes #114918). - // We verify that indirectly by checking that the previous node is the - // current node's body - if node.body_id().map(|b| b.hir_id) == prev_hir_id => { - return Some(hir_id) - } - // Ignore `return`s on the first iteration - Node::Expr(Expr { kind: ExprKind::Loop(..) | ExprKind::Ret(..), .. }) - | Node::LetStmt(_) => { - return None; - } - _ => {} - } - - prev_hir_id = Some(hir_id); } - None + + Some(enclosing_body_owner) } /// Retrieves the `OwnerId` for `id`'s parent item, or `id` itself if no @@ -826,6 +816,11 @@ impl<'hir> Map<'hir> { }) | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(sig, ..), span: outer_span, .. + }) + | Node::ForeignItem(ForeignItem { + kind: ForeignItemKind::Fn(sig, ..), + span: outer_span, + .. }) => { // Ensure that the returned span has the item's SyntaxContext, and not the // SyntaxContext of the visibility. @@ -884,10 +879,7 @@ impl<'hir> Map<'hir> { }, Node::Variant(variant) => named_span(variant.span, variant.ident, None), Node::ImplItem(item) => named_span(item.span, item.ident, Some(item.generics)), - Node::ForeignItem(item) => match item.kind { - ForeignItemKind::Fn(decl, _, _, _) => until_within(item.span, decl.output.span()), - _ => named_span(item.span, item.ident, None), - }, + Node::ForeignItem(item) => named_span(item.span, item.ident, None), Node::Ctor(_) => return self.span(self.tcx.parent_hir_id(hir_id)), Node::Expr(Expr { kind: ExprKind::Closure(Closure { fn_decl_span, .. }), diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index fa521ab9f2f..596d9f07737 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -202,7 +202,7 @@ pub fn provide(providers: &mut Providers) { .. }) | Node::ForeignItem(&ForeignItem { - kind: ForeignItemKind::Fn(_, idents, _, _), + kind: ForeignItemKind::Fn(_, idents, _), .. }) = tcx.hir_node(tcx.local_def_id_to_hir_id(def_id)) { diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 5bd7736a3f3..32f79ff7234 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -28,12 +28,13 @@ #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::potential_query_instability)] #![allow(rustc::untranslatable_diagnostic)] -#![cfg_attr(bootstrap, feature(min_exhaustive_patterns))] +#![cfg_attr(bootstrap, feature(min_exhaustive_patterns, unsafe_extern_blocks))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(allocator_api)] #![feature(array_windows)] #![feature(assert_matches)] +#![feature(box_as_ptr)] #![feature(box_patterns)] #![feature(closure_track_caller)] #![feature(const_option)] @@ -52,7 +53,6 @@ #![feature(min_specialization)] #![feature(negative_impls)] #![feature(never_type)] -#![feature(new_uninit)] #![feature(ptr_alignment_type)] #![feature(rustc_attrs)] #![feature(rustdoc_internals)] diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index b7d290e58d2..c098a739592 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -26,8 +26,8 @@ pub struct CodegenFnAttrs { /// be set when `link_name` is set. This is for foreign items with the /// "raw-dylib" kind. pub link_ordinal: Option, - /// The `#[target_feature(enable = "...")]` attribute and the enabled - /// features (only enabled features are supported right now). + /// All the target features that are enabled for this function. Some features might be enabled + /// implicitly. pub target_features: Vec, /// The `#[linkage = "..."]` attribute on Rust-defined items and the value we found. pub linkage: Option, @@ -55,8 +55,8 @@ pub struct CodegenFnAttrs { pub struct TargetFeature { /// The name of the target feature (e.g. "avx") pub name: Symbol, - /// The feature is implied by another feature, rather than explicitly added by the - /// `#[target_feature]` attribute + /// The feature is implied by another feature or by an argument, rather than explicitly + /// added by the `#[target_feature]` attribute pub implied: bool, } diff --git a/compiler/rustc_middle/src/middle/resolve_bound_vars.rs b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs index a4f6d7afe4d..32e2f3b4b16 100644 --- a/compiler/rustc_middle/src/middle/resolve_bound_vars.rs +++ b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs @@ -2,7 +2,7 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_errors::ErrorGuaranteed; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{ItemLocalId, OwnerId}; use rustc_macros::{Decodable, Encodable, HashStable, TyDecodable, TyEncodable}; @@ -11,9 +11,9 @@ use crate::ty; #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, HashStable)] pub enum ResolvedArg { StaticLifetime, - EarlyBound(/* decl */ DefId), - LateBound(ty::DebruijnIndex, /* late-bound index */ u32, /* decl */ DefId), - Free(DefId, /* lifetime decl */ DefId), + EarlyBound(/* decl */ LocalDefId), + LateBound(ty::DebruijnIndex, /* late-bound index */ u32, /* decl */ LocalDefId), + Free(LocalDefId, /* lifetime decl */ LocalDefId), Error(ErrorGuaranteed), } diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index b11c523cfe9..bfe2a2c2cb3 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -163,7 +163,7 @@ impl Debug for CoverageKind { #[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, Eq, PartialOrd, Ord)] #[derive(TypeFoldable, TypeVisitable)] -pub struct CodeRegion { +pub struct SourceRegion { pub file_name: Symbol, pub start_line: u32, pub start_col: u32, @@ -171,7 +171,7 @@ pub struct CodeRegion { pub end_col: u32, } -impl Debug for CodeRegion { +impl Debug for SourceRegion { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { write!( fmt, @@ -242,7 +242,7 @@ impl MappingKind { #[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] pub struct Mapping { pub kind: MappingKind, - pub code_region: CodeRegion, + pub source_region: SourceRegion, } /// Stores per-function coverage information attached to a `mir::Body`, diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 665ab2797f2..3e101c0c635 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -62,13 +62,11 @@ impl AllocBytes for Box<[u8]> { } fn as_mut_ptr(&mut self) -> *mut u8 { - // Carefully avoiding any intermediate references. - ptr::addr_of_mut!(**self).cast() + Box::as_mut_ptr(self).cast() } fn as_ptr(&self) -> *const u8 { - // Carefully avoiding any intermediate references. - ptr::addr_of!(**self).cast() + Box::as_ptr(self).cast() } } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 46c4d586f6a..7b901915037 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -267,18 +267,6 @@ pub struct CoroutineInfo<'tcx> { /// Coroutine drop glue. This field is populated after the state transform pass. pub coroutine_drop: Option>, - /// The body of the coroutine, modified to take its upvars by move rather than by ref. - /// - /// This is used by coroutine-closures, which must return a different flavor of coroutine - /// when called using `AsyncFnOnce::call_once`. It is produced by the `ByMoveBody` pass which - /// is run right after building the initial MIR, and will only be populated for coroutines - /// which come out of the async closure desugaring. - /// - /// This body should be processed in lockstep with the containing body -- any optimization - /// passes, etc, should be applied to this body as well. This is done automatically if - /// using `run_passes`. - pub by_move_body: Option>, - /// The layout of a coroutine. This field is populated after the state transform pass. pub coroutine_layout: Option>, @@ -298,7 +286,6 @@ impl<'tcx> CoroutineInfo<'tcx> { coroutine_kind, yield_ty: Some(yield_ty), resume_ty: Some(resume_ty), - by_move_body: None, coroutine_drop: None, coroutine_layout: None, } @@ -665,10 +652,6 @@ impl<'tcx> Body<'tcx> { self.coroutine.as_ref().and_then(|coroutine| coroutine.coroutine_drop.as_ref()) } - pub fn coroutine_by_move_body(&self) -> Option<&Body<'tcx>> { - self.coroutine.as_ref()?.by_move_body.as_ref() - } - #[inline] pub fn coroutine_kind(&self) -> Option { self.coroutine.as_ref().map(|coroutine| coroutine.coroutine_kind) @@ -1368,7 +1351,7 @@ rustc_index::newtype_index! { /// [CFG]: https://rustc-dev-guide.rust-lang.org/appendix/background.html#cfg /// [data-flow analyses]: /// https://rustc-dev-guide.rust-lang.org/appendix/background.html#what-is-a-dataflow-analysis - /// [`CriticalCallEdges`]: ../../rustc_const_eval/transform/add_call_guards/enum.AddCallGuards.html#variant.CriticalCallEdges + /// [`CriticalCallEdges`]: ../../rustc_mir_transform/add_call_guards/enum.AddCallGuards.html#variant.CriticalCallEdges /// [guide-mir]: https://rustc-dev-guide.rust-lang.org/mir/ #[derive(HashStable)] #[encodable] diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 336a9388a56..1d94c364ae3 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -415,7 +415,6 @@ impl<'tcx> CodegenUnit<'tcx> { | InstanceKind::Virtual(..) | InstanceKind::ClosureOnceShim { .. } | InstanceKind::ConstructCoroutineInClosureShim { .. } - | InstanceKind::CoroutineKindShim { .. } | InstanceKind::DropGlue(..) | InstanceKind::CloneShim(..) | InstanceKind::ThreadLocalShim(..) diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index f2d87814130..6785805c27d 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -547,8 +547,8 @@ fn write_function_coverage_info( for (id, expression) in expressions.iter_enumerated() { writeln!(w, "{INDENT}coverage {id:?} => {expression:?};")?; } - for coverage::Mapping { kind, code_region } in mappings { - writeln!(w, "{INDENT}coverage {kind:?} => {code_region:?};")?; + for coverage::Mapping { kind, source_region } in mappings { + writeln!(w, "{INDENT}coverage {kind:?} => {source_region:?};")?; } writeln!(w)?; @@ -1038,7 +1038,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { CopyForDeref(ref place) => write!(fmt, "deref_copy {place:#?}"), - AddressOf(mutability, ref place) => { + RawPtr(mutability, ref place) => { write!(fmt, "&raw {mut_str} {place:?}", mut_str = mutability.ptr_str()) } @@ -1159,7 +1159,7 @@ impl<'tcx> Debug for Operand<'tcx> { use self::Operand::*; match *self { Constant(ref a) => write!(fmt, "{a:?}"), - Copy(ref place) => write!(fmt, "{place:?}"), + Copy(ref place) => write!(fmt, "copy {place:?}"), Move(ref place) => write!(fmt, "move {place:?}"), } } @@ -1418,21 +1418,19 @@ pub fn write_allocations<'tcx>( alloc.inner().provenance().ptrs().values().map(|p| p.alloc_id()) } - fn alloc_ids_from_const_val(val: ConstValue<'_>) -> impl Iterator + '_ { + fn alloc_id_from_const_val(val: ConstValue<'_>) -> Option { match val { - ConstValue::Scalar(interpret::Scalar::Ptr(ptr, _)) => { - Either::Left(std::iter::once(ptr.provenance.alloc_id())) - } - ConstValue::Scalar(interpret::Scalar::Int { .. }) => Either::Right(std::iter::empty()), - ConstValue::ZeroSized => Either::Right(std::iter::empty()), + ConstValue::Scalar(interpret::Scalar::Ptr(ptr, _)) => Some(ptr.provenance.alloc_id()), + ConstValue::Scalar(interpret::Scalar::Int { .. }) => None, + ConstValue::ZeroSized => None, ConstValue::Slice { .. } => { // `u8`/`str` slices, shouldn't contain pointers that we want to print. - Either::Right(std::iter::empty()) + None } ConstValue::Indirect { alloc_id, .. } => { // FIXME: we don't actually want to print all of these, since some are printed nicely directly as values inline in MIR. // Really we'd want `pretty_print_const_value` to decide which allocations to print, instead of having a separate visitor. - Either::Left(std::iter::once(alloc_id)) + Some(alloc_id) } } } @@ -1443,7 +1441,9 @@ pub fn write_allocations<'tcx>( match c.const_ { Const::Ty(_, _) | Const::Unevaluated(..) => {} Const::Val(val, _) => { - self.0.extend(alloc_ids_from_const_val(val)); + if let Some(id) = alloc_id_from_const_val(val) { + self.0.insert(id); + } } } } diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index 3009ca8d809..bc7dfa6205e 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -423,7 +423,7 @@ impl<'tcx> Rvalue<'tcx> { | Rvalue::Repeat(_, _) | Rvalue::Ref(_, _, _) | Rvalue::ThreadLocalRef(_) - | Rvalue::AddressOf(_, _) + | Rvalue::RawPtr(_, _) | Rvalue::Len(_) | Rvalue::Cast( CastKind::IntToInt diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 1119ff6ff3d..748ca047754 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -395,7 +395,7 @@ pub enum StatementKind<'tcx> { /// `PlaceMention(PLACE)`. /// /// When executed at runtime, this computes the given place, but then discards - /// it without doing a load. It is UB if the place is not pointing to live memory. + /// it without doing a load. `let _ = *ptr;` is fine even if the pointer is dangling. PlaceMention(Box>), /// Encodes a user's type ascription. These need to be preserved @@ -1293,14 +1293,14 @@ pub enum Rvalue<'tcx> { /// nature of this operation? ThreadLocalRef(DefId), - /// Creates a pointer with the indicated mutability to the place. + /// Creates a raw pointer with the indicated mutability to the place. /// - /// This is generated by pointer casts like `&v as *const _` or raw address of expressions like - /// `&raw v` or `addr_of!(v)`. + /// This is generated by pointer casts like `&v as *const _` or raw borrow expressions like + /// `&raw const v`. /// /// Like with references, the semantics of this operation are heavily dependent on the aliasing /// model. - AddressOf(Mutability, Place<'tcx>), + RawPtr(Mutability, Place<'tcx>), /// Yields the length of the place, as a `usize`. /// diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index 1075344dc00..8d57d0d8654 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -170,7 +170,7 @@ impl<'tcx> Rvalue<'tcx> { let place_ty = place.ty(local_decls, tcx).ty; Ty::new_ref(tcx, reg, place_ty, bk.to_mutbl_lossy()) } - Rvalue::AddressOf(mutability, ref place) => { + Rvalue::RawPtr(mutability, ref place) => { let place_ty = place.ty(local_decls, tcx).ty; Ty::new_ptr(tcx, place_ty, mutability) } diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 3921176873c..64898a8495e 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -349,7 +349,6 @@ macro_rules! make_mir_visitor { coroutine_closure_def_id: _def_id, receiver_by_ref: _, } | - ty::InstanceKind::CoroutineKindShim { coroutine_def_id: _def_id } | ty::InstanceKind::AsyncDropGlueCtorShim(_def_id, None) | ty::InstanceKind::DropGlue(_def_id, None) => {} @@ -682,13 +681,13 @@ macro_rules! make_mir_visitor { ); } - Rvalue::AddressOf(m, path) => { + Rvalue::RawPtr(m, path) => { let ctx = match m { Mutability::Mut => PlaceContext::MutatingUse( - MutatingUseContext::AddressOf + MutatingUseContext::RawBorrow ), Mutability::Not => PlaceContext::NonMutatingUse( - NonMutatingUseContext::AddressOf + NonMutatingUseContext::RawBorrow ), }; self.visit_place(path, ctx, location); @@ -1299,8 +1298,8 @@ pub enum NonMutatingUseContext { /// FIXME: do we need to distinguish shallow and deep fake borrows? In fact, do we need to /// distinguish fake and normal deep borrows? FakeBorrow, - /// AddressOf for *const pointer. - AddressOf, + /// `&raw const`. + RawBorrow, /// PlaceMention statement. /// /// This statement is executed as a check that the `Place` is live without reading from it, @@ -1333,8 +1332,8 @@ pub enum MutatingUseContext { Drop, /// Mutable borrow. Borrow, - /// AddressOf for *mut pointer. - AddressOf, + /// `&raw mut`. + RawBorrow, /// Used as base for another place, e.g., `x` in `x.y`. Could potentially mutate the place. /// For example, the projection `x.y` is marked as a mutation in these cases: /// ```ignore (illustrative) @@ -1386,8 +1385,8 @@ impl PlaceContext { pub fn is_address_of(&self) -> bool { matches!( self, - PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf) - | PlaceContext::MutatingUse(MutatingUseContext::AddressOf) + PlaceContext::NonMutatingUse(NonMutatingUseContext::RawBorrow) + | PlaceContext::MutatingUse(MutatingUseContext::RawBorrow) ) } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 075eae02904..6434bd0d7bf 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -47,7 +47,7 @@ use {rustc_ast as ast, rustc_attr as attr, rustc_hir as hir}; use crate::infer::canonical::{self, Canonical}; use crate::lint::LintExpectation; use crate::metadata::ModChild; -use crate::middle::codegen_fn_attrs::CodegenFnAttrs; +use crate::middle::codegen_fn_attrs::{CodegenFnAttrs, TargetFeature}; use crate::middle::debugger_visualizer::DebuggerVisualizerFile; use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; use crate::middle::lib_features::LibFeatures; @@ -65,10 +65,9 @@ use crate::query::plumbing::{ }; use crate::traits::query::{ CanonicalAliasGoal, CanonicalPredicateGoal, CanonicalTyGoal, - CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal, - CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal, DropckConstraint, - DropckOutlivesResult, MethodAutoderefStepsResult, NoSolution, NormalizationResult, - OutlivesBound, + CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpNormalizeGoal, + CanonicalTypeOpProvePredicateGoal, DropckConstraint, DropckOutlivesResult, + MethodAutoderefStepsResult, NoSolution, NormalizationResult, OutlivesBound, }; use crate::traits::{ specialization_graph, CodegenObligationError, EvaluationResult, ImplSource, @@ -313,20 +312,10 @@ rustc_queries! { /// predicates (where-clauses) that must be proven true in order /// to reference it. This is almost always the "predicates query" /// that you want. - /// - /// `predicates_of` builds on `predicates_defined_on` -- in fact, - /// it is almost always the same as that query, except for the - /// case of traits. For traits, `predicates_of` contains - /// an additional `Self: Trait<...>` predicate that users don't - /// actually write. This reflects the fact that to invoke the - /// trait (e.g., via `Default::default`) you must supply types - /// that actually implement the trait. (However, this extra - /// predicate gets in the way of some checks, which are intended - /// to operate over only the actual where-clauses written by the - /// user.) query predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> { desc { |tcx| "computing predicates of `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } + feedable } query opaque_types_defined_by( @@ -499,6 +488,7 @@ rustc_queries! { /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/construction.html query mir_built(key: LocalDefId) -> &'tcx Steal> { desc { |tcx| "building MIR for `{}`", tcx.def_path_str(key) } + feedable } /// Try to build an abstract representation of the given constant. @@ -618,14 +608,6 @@ rustc_queries! { desc { "getting wasm import module map" } } - /// Maps from the `DefId` of an item (trait/struct/enum/fn) to the - /// predicates (where-clauses) directly defined on it. This is - /// equal to the `explicit_predicates_of` predicates plus the - /// `inferred_outlives_of` predicates. - query predicates_defined_on(key: DefId) -> ty::GenericPredicates<'tcx> { - desc { |tcx| "computing predicates of `{}`", tcx.def_path_str(key) } - } - /// Returns everything that looks like a predicate written explicitly /// by the user on a trait item. /// @@ -743,6 +725,7 @@ rustc_queries! { query constness(key: DefId) -> hir::Constness { desc { |tcx| "checking if item is const: `{}`", tcx.def_path_str(key) } separate_provide_extern + feedable } query asyncness(key: DefId) -> ty::Asyncness { @@ -761,10 +744,22 @@ rustc_queries! { desc { |tcx| "checking if item is promotable: `{}`", tcx.def_path_str(key) } } + /// The body of the coroutine, modified to take its upvars by move rather than by ref. + /// + /// This is used by coroutine-closures, which must return a different flavor of coroutine + /// when called using `AsyncFnOnce::call_once`. It is produced by the `ByMoveBody` pass which + /// is run right after building the initial MIR, and will only be populated for coroutines + /// which come out of the async closure desugaring. + query coroutine_by_move_body_def_id(def_id: DefId) -> DefId { + desc { |tcx| "looking up the coroutine by-move body for `{}`", tcx.def_path_str(def_id) } + separate_provide_extern + } + /// Returns `Some(coroutine_kind)` if the node pointed to by `def_id` is a coroutine. query coroutine_kind(def_id: DefId) -> Option { desc { |tcx| "looking up coroutine kind of `{}`", tcx.def_path_str(def_id) } separate_provide_extern + feedable } query coroutine_for_closure(def_id: DefId) -> DefId { @@ -1250,6 +1245,11 @@ rustc_queries! { feedable } + query struct_target_features(def_id: DefId) -> &'tcx [TargetFeature] { + separate_provide_extern + desc { |tcx| "computing target features for struct `{}`", tcx.def_path_str(def_id) } + } + query asm_target_features(def_id: DefId) -> &'tcx FxIndexSet { desc { |tcx| "computing target features for inline asm of `{}`", tcx.def_path_str(def_id) } } @@ -1521,7 +1521,7 @@ rustc_queries! { separate_provide_extern } - query extern_crate(def_id: DefId) -> Option<&'tcx ExternCrate> { + query extern_crate(def_id: CrateNum) -> Option<&'tcx ExternCrate> { eval_always desc { "getting crate's ExternCrateData" } separate_provide_extern @@ -2090,26 +2090,6 @@ rustc_queries! { desc { "evaluating `type_op_ascribe_user_type` `{:?}`", goal.value.value } } - /// Do not call this query directly: part of the `Eq` type-op - query type_op_eq( - goal: CanonicalTypeOpEqGoal<'tcx> - ) -> Result< - &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>, - NoSolution, - > { - desc { "evaluating `type_op_eq` `{:?}`", goal.value.value } - } - - /// Do not call this query directly: part of the `Subtype` type-op - query type_op_subtype( - goal: CanonicalTypeOpSubtypeGoal<'tcx> - ) -> Result< - &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>, - NoSolution, - > { - desc { "evaluating `type_op_subtype` `{:?}`", goal.value.value } - } - /// Do not call this query directly: part of the `ProvePredicate` type-op query type_op_prove_predicate( goal: CanonicalTypeOpProvePredicateGoal<'tcx> diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index f2ea32275f9..aca1390935e 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -407,7 +407,7 @@ pub enum ExprKind<'tcx> { arg: ExprId, }, /// A `&raw [const|mut] $place_expr` raw borrow resulting in type `*[const|mut] T`. - AddressOf { + RawBorrow { mutability: hir::Mutability, arg: ExprId, }, diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index f1988810437..e246ecebbec 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -92,7 +92,7 @@ pub fn walk_expr<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>( } VarRef { id: _ } | UpvarRef { closure_def_id: _, var_hir_id: _ } => {} Borrow { arg, borrow_kind: _ } => visitor.visit_expr(&visitor.thir()[arg]), - AddressOf { arg, mutability: _ } => visitor.visit_expr(&visitor.thir()[arg]), + RawBorrow { arg, mutability: _ } => visitor.visit_expr(&visitor.thir()[arg]), Break { value, label: _ } => { if let Some(value) = value { visitor.visit_expr(&visitor.thir()[value]) diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index d54e2ca0a74..a3277fb96d2 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -353,7 +353,7 @@ pub enum ObligationCauseCode<'tcx> { ReturnValue(HirId), /// Opaque return type of this function - OpaqueReturnType(Option<(Ty<'tcx>, Span)>), + OpaqueReturnType(Option<(Ty<'tcx>, HirId)>), /// Block implicit return BlockTailExpression(HirId, hir::MatchSource), diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 401f6da6526..46203ee150f 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -462,7 +462,6 @@ impl_decodable_via_ref! { &'tcx traits::ImplSource<'tcx, ()>, &'tcx mir::Body<'tcx>, &'tcx mir::BorrowCheckResult<'tcx>, - &'tcx mir::coverage::CodeRegion, &'tcx ty::List, &'tcx ty::ListWithCachedTypeInfo>, &'tcx ty::List, diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index c380019e63f..362ff8e988d 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -240,7 +240,7 @@ impl<'tcx> Const<'tcx> { let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic"); - match Self::try_from_lit(tcx, ty, expr) { + match Self::try_from_lit_or_param(tcx, ty, expr) { Some(v) => v, None => ty::Const::new_unevaluated( tcx, @@ -281,7 +281,11 @@ impl<'tcx> Const<'tcx> { } #[instrument(skip(tcx), level = "debug")] - fn try_from_lit(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, expr: &'tcx hir::Expr<'tcx>) -> Option { + fn try_from_lit_or_param( + tcx: TyCtxt<'tcx>, + ty: Ty<'tcx>, + expr: &'tcx hir::Expr<'tcx>, + ) -> Option { // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments // currently have to be wrapped in curly brackets, so it's necessary to special-case. let expr = match &expr.kind { @@ -291,6 +295,22 @@ impl<'tcx> Const<'tcx> { _ => expr, }; + if let hir::ExprKind::Path( + qpath @ hir::QPath::Resolved( + _, + &hir::Path { res: Res::Def(DefKind::ConstParam, _), .. }, + ), + ) = expr.kind + { + if tcx.features().const_arg_path { + span_bug!( + expr.span, + "try_from_lit: received const param which shouldn't be possible" + ); + } + return Some(Const::from_param(tcx, qpath, expr.hir_id)); + }; + let lit_input = match expr.kind { hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }), hir::ExprKind::Unary(hir::UnOp::Neg, expr) => match expr.kind { @@ -305,6 +325,10 @@ impl<'tcx> Const<'tcx> { // mir. match tcx.at(expr.span).lit_to_const(lit_input) { Ok(c) => return Some(c), + Err(_) if lit_input.ty.has_aliases() => { + // allow the `ty` to be an alias type, though we cannot handle it here + return None; + } Err(e) => { tcx.dcx().span_delayed_bug( expr.span, @@ -314,14 +338,6 @@ impl<'tcx> Const<'tcx> { } } - if let hir::ExprKind::Path(hir::QPath::Resolved( - _, - &hir::Path { res: Res::Def(DefKind::ConstParam, _), .. }, - )) = expr.kind - { - span_bug!(expr.span, "try_from_lit: received const param which shouldn't be possible") - } - None } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 971e51be256..8effb67a1f6 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -107,8 +107,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.mk_predefined_opaques_in_body(data) } type DefiningOpaqueTypes = &'tcx ty::List; - type CanonicalGoalEvaluationStepRef = - &'tcx solve::inspect::CanonicalGoalEvaluationStep>; type CanonicalVars = CanonicalVarInfos<'tcx>; fn mk_canonical_var_infos(self, infos: &[ty::CanonicalVarInfo]) -> Self::CanonicalVars { self.mk_canonical_var_infos(infos) @@ -277,13 +275,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.debug_assert_args_compatible(def_id, args); } - fn intern_canonical_goal_evaluation_step( - self, - step: solve::inspect::CanonicalGoalEvaluationStep>, - ) -> &'tcx solve::inspect::CanonicalGoalEvaluationStep> { - self.arena.alloc(step) - } - fn mk_type_list_from_iter(self, args: I) -> T::Output where I: Iterator, @@ -427,7 +418,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { | ty::RawPtr(_, _) | ty::Ref(_, _, _) | ty::FnDef(_, _) - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::Dynamic(_, _, _) | ty::Closure(..) | ty::CoroutineClosure(..) @@ -1588,6 +1579,12 @@ impl<'tcx> TyCtxt<'tcx> { ) } + // Whether the body owner is synthetic, which in this case means it does not correspond to + // meaningful HIR. This is currently used to skip over MIR borrowck. + pub fn is_synthetic_mir(self, def_id: impl Into) -> bool { + matches!(self.def_kind(def_id.into()), DefKind::SyntheticCoroutineBody) + } + /// Returns `true` if the node pointed to by `def_id` is a general coroutine that implements `Coroutine`. /// This means it is neither an `async` or `gen` construct. pub fn is_general_coroutine(self, def_id: DefId) -> bool { @@ -3044,13 +3041,13 @@ impl<'tcx> TyCtxt<'tcx> { match self.named_bound_var(lifetime.hir_id) { Some(resolve_bound_vars::ResolvedArg::EarlyBound(ebv)) => { - let new_parent = self.parent(ebv); + let new_parent = self.local_parent(ebv); // If we map to another opaque, then it should be a parent // of the opaque we mapped from. Continue mapping. if matches!(self.def_kind(new_parent), DefKind::OpaqueTy) { - debug_assert_eq!(self.parent(parent.to_def_id()), new_parent); - opaque_lifetime_param_def_id = ebv.expect_local(); + debug_assert_eq!(self.local_parent(parent), new_parent); + opaque_lifetime_param_def_id = ebv; continue; } @@ -3059,20 +3056,20 @@ impl<'tcx> TyCtxt<'tcx> { self, ty::EarlyParamRegion { index: generics - .param_def_id_to_index(self, ebv) + .param_def_id_to_index(self, ebv.to_def_id()) .expect("early-bound var should be present in fn generics"), - name: self.hir().name(self.local_def_id_to_hir_id(ebv.expect_local())), + name: self.item_name(ebv.to_def_id()), }, ); } Some(resolve_bound_vars::ResolvedArg::LateBound(_, _, lbv)) => { - let new_parent = self.parent(lbv); + let new_parent = self.local_parent(lbv); return ty::Region::new_late_param( self, - new_parent, + new_parent.to_def_id(), ty::BoundRegionKind::BrNamed( - lbv, - self.hir().name(self.local_def_id_to_hir_id(lbv.expect_local())), + lbv.to_def_id(), + self.item_name(lbv.to_def_id()), ), ); } @@ -3177,6 +3174,18 @@ impl<'tcx> TyCtxt<'tcx> { self.impl_trait_header(def_id).map_or(ty::ImplPolarity::Positive, |h| h.polarity) } + pub fn needs_coroutine_by_move_body_def_id(self, def_id: LocalDefId) -> bool { + if let Some(hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure)) = + self.coroutine_kind(def_id) + && let ty::Coroutine(_, args) = self.type_of(def_id).instantiate_identity().kind() + && args.as_coroutine().kind_ty().to_opt_closure_kind() != Some(ty::ClosureKind::FnOnce) + { + true + } else { + false + } + } + /// Whether this is a trait implementation that has `#[diagnostic::do_not_recommend]` pub fn do_not_recommend_impl(self, def_id: DefId) -> bool { matches!(self.def_kind(def_id), DefKind::Impl { of_trait: true }) diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 5acc0b7ac7f..c14dadc68c9 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -6,10 +6,9 @@ use std::ops::ControlFlow; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{into_diag_arg_using_display, Applicability, Diag, DiagArgValue, IntoDiagArg}; -use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; -use rustc_hir::{PredicateOrigin, WherePredicate}; +use rustc_hir::{self as hir, LangItem, PredicateOrigin, WherePredicate}; use rustc_span::{BytePos, Span}; use rustc_type_ir::TyKind::*; @@ -290,8 +289,9 @@ pub fn suggest_constraining_type_params<'a>( let Some(param) = param else { return false }; { - let mut sized_constraints = - constraints.extract_if(|(_, def_id)| *def_id == tcx.lang_items().sized_trait()); + let mut sized_constraints = constraints.extract_if(|(_, def_id)| { + def_id.is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::Sized)) + }); if let Some((_, def_id)) = sized_constraints.next() { applicability = Applicability::MaybeIncorrect; diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 2f9bdb16bb0..d974a86a303 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -130,7 +130,7 @@ impl<'tcx> Ty<'tcx> { DefKind::Ctor(CtorOf::Variant, _) => "enum constructor".into(), _ => "fn item".into(), }, - ty::FnPtr(_) => "fn pointer".into(), + ty::FnPtr(..) => "fn pointer".into(), ty::Dynamic(inner, ..) if let Some(principal) = inner.principal() => { format!("`dyn {}`", tcx.def_path_str(principal.def_id())).into() } @@ -194,7 +194,7 @@ impl<'tcx> Ty<'tcx> { DefKind::Ctor(CtorOf::Variant, _) => "enum constructor".into(), _ => "fn item".into(), }, - ty::FnPtr(_) => "fn pointer".into(), + ty::FnPtr(..) => "fn pointer".into(), ty::Dynamic(..) => "trait object".into(), ty::Closure(..) | ty::CoroutineClosure(..) => "closure".into(), ty::Coroutine(def_id, ..) => { diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index c3430b58406..fc079592583 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -250,9 +250,8 @@ impl FlagComputation { self.add_args(args); } - &ty::FnPtr(fn_sig) => self.bound_computation(fn_sig, |computation, fn_sig| { - computation.add_tys(fn_sig.inputs()); - computation.add_ty(fn_sig.output()); + &ty::FnPtr(sig_tys, _) => self.bound_computation(sig_tys, |computation, sig_tys| { + computation.add_tys(sig_tys.inputs_and_output); }), } } diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 8cb8e9af11c..bbc696e0f08 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -269,7 +269,7 @@ impl<'tcx> Generics { } /// Returns the `GenericParamDef` associated with this `ParamConst`. - pub fn const_param(&'tcx self, param: ParamConst, tcx: TyCtxt<'tcx>) -> &GenericParamDef { + pub fn const_param(&'tcx self, param: ParamConst, tcx: TyCtxt<'tcx>) -> &'tcx GenericParamDef { let param = self.param_at(param.index as usize, tcx); match param.kind { GenericParamDefKind::Const { .. } => param, diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 0496c571f5e..7d5f0f1e9c4 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -141,14 +141,6 @@ pub enum InstanceKind<'tcx> { receiver_by_ref: bool, }, - /// `<[coroutine] as Future>::poll`, but for coroutines produced when `AsyncFnOnce` - /// is called on a coroutine-closure whose closure kind greater than `FnOnce`, or - /// similarly for `AsyncFnMut`. - /// - /// This will select the body that is produced by the `ByMoveBody` transform, and thus - /// take and use all of its upvars by-move rather than by-ref. - CoroutineKindShim { coroutine_def_id: DefId }, - /// Compiler-generated accessor for thread locals which returns a reference to the thread local /// the `DefId` defines. This is used to export thread locals from dylibs on platforms lacking /// native support. @@ -248,7 +240,6 @@ impl<'tcx> InstanceKind<'tcx> { coroutine_closure_def_id: def_id, receiver_by_ref: _, } - | ty::InstanceKind::CoroutineKindShim { coroutine_def_id: def_id } | InstanceKind::DropGlue(def_id, _) | InstanceKind::CloneShim(def_id, _) | InstanceKind::FnPtrAddrShim(def_id, _) @@ -270,7 +261,6 @@ impl<'tcx> InstanceKind<'tcx> { | InstanceKind::Intrinsic(..) | InstanceKind::ClosureOnceShim { .. } | ty::InstanceKind::ConstructCoroutineInClosureShim { .. } - | ty::InstanceKind::CoroutineKindShim { .. } | InstanceKind::DropGlue(..) | InstanceKind::AsyncDropGlueCtorShim(..) | InstanceKind::CloneShim(..) @@ -377,7 +367,6 @@ impl<'tcx> InstanceKind<'tcx> { | InstanceKind::AsyncDropGlueCtorShim(_, Some(_)) => false, InstanceKind::ClosureOnceShim { .. } | InstanceKind::ConstructCoroutineInClosureShim { .. } - | InstanceKind::CoroutineKindShim { .. } | InstanceKind::DropGlue(..) | InstanceKind::AsyncDropGlueCtorShim(..) | InstanceKind::Item(_) @@ -452,7 +441,6 @@ pub fn fmt_instance( InstanceKind::FnPtrShim(_, ty) => write!(f, " - shim({ty})"), InstanceKind::ClosureOnceShim { .. } => write!(f, " - shim"), InstanceKind::ConstructCoroutineInClosureShim { .. } => write!(f, " - shim"), - InstanceKind::CoroutineKindShim { .. } => write!(f, " - shim"), InstanceKind::DropGlue(_, None) => write!(f, " - shim(None)"), InstanceKind::DropGlue(_, Some(ty)) => write!(f, " - shim(Some({ty}))"), InstanceKind::CloneShim(_, ty) => write!(f, " - shim({ty})"), @@ -581,9 +569,9 @@ impl<'tcx> Instance<'tcx> { let mut path = PathBuf::new(); let was_written = if let Some(path2) = written_to_path { path = path2; - Some(()) + true } else { - None + false }; tcx.dcx().emit_fatal(error::TypeLengthLimit { // We don't use `def_span(def_id)` so that diagnostics point @@ -838,7 +826,7 @@ impl<'tcx> Instance<'tcx> { return None; }; - if tcx.lang_items().get(coroutine_callable_item) == Some(trait_item_id) { + if tcx.is_lang_item(trait_item_id, coroutine_callable_item) { let ty::Coroutine(_, id_args) = *tcx.type_of(coroutine_def_id).skip_binder().kind() else { bug!() @@ -850,7 +838,9 @@ impl<'tcx> Instance<'tcx> { Some(Instance { def: ty::InstanceKind::Item(coroutine_def_id), args }) } else { Some(Instance { - def: ty::InstanceKind::CoroutineKindShim { coroutine_def_id }, + def: ty::InstanceKind::Item( + tcx.coroutine_by_move_body_def_id(coroutine_def_id), + ), args, }) } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 684574825e3..d0a9039441d 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -801,7 +801,7 @@ where | ty::Int(_) | ty::Uint(_) | ty::Float(_) - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::Never | ty::FnDef(..) | ty::CoroutineWitness(..) @@ -986,9 +986,11 @@ where safe: None, }) } - ty::FnPtr(fn_sig) if offset.bytes() == 0 => { - tcx.layout_of(param_env.and(Ty::new_fn_ptr(tcx, fn_sig))).ok().map(|layout| { - PointeeInfo { size: layout.size, align: layout.align.abi, safe: None } + ty::FnPtr(..) if offset.bytes() == 0 => { + tcx.layout_of(param_env.and(this.ty)).ok().map(|layout| PointeeInfo { + size: layout.size, + align: layout.align.abi, + safe: None, }) } ty::Ref(_, ty, mt) if offset.bytes() == 0 => { @@ -1102,7 +1104,7 @@ where } fn is_never(this: TyAndLayout<'tcx>) -> bool { - this.ty.kind() == &ty::Never + matches!(this.ty.kind(), ty::Never) } fn is_tuple(this: TyAndLayout<'tcx>) -> bool { diff --git a/compiler/rustc_middle/src/ty/list.rs b/compiler/rustc_middle/src/ty/list.rs index 1a1acf36d77..af76d5b7d92 100644 --- a/compiler/rustc_middle/src/ty/list.rs +++ b/compiler/rustc_middle/src/ty/list.rs @@ -58,7 +58,7 @@ impl Default for &List { } } -extern "C" { +unsafe extern "C" { /// A dummy type used to force `List` to be unsized while not requiring /// references to it be wide pointers. type OpaqueListContents; diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 69b194045ad..e41ea7507ef 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1756,7 +1756,6 @@ impl<'tcx> TyCtxt<'tcx> { | ty::InstanceKind::Virtual(..) | ty::InstanceKind::ClosureOnceShim { .. } | ty::InstanceKind::ConstructCoroutineInClosureShim { .. } - | ty::InstanceKind::CoroutineKindShim { .. } | ty::InstanceKind::DropGlue(..) | ty::InstanceKind::CloneShim(..) | ty::InstanceKind::ThreadLocalShim(..) @@ -1874,7 +1873,8 @@ impl<'tcx> TyCtxt<'tcx> { identity_kind_ty.to_opt_closure_kind(), Some(ClosureKind::Fn | ClosureKind::FnMut) ); - mir.coroutine_by_move_body().unwrap().coroutine_layout_raw() + self.optimized_mir(self.coroutine_by_move_body_def_id(def_id)) + .coroutine_layout_raw() } } } @@ -2150,6 +2150,6 @@ mod size_asserts { use super::*; // tidy-alphabetical-start static_assert_size!(PredicateKind<'_>, 32); - static_assert_size!(WithCachedTypeInfo>, 56); + static_assert_size!(WithCachedTypeInfo>, 48); // tidy-alphabetical-end } diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index 7e1255f606c..be611e19b49 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -59,6 +59,7 @@ trivially_parameterized_over_tcx! { std::string::String, crate::metadata::ModChild, crate::middle::codegen_fn_attrs::CodegenFnAttrs, + crate::middle::codegen_fn_attrs::TargetFeature, crate::middle::debugger_visualizer::DebuggerVisualizerFile, crate::middle::exported_symbols::SymbolExportInfo, crate::middle::lib_features::FeatureStability, diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 6cce79dfdc1..cc746746760 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -290,7 +290,7 @@ fn characteristic_def_id_of_type_cached<'a>( | ty::Int(_) | ty::Uint(_) | ty::Str - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::Alias(..) | ty::Placeholder(..) | ty::Param(_) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 29d72183dd3..f1ff90831b0 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -451,7 +451,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { // 2. For an extern inferred from a path or an indirect crate, // where there is no explicit `extern crate`, we just prepend // the crate name. - match self.tcx().extern_crate(def_id) { + match self.tcx().extern_crate(cnum) { Some(&ExternCrate { src, dependency_of, span, .. }) => match (src, dependency_of) { (ExternCrateSource::Extern(def_id), LOCAL_CRATE) => { // NOTE(eddyb) the only reason `span` might be dummy, @@ -696,7 +696,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { p!(print(sig), " {{", print_value_path(def_id, args), "}}"); } } - ty::FnPtr(ref bare_fn) => p!(print(bare_fn)), + ty::FnPtr(ref sig_tys, hdr) => p!(print(sig_tys.with(hdr))), ty::Infer(infer_ty) => { if self.should_print_verbose() { p!(write("{:?}", ty.kind())); @@ -1145,7 +1145,9 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { let term = if let Some(ty) = term.skip_binder().as_type() && let ty::Alias(ty::Projection, proj) = ty.kind() && let Some(assoc) = tcx.opt_associated_item(proj.def_id) - && assoc.trait_container(tcx) == tcx.lang_items().coroutine_trait() + && assoc + .trait_container(tcx) + .is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::Coroutine)) && assoc.name == rustc_span::sym::Return { if let ty::Coroutine(_, args) = args.type_at(0).kind() { @@ -1678,7 +1680,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { } } } - ty::FnPtr(_) => { + ty::FnPtr(..) => { // FIXME: We should probably have a helper method to share code with the "Byte strings" // printing above (which also has to handle pointers to all sorts of things). if let Some(GlobalAlloc::Function { instance, .. }) = @@ -1741,7 +1743,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { p!(write("{:?}", char::try_from(int).unwrap())) } // Pointer types - ty::Ref(..) | ty::RawPtr(_, _) | ty::FnPtr(_) => { + ty::Ref(..) | ty::RawPtr(_, _) | ty::FnPtr(..) => { let data = int.to_bits(self.tcx().data_layout.pointer_size); self.typed_value( |this| { @@ -3117,7 +3119,10 @@ define_print! { ty::ExistentialProjection<'tcx> { let name = cx.tcx().associated_item(self.def_id).name; - p!(write("{} = ", name), print(self.term)) + // The args don't contain the self ty (as it has been erased) but the corresp. + // generics do as the trait always has a self ty param. We need to offset. + let args = &self.args[cx.tcx().generics_of(self.def_id).parent_count - 1..]; + p!(path_generic_args(|cx| write!(cx, "{name}"), args), " = ", print(self.term)) } ty::ProjectionPredicate<'tcx> { @@ -3245,10 +3250,8 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N let mut seen_defs: DefIdSet = Default::default(); for &cnum in tcx.crates(()).iter() { - let def_id = cnum.as_def_id(); - // Ignore crates that are not direct dependencies. - match tcx.extern_crate(def_id) { + match tcx.extern_crate(cnum) { None => continue, Some(extern_crate) => { if !extern_crate.is_direct() { @@ -3257,7 +3260,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N } } - queue.push(def_id); + queue.push(cnum.as_def_id()); } // Iterate external crate defs but be mindful about visibility diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 8fb44a5f0b1..80b33c2cda9 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -374,7 +374,7 @@ impl<'tcx> TypeSuperFoldable> for Ty<'tcx> { ), ty::Tuple(ts) => ty::Tuple(ts.try_fold_with(folder)?), ty::FnDef(def_id, args) => ty::FnDef(def_id, args.try_fold_with(folder)?), - ty::FnPtr(f) => ty::FnPtr(f.try_fold_with(folder)?), + ty::FnPtr(sig_tys, hdr) => ty::FnPtr(sig_tys.try_fold_with(folder)?, hdr), ty::Ref(r, ty, mutbl) => { ty::Ref(r.try_fold_with(folder)?, ty.try_fold_with(folder)?, mutbl) } @@ -424,7 +424,7 @@ impl<'tcx> TypeSuperVisitable> for Ty<'tcx> { } ty::Tuple(ts) => ts.visit_with(visitor), ty::FnDef(_, args) => args.visit_with(visitor), - ty::FnPtr(ref f) => f.visit_with(visitor), + ty::FnPtr(ref sig_tys, _) => sig_tys.visit_with(visitor), ty::Ref(r, ty, _) => { try_visit!(r.visit_with(visitor)); ty.visit_with(visitor) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 8781a670acb..d60bfb9faa1 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -658,7 +658,8 @@ impl<'tcx> Ty<'tcx> { #[inline] pub fn new_fn_ptr(tcx: TyCtxt<'tcx>, fty: PolyFnSig<'tcx>) -> Ty<'tcx> { - Ty::new(tcx, FnPtr(fty)) + let (sig_tys, hdr) = fty.split(); + Ty::new(tcx, FnPtr(sig_tys, hdr)) } #[inline] @@ -969,6 +970,10 @@ impl<'tcx> rustc_type_ir::inherent::Ty> for Ty<'tcx> { /// Type utilities impl<'tcx> Ty<'tcx> { + // It would be nicer if this returned the value instead of a reference, + // like how `Predicate::kind` and `Region::kind` do. (It would result in + // many fewer subsequent dereferences.) But that gives a small but + // noticeable performance hit. See #126069 for details. #[inline(always)] pub fn kind(self) -> &'tcx TyKind<'tcx> { self.0.0 @@ -1182,7 +1187,7 @@ impl<'tcx> Ty<'tcx> { | Float(_) | Uint(_) | FnDef(..) - | FnPtr(_) + | FnPtr(..) | RawPtr(_, _) | Infer(IntVar(_) | FloatVar(_)) ) @@ -1333,7 +1338,7 @@ impl<'tcx> Ty<'tcx> { pub fn fn_sig(self, tcx: TyCtxt<'tcx>) -> PolyFnSig<'tcx> { match self.kind() { FnDef(def_id, args) => tcx.fn_sig(*def_id).instantiate(tcx, args), - FnPtr(f) => *f, + FnPtr(sig_tys, hdr) => sig_tys.with(*hdr), Error(_) => { // ignore errors (#54954) Binder::dummy(ty::FnSig { @@ -1352,12 +1357,12 @@ impl<'tcx> Ty<'tcx> { #[inline] pub fn is_fn(self) -> bool { - matches!(self.kind(), FnDef(..) | FnPtr(_)) + matches!(self.kind(), FnDef(..) | FnPtr(..)) } #[inline] pub fn is_fn_ptr(self) -> bool { - matches!(self.kind(), FnPtr(_)) + matches!(self.kind(), FnPtr(..)) } #[inline] @@ -1599,7 +1604,7 @@ impl<'tcx> Ty<'tcx> { | ty::Bool | ty::Float(_) | ty::FnDef(..) - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::RawPtr(..) | ty::Char | ty::Ref(..) @@ -1791,7 +1796,7 @@ impl<'tcx> Ty<'tcx> { | ty::Bool | ty::Float(_) | ty::FnDef(..) - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::RawPtr(..) | ty::Char | ty::Ref(..) @@ -1915,7 +1920,7 @@ impl<'tcx> Ty<'tcx> { pub fn is_c_void(self, tcx: TyCtxt<'_>) -> bool { match self.kind() { - ty::Adt(adt, _) => tcx.lang_items().get(LangItem::CVoid) == Some(adt.did()), + ty::Adt(adt, _) => tcx.is_lang_item(adt.did(), LangItem::CVoid), _ => false, } } @@ -1941,7 +1946,7 @@ impl<'tcx> Ty<'tcx> { | RawPtr(_, _) | Ref(_, _, _) | FnDef(_, _) - | FnPtr(_) + | FnPtr(..) | Dynamic(_, _, _) | Closure(_, _) | CoroutineClosure(_, _) @@ -1955,9 +1960,12 @@ impl<'tcx> Ty<'tcx> { } impl<'tcx> rustc_type_ir::inherent::Tys> for &'tcx ty::List> { - fn split_inputs_and_output(self) -> (&'tcx [Ty<'tcx>], Ty<'tcx>) { - let (output, inputs) = self.split_last().unwrap(); - (inputs, *output) + fn inputs(self) -> &'tcx [Ty<'tcx>] { + self.split_last().unwrap().1 + } + + fn output(self) -> Ty<'tcx> { + *self.split_last().unwrap().0 } } @@ -1969,6 +1977,6 @@ mod size_asserts { use super::*; // tidy-alphabetical-start static_assert_size!(ty::RegionKind<'_>, 24); - static_assert_size!(ty::TyKind<'_>, 32); + static_assert_size!(ty::TyKind<'_>, 24); // tidy-alphabetical-end } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 6be3dc423de..efbccca77c1 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -296,7 +296,7 @@ impl<'tcx> TyCtxt<'tcx> { ) -> (Ty<'tcx>, Ty<'tcx>) { let (mut a, mut b) = (source, target); loop { - match (&a.kind(), &b.kind()) { + match (a.kind(), b.kind()) { (&ty::Adt(a_def, a_args), &ty::Adt(b_def, b_args)) if a_def == b_def && a_def.is_struct() => { @@ -859,7 +859,7 @@ impl<'tcx> TyCtxt<'tcx> { // If `extern_crate` is `None`, then the crate was injected (e.g., by the allocator). // Treat that kind of crate as "indirect", since it's an implementation detail of // the language. - || self.extern_crate(key.as_def_id()).is_some_and(|e| e.is_direct()) + || self.extern_crate(key).is_some_and(|e| e.is_direct()) } /// Whether the item has a host effect param. This is different from `TyCtxt::is_const`, @@ -1272,7 +1272,7 @@ impl<'tcx> Ty<'tcx> { | ty::RawPtr(_, _) | ty::FnDef(..) | ty::Error(_) - | ty::FnPtr(_) => true, + | ty::FnPtr(..) => true, ty::Tuple(fields) => fields.iter().all(Self::is_trivially_freeze), ty::Pat(ty, _) | ty::Slice(ty) | ty::Array(ty, _) => ty.is_trivially_freeze(), ty::Adt(..) @@ -1312,7 +1312,7 @@ impl<'tcx> Ty<'tcx> { | ty::RawPtr(_, _) | ty::FnDef(..) | ty::Error(_) - | ty::FnPtr(_) => true, + | ty::FnPtr(..) => true, ty::Tuple(fields) => fields.iter().all(Self::is_trivially_unpin), ty::Pat(ty, _) | ty::Slice(ty) | ty::Array(ty, _) => ty.is_trivially_unpin(), ty::Adt(..) @@ -1351,7 +1351,7 @@ impl<'tcx> Ty<'tcx> { | ty::Ref(..) | ty::RawPtr(..) | ty::FnDef(..) - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::Infer(ty::FreshIntTy(_)) | ty::Infer(ty::FreshFloatTy(_)) => AsyncDropGlueMorphology::Noop, @@ -1534,7 +1534,7 @@ impl<'tcx> Ty<'tcx> { ty::Pat(..) | ty::Ref(..) | ty::Array(..) | ty::Slice(_) | ty::Tuple(..) => true, // Raw pointers use bitwise comparison. - ty::RawPtr(_, _) | ty::FnPtr(_) => true, + ty::RawPtr(_, _) | ty::FnPtr(..) => true, // Floating point numbers are not `Eq`. ty::Float(_) => false, @@ -1665,7 +1665,7 @@ pub fn needs_drop_components_with_async<'tcx>( | ty::Float(_) | ty::Never | ty::FnDef(..) - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::Char | ty::RawPtr(_, _) | ty::Ref(..) @@ -1732,7 +1732,7 @@ pub fn is_trivially_const_drop(ty: Ty<'_>) -> bool { | ty::RawPtr(_, _) | ty::Ref(..) | ty::FnDef(..) - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::Never | ty::Foreign(_) => true, diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index 2dd7a96f192..abd6df17514 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -189,9 +189,10 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) stack.extend(args.iter().rev()); } ty::Tuple(ts) => stack.extend(ts.iter().rev().map(GenericArg::from)), - ty::FnPtr(sig) => { - stack.push(sig.skip_binder().output().into()); - stack.extend(sig.skip_binder().inputs().iter().copied().rev().map(|ty| ty.into())); + ty::FnPtr(sig_tys, _hdr) => { + stack.extend( + sig_tys.skip_binder().inputs_and_output.iter().rev().map(|ty| ty.into()), + ); } }, GenericArgKind::Lifetime(_) => {} diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index dda4debecec..a42e8ff0168 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -30,7 +30,7 @@ mir_build_call_to_deprecated_safe_fn_requires_unsafe = call to deprecated safe function `{$function}` is unsafe and requires unsafe block .note = consult the function's documentation for information on how to avoid undefined behavior .label = call to unsafe function - .suggestion = you can wrap the call in an `unsafe` block if you can guarantee the code is only ever called from single-threaded code + .suggestion = you can wrap the call in an `unsafe` block if you can guarantee {$guarantee} mir_build_call_to_fn_with_requires_unsafe = call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block @@ -125,6 +125,17 @@ mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior .label = initializing type with `rustc_layout_scalar_valid_range` attr +mir_build_initializing_type_with_target_feature_requires_unsafe = + initializing type with `target_feature` attr is unsafe and requires unsafe block + .note = this struct can only be constructed if the corresponding `target_feature`s are available + .label = initializing type with `target_feature` attr + +mir_build_initializing_type_with_target_feature_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = + initializing type with `target_feature` attr is unsafe and requires unsafe function or block + .note = this struct can only be constructed if the corresponding `target_feature`s are available + .label = initializing type with `target_feature` attr + + mir_build_inline_assembly_requires_unsafe = use of inline assembly is unsafe and requires unsafe block .note = inline assembly is entirely unchecked and can cause undefined behavior @@ -327,14 +338,17 @@ mir_build_union_pattern = cannot use unions in constant patterns mir_build_unreachable_making_this_unreachable = collectively making this unreachable +mir_build_unreachable_making_this_unreachable_n_more = ...and {$covered_by_many_n_more_count} other patterns collectively make this unreachable + mir_build_unreachable_matches_same_values = matches some of the same values mir_build_unreachable_pattern = unreachable pattern - .label = unreachable pattern - .unreachable_matches_no_values = this pattern matches no values because `{$ty}` is uninhabited + .label = no value can reach this + .unreachable_matches_no_values = matches no values because `{$matches_no_values_ty}` is uninhabited + .unreachable_uninhabited_note = to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types .unreachable_covered_by_catchall = matches any value - .unreachable_covered_by_one = matches all the values already - .unreachable_covered_by_many = these patterns collectively make the last one unreachable + .unreachable_covered_by_one = matches all the relevant values + .unreachable_covered_by_many = multiple earlier patterns match some of the same values mir_build_unsafe_fn_safe_body = an unsafe function restricts its caller, but its body is safe by default mir_build_unsafe_not_inherited = items do not inherit unsafety from separate enclosing items @@ -384,6 +398,11 @@ mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe = .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior .label = initializing type with `rustc_layout_scalar_valid_range` attr +mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_target_feature_requires_unsafe = + initializing type with `target_feature` attr is unsafe and requires unsafe block + .note = this struct can only be constructed if the corresponding `target_feature`s are available + .label = initializing type with `target_feature` attr + mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe = use of inline assembly is unsafe and requires unsafe block .note = inline assembly is entirely unchecked and can cause undefined behavior diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs index 56896d945e5..0b13ceb574d 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs @@ -244,8 +244,8 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { ExprKind::Borrow { borrow_kind, arg } => Ok( Rvalue::Ref(self.tcx.lifetimes.re_erased, *borrow_kind, self.parse_place(*arg)?) ), - ExprKind::AddressOf { mutability, arg } => Ok( - Rvalue::AddressOf(*mutability, self.parse_place(*arg)?) + ExprKind::RawBorrow { mutability, arg } => Ok( + Rvalue::RawPtr(*mutability, self.parse_place(*arg)?) ), ExprKind::Binary { op, lhs, rhs } => Ok( Rvalue::BinaryOp(*op, Box::new((self.parse_operand(*lhs)?, self.parse_operand(*rhs)?))) diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index 4430aab73a8..4f1166f9111 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -127,7 +127,7 @@ fn lit_to_mir_constant<'tcx>( Ok(ConstValue::Scalar(Scalar::from_uint(result, width))) }; - let value = match (lit, &ty.kind()) { + let value = match (lit, ty.kind()) { (ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => { let s = s.as_str(); let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes()); diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index b80d9de70c8..07784982631 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -542,7 +542,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | ExprKind::PointerCoercion { .. } | ExprKind::Repeat { .. } | ExprKind::Borrow { .. } - | ExprKind::AddressOf { .. } + | ExprKind::RawBorrow { .. } | ExprKind::Match { .. } | ExprKind::If { .. } | ExprKind::Loop { .. } diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 379d2140c09..0c9571da3cf 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -512,7 +512,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | ExprKind::NeverToAny { .. } | ExprKind::Use { .. } | ExprKind::Borrow { .. } - | ExprKind::AddressOf { .. } + | ExprKind::RawBorrow { .. } | ExprKind::Adt { .. } | ExprKind::Loop { .. } | ExprKind::LogicalOp { .. } diff --git a/compiler/rustc_mir_build/src/build/expr/category.rs b/compiler/rustc_mir_build/src/build/expr/category.rs index e07ba6b6e93..e0349e3e3f6 100644 --- a/compiler/rustc_mir_build/src/build/expr/category.rs +++ b/compiler/rustc_mir_build/src/build/expr/category.rs @@ -51,7 +51,7 @@ impl Category { | ExprKind::Use { .. } | ExprKind::Adt { .. } | ExprKind::Borrow { .. } - | ExprKind::AddressOf { .. } + | ExprKind::RawBorrow { .. } | ExprKind::Yield { .. } | ExprKind::Call { .. } | ExprKind::InlineAsm { .. } => Some(Category::Rvalue(RvalueFunc::Into)), diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 01b32b8e05e..1c805ed20cc 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -303,12 +303,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.cfg.push_assign(block, source_info, destination, borrow); block.unit() } - ExprKind::AddressOf { mutability, arg } => { + ExprKind::RawBorrow { mutability, arg } => { let place = match mutability { hir::Mutability::Not => this.as_read_only_place(block, arg), hir::Mutability::Mut => this.as_place(block, arg), }; - let address_of = Rvalue::AddressOf(mutability, unpack!(block = place)); + let address_of = Rvalue::RawPtr(mutability, unpack!(block = place)); this.cfg.push_assign(block, source_info, destination, address_of); block.unit() } diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index 8546a2539d7..693037d03e0 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -748,7 +748,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.cfg.terminate(block, source_info, TerminatorKind::UnwindResume); } - /// Sets up the drops for explict tail calls. + /// Sets up the drops for explicit tail calls. /// /// Unlike other kinds of early exits, tail calls do not go through the drop tree. /// Instead, all scheduled drops are immediately added to the CFG. diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 54a4204da71..60cd49b88b4 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -96,9 +96,32 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { // from an edition before 2024. &UnsafeOpKind::CallToUnsafeFunction(Some(id)) if !span.at_least_rust_2024() - && self.tcx.has_attr(id, sym::rustc_deprecated_safe_2024) => + && let Some(attr) = self.tcx.get_attr(id, sym::rustc_deprecated_safe_2024) => { + let suggestion = attr + .meta_item_list() + .unwrap_or_default() + .into_iter() + .find(|item| item.has_name(sym::audit_that)) + .map(|item| { + item.value_str().expect( + "`#[rustc_deprecated_safe_2024(audit_that)]` must have a string value", + ) + }); + let sm = self.tcx.sess.source_map(); + let guarantee = suggestion + .as_ref() + .map(|suggestion| format!("that {}", suggestion)) + .unwrap_or_else(|| String::from("its unsafe preconditions")); + let suggestion = suggestion + .and_then(|suggestion| { + sm.indentation_before(span).map(|indent| { + format!("{}// TODO: Audit that {}.\n", indent, suggestion) // ignore-tidy-todo + }) + }) + .unwrap_or_default(); + self.tcx.emit_node_span_lint( DEPRECATED_SAFE_2024, self.hir_context, @@ -106,8 +129,9 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { CallToDeprecatedSafeFnRequiresUnsafe { span, function: with_no_trimmed_paths!(self.tcx.def_path_str(id)), + guarantee, sub: CallToDeprecatedSafeFnRequiresUnsafeSub { - indent: sm.indentation_before(span).unwrap_or_default(), + start_of_line_suggestion: suggestion, start_of_line: sm.span_extend_to_line(span).shrink_to_lo(), left: span.shrink_to_lo(), right: span.shrink_to_hi(), @@ -373,7 +397,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { | ExprKind::Scope { .. } | ExprKind::Cast { .. } => {} - ExprKind::AddressOf { .. } + ExprKind::RawBorrow { .. } | ExprKind::Adt { .. } | ExprKind::Array { .. } | ExprKind::Binary { .. } @@ -437,14 +461,18 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { }; self.requires_unsafe(expr.span, CallToUnsafeFunction(func_id)); } else if let &ty::FnDef(func_did, _) = self.thir[fun].ty.kind() { - // If the called function has target features the calling function hasn't, + // If the called function has explicit target features the calling function hasn't, // the call requires `unsafe`. Don't check this on wasm // targets, though. For more information on wasm see the // is_like_wasm check in hir_analysis/src/collect.rs + // Implicit target features are OK because they are either a consequence of some + // explicit target feature (which is checked to be present in the caller) or + // come from a witness argument. let callee_features = &self.tcx.codegen_fn_attrs(func_did).target_features; if !self.tcx.sess.target.options.is_like_wasm && !callee_features.iter().all(|feature| { - self.body_target_features.iter().any(|f| f.name == feature.name) + feature.implied + || self.body_target_features.iter().any(|f| f.name == feature.name) }) { let missing: Vec<_> = callee_features @@ -474,7 +502,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { } } } - ExprKind::AddressOf { arg, .. } => { + ExprKind::RawBorrow { arg, .. } => { if let ExprKind::Scope { value: arg, .. } = self.thir[arg].kind // THIR desugars UNSAFE_STATIC into *UNSAFE_STATIC_REF, where // UNSAFE_STATIC_REF holds the addr of the UNSAFE_STATIC, so: take two steps @@ -518,10 +546,16 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { user_ty: _, fields: _, base: _, - }) => match self.tcx.layout_scalar_valid_range(adt_def.did()) { - (Bound::Unbounded, Bound::Unbounded) => {} - _ => self.requires_unsafe(expr.span, InitializingTypeWith), - }, + }) => { + match self.tcx.layout_scalar_valid_range(adt_def.did()) { + (Bound::Unbounded, Bound::Unbounded) => {} + _ => self.requires_unsafe(expr.span, InitializingTypeWith), + } + if !self.tcx.struct_target_features(adt_def.did()).is_empty() { + self.requires_unsafe(expr.span, ConstructingTargetFeaturesType) + } + } + ExprKind::Closure(box ClosureExpr { closure_id, args: _, @@ -623,6 +657,7 @@ enum UnsafeOpKind { CallToUnsafeFunction(Option), UseOfInlineAssembly, InitializingTypeWith, + ConstructingTargetFeaturesType, UseOfMutableStatic, UseOfExternStatic, DerefOfRawPointer, @@ -704,6 +739,15 @@ impl UnsafeOpKind { unsafe_not_inherited_note, }, ), + ConstructingTargetFeaturesType => tcx.emit_node_span_lint( + UNSAFE_OP_IN_UNSAFE_FN, + hir_id, + span, + UnsafeOpInUnsafeFnInitializingTypeWithTargetFeatureRequiresUnsafe { + span, + unsafe_not_inherited_note, + }, + ), UseOfMutableStatic => tcx.emit_node_span_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, @@ -769,7 +813,7 @@ impl UnsafeOpKind { missing.iter().map(|feature| Cow::from(feature.to_string())).collect(), ), missing_target_features_count: missing.len(), - note: if build_enabled.is_empty() { None } else { Some(()) }, + note: !build_enabled.is_empty(), build_target_features: DiagArgValue::StrListSepByAnd( build_enabled .iter() @@ -861,6 +905,20 @@ impl UnsafeOpKind { unsafe_not_inherited_note, }); } + ConstructingTargetFeaturesType if unsafe_op_in_unsafe_fn_allowed => { + dcx.emit_err( + InitializingTypeWithTargetFeatureRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + span, + unsafe_not_inherited_note, + }, + ); + } + ConstructingTargetFeaturesType => { + dcx.emit_err(InitializingTypeWithTargetFeatureRequiresUnsafe { + span, + unsafe_not_inherited_note, + }); + } UseOfMutableStatic if unsafe_op_in_unsafe_fn_allowed => { dcx.emit_err(UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span, @@ -934,7 +992,7 @@ impl UnsafeOpKind { missing.iter().map(|feature| Cow::from(feature.to_string())).collect(), ), missing_target_features_count: missing.len(), - note: if build_enabled.is_empty() { None } else { Some(()) }, + note: !build_enabled.is_empty(), build_target_features: DiagArgValue::StrListSepByAnd( build_enabled .iter() @@ -953,7 +1011,7 @@ impl UnsafeOpKind { missing.iter().map(|feature| Cow::from(feature.to_string())).collect(), ), missing_target_features_count: missing.len(), - note: if build_enabled.is_empty() { None } else { Some(()) }, + note: !build_enabled.is_empty(), build_target_features: DiagArgValue::StrListSepByAnd( build_enabled .iter() diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 42eca71ca3f..e7d6239aa9b 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -28,6 +28,7 @@ pub(crate) struct CallToDeprecatedSafeFnRequiresUnsafe { #[label] pub(crate) span: Span, pub(crate) function: String, + pub(crate) guarantee: String, #[subdiagnostic] pub(crate) sub: CallToDeprecatedSafeFnRequiresUnsafeSub, } @@ -35,10 +36,8 @@ pub(crate) struct CallToDeprecatedSafeFnRequiresUnsafe { #[derive(Subdiagnostic)] #[multipart_suggestion(mir_build_suggestion, applicability = "machine-applicable")] pub(crate) struct CallToDeprecatedSafeFnRequiresUnsafeSub { - pub(crate) indent: String, - #[suggestion_part( - code = "{indent}// TODO: Audit that the environment access only happens in single-threaded code.\n" // ignore-tidy-todo - )] + pub(crate) start_of_line_suggestion: String, + #[suggestion_part(code = "{start_of_line_suggestion}")] pub(crate) start_of_line: Span, #[suggestion_part(code = "unsafe {{ ")] pub(crate) left: Span, @@ -87,6 +86,16 @@ pub(crate) struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { pub(crate) unsafe_not_inherited_note: Option, } +#[derive(LintDiagnostic)] +#[diag(mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_target_feature_requires_unsafe, code = E0133)] +#[note] +pub(crate) struct UnsafeOpInUnsafeFnInitializingTypeWithTargetFeatureRequiresUnsafe { + #[label] + pub(crate) span: Span, + #[subdiagnostic] + pub(crate) unsafe_not_inherited_note: Option, +} + #[derive(LintDiagnostic)] #[diag(mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe, code = E0133)] #[note] @@ -162,7 +171,7 @@ pub(crate) struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe { pub(crate) missing_target_features: DiagArgValue, pub(crate) missing_target_features_count: usize, #[note] - pub(crate) note: Option<()>, + pub(crate) note: bool, pub(crate) build_target_features: DiagArgValue, pub(crate) build_target_features_count: usize, #[subdiagnostic] @@ -251,6 +260,17 @@ pub(crate) struct InitializingTypeWithRequiresUnsafe { pub(crate) unsafe_not_inherited_note: Option, } +#[derive(Diagnostic)] +#[diag(mir_build_initializing_type_with_target_feature_requires_unsafe, code = E0133)] +#[note] +pub(crate) struct InitializingTypeWithTargetFeatureRequiresUnsafe { + #[primary_span] + #[label] + pub(crate) span: Span, + #[subdiagnostic] + pub(crate) unsafe_not_inherited_note: Option, +} + #[derive(Diagnostic)] #[diag( mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, @@ -265,6 +285,20 @@ pub(crate) struct InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { pub(crate) unsafe_not_inherited_note: Option, } +#[derive(Diagnostic)] +#[diag( + mir_build_initializing_type_with_target_feature_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, + code = E0133 +)] +#[note] +pub(crate) struct InitializingTypeWithTargetFeatureRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + #[primary_span] + #[label] + pub(crate) span: Span, + #[subdiagnostic] + pub(crate) unsafe_not_inherited_note: Option, +} + #[derive(Diagnostic)] #[diag(mir_build_mutable_static_requires_unsafe, code = E0133)] #[note] @@ -414,7 +448,7 @@ pub(crate) struct CallToFunctionWithRequiresUnsafe { pub(crate) missing_target_features: DiagArgValue, pub(crate) missing_target_features_count: usize, #[note] - pub(crate) note: Option<()>, + pub(crate) note: bool, pub(crate) build_target_features: DiagArgValue, pub(crate) build_target_features_count: usize, #[subdiagnostic] @@ -432,7 +466,7 @@ pub(crate) struct CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { pub(crate) missing_target_features: DiagArgValue, pub(crate) missing_target_features_count: usize, #[note] - pub(crate) note: Option<()>, + pub(crate) note: bool, pub(crate) build_target_features: DiagArgValue, pub(crate) build_target_features_count: usize, #[subdiagnostic] @@ -494,7 +528,7 @@ pub(crate) struct NonExhaustivePatternsTypeNotEmpty<'p, 'tcx, 'm> { } impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'_, G> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { let mut diag = Diag::new(dcx, level, fluent::mir_build_non_exhaustive_patterns_type_not_empty); diag.span(self.scrut_span); @@ -587,20 +621,18 @@ pub(crate) struct NonConstPath { pub(crate) struct UnreachablePattern<'tcx> { #[label] pub(crate) span: Option, - #[subdiagnostic] - pub(crate) matches_no_values: Option>, + #[label(mir_build_unreachable_matches_no_values)] + pub(crate) matches_no_values: Option, + pub(crate) matches_no_values_ty: Ty<'tcx>, + #[note(mir_build_unreachable_uninhabited_note)] + pub(crate) uninhabited_note: Option<()>, #[label(mir_build_unreachable_covered_by_catchall)] pub(crate) covered_by_catchall: Option, #[label(mir_build_unreachable_covered_by_one)] pub(crate) covered_by_one: Option, #[note(mir_build_unreachable_covered_by_many)] pub(crate) covered_by_many: Option, -} - -#[derive(Subdiagnostic)] -#[note(mir_build_unreachable_matches_no_values)] -pub(crate) struct UnreachableMatchesNoValues<'tcx> { - pub(crate) ty: Ty<'tcx>, + pub(crate) covered_by_many_n_more_count: usize, } #[derive(Diagnostic)] @@ -624,7 +656,7 @@ pub(crate) struct LowerRangeBoundMustBeLessThanOrEqualToUpper { #[label] pub(crate) span: Span, #[note(mir_build_teach_note)] - pub(crate) teach: Option<()>, + pub(crate) teach: bool, } #[derive(Diagnostic)] @@ -866,7 +898,7 @@ pub(crate) struct PatternNotCovered<'s, 'tcx> { #[subdiagnostic] pub(crate) adt_defined_here: Option>, #[note(mir_build_privately_uninhabited)] - pub(crate) witness_1_is_privately_uninhabited: Option<()>, + pub(crate) witness_1_is_privately_uninhabited: bool, #[note(mir_build_pattern_ty)] pub(crate) _p: (), pub(crate) pattern_ty: Ty<'tcx>, diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index 7b94867114d..b8877a64e47 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -29,7 +29,7 @@ pub(crate) fn lit_to_const<'tcx>( .unwrap_or_else(|| bug!("expected to create ScalarInt from uint {:?}", result))) }; - let valtree = match (lit, &ty.kind()) { + let valtree = match (lit, ty.kind()) { (ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => { let str_bytes = s.as_str().as_bytes(); ty::ValTree::from_raw_bytes(tcx, str_bytes) diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index d4de5fac96e..89f98a40201 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -143,7 +143,7 @@ impl<'tcx> Cx<'tcx> { arg: self.thir.exprs.push(expr), }, Adjust::Borrow(AutoBorrow::RawPtr(mutability)) => { - ExprKind::AddressOf { mutability, arg: self.thir.exprs.push(expr) } + ExprKind::RawBorrow { mutability, arg: self.thir.exprs.push(expr) } } Adjust::DynStar => ExprKind::Cast { source: self.thir.exprs.push(expr) }, }; @@ -218,12 +218,7 @@ impl<'tcx> Cx<'tcx> { let lhs = self.thir.exprs.push(Expr { temp_lifetime, ty: discr_ty, span, kind }); let bin = ExprKind::Binary { op: BinOp::Add, lhs, rhs: offset }; - self.thir.exprs.push(Expr { - temp_lifetime, - ty: discr_ty, - span: span, - kind: bin, - }) + self.thir.exprs.push(Expr { temp_lifetime, ty: discr_ty, span, kind: bin }) } None => offset, }; @@ -396,7 +391,7 @@ impl<'tcx> Cx<'tcx> { } hir::ExprKind::AddrOf(hir::BorrowKind::Raw, mutability, arg) => { - ExprKind::AddressOf { mutability, arg: self.mirror_expr(arg) } + ExprKind::RawBorrow { mutability, arg: self.mirror_expr(arg) } } hir::ExprKind::Block(blk, _) => ExprKind::Block { block: self.mirror_block(blk) }, diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index 6120b1453cf..5b5f97cb514 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -8,7 +8,7 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; -use rustc_hir::{HirId, Node}; +use rustc_hir::HirId; use rustc_middle::bug; use rustc_middle::middle::region; use rustc_middle::thir::*; @@ -110,11 +110,7 @@ impl<'tcx> Cx<'tcx> { } #[instrument(level = "debug", skip(self))] - fn pattern_from_hir(&mut self, p: &hir::Pat<'_>) -> Box> { - let p = match self.tcx.hir_node(p.hir_id) { - Node::Pat(p) => p, - node => bug!("pattern became {:?}", node), - }; + fn pattern_from_hir(&mut self, p: &'tcx hir::Pat<'tcx>) -> Box> { pat_from_hir(self.tcx, self.param_env, self.typeck_results(), p) } diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 07bf222fcca..4c066a68ef9 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -325,7 +325,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { Assign { .. } | AssignOp { .. } | InlineAsm { .. } | Let { .. } => true, // These evaluate to a value. - AddressOf { .. } + RawBorrow { .. } | Adt { .. } | Array { .. } | Binary { .. } @@ -702,10 +702,12 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { && adt.is_enum() && let Constructor::Variant(variant_index) = witness_1.ctor() { - let variant = adt.variant(*variant_index); - let inhabited = variant.inhabited_predicate(self.tcx, *adt).instantiate(self.tcx, args); - assert!(inhabited.apply(self.tcx, cx.param_env, cx.module)); - !inhabited.apply_ignore_module(self.tcx, cx.param_env) + let variant_inhabited = adt + .variant(*variant_index) + .inhabited_predicate(self.tcx, *adt) + .instantiate(self.tcx, args); + variant_inhabited.apply(self.tcx, cx.param_env, cx.module) + && !variant_inhabited.apply_ignore_module(self.tcx, cx.param_env) } else { false }; @@ -716,7 +718,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { uncovered: Uncovered::new(pat.span, &cx, witnesses), inform, interpreted_as_const, - witness_1_is_privately_uninhabited: witness_1_is_privately_uninhabited.then_some(()), + witness_1_is_privately_uninhabited, _p: (), pattern_ty, let_suggestion, @@ -915,22 +917,28 @@ fn report_unreachable_pattern<'p, 'tcx>( pat: &DeconstructedPat<'p, 'tcx>, explanation: &RedundancyExplanation<'p, 'tcx>, ) { + static CAP_COVERED_BY_MANY: usize = 4; let pat_span = pat.data().span; let mut lint = UnreachablePattern { span: Some(pat_span), matches_no_values: None, + matches_no_values_ty: **pat.ty(), + uninhabited_note: None, covered_by_catchall: None, covered_by_one: None, covered_by_many: None, + covered_by_many_n_more_count: 0, }; match explanation.covered_by.as_slice() { [] => { // Empty pattern; we report the uninhabited type that caused the emptiness. lint.span = None; // Don't label the pattern itself + lint.uninhabited_note = Some(()); // Give a link about empty types + lint.matches_no_values = Some(pat_span); pat.walk(&mut |subpat| { let ty = **subpat.ty(); if cx.is_uninhabited(ty) { - lint.matches_no_values = Some(UnreachableMatchesNoValues { ty }); + lint.matches_no_values_ty = ty; false // No need to dig further. } else if matches!(subpat.ctor(), Constructor::Ref | Constructor::UnionField) { false // Don't explore further since they are not by-value. @@ -946,15 +954,27 @@ fn report_unreachable_pattern<'p, 'tcx>( lint.covered_by_one = Some(covering_pat.data().span); } covering_pats => { + let mut iter = covering_pats.iter(); let mut multispan = MultiSpan::from_span(pat_span); - for p in covering_pats { + for p in iter.by_ref().take(CAP_COVERED_BY_MANY) { multispan.push_span_label( p.data().span, fluent::mir_build_unreachable_matches_same_values, ); } - multispan - .push_span_label(pat_span, fluent::mir_build_unreachable_making_this_unreachable); + let remain = iter.count(); + if remain == 0 { + multispan.push_span_label( + pat_span, + fluent::mir_build_unreachable_making_this_unreachable, + ); + } else { + lint.covered_by_many_n_more_count = remain; + multispan.push_span_label( + pat_span, + fluent::mir_build_unreachable_making_this_unreachable_n_more, + ); + } lint.covered_by_many = Some(multispan); } } diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 6f8d17b772a..53393046610 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -129,7 +129,7 @@ impl<'tcx> ConstToPat<'tcx> { let err = TypeNotPartialEq { span: self.span, non_peq_ty: ty }; let e = self.tcx().dcx().emit_err(err); let kind = PatKind::Error(e); - return Box::new(Pat { span: self.span, ty: ty, kind }); + return Box::new(Pat { span: self.span, ty, kind }); } } diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 615070034b9..d78e1f5da09 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -256,7 +256,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { RangeEnd::Included => { self.tcx.dcx().emit_err(LowerRangeBoundMustBeLessThanOrEqualToUpper { span, - teach: self.tcx.sess.teach(E0030).then_some(()), + teach: self.tcx.sess.teach(E0030), }) } RangeEnd::Excluded => { diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs index 2d4b39e7b08..ce7774f5948 100644 --- a/compiler/rustc_mir_build/src/thir/print.rs +++ b/compiler/rustc_mir_build/src/thir/print.rs @@ -379,8 +379,8 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { self.print_expr(*arg, depth_lvl + 2); print_indented!(self, ")", depth_lvl); } - AddressOf { mutability, arg } => { - print_indented!(self, "AddressOf {", depth_lvl); + RawBorrow { mutability, arg } => { + print_indented!(self, "RawBorrow {", depth_lvl); print_indented!(self, format!("mutability: {:?}", mutability), depth_lvl + 1); print_indented!(self, "arg:", depth_lvl + 1); self.print_expr(*arg, depth_lvl + 2); diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index 2ec3b53bc98..d7e738b8829 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -703,7 +703,7 @@ where statements: vec![ self.assign( ptr, - Rvalue::AddressOf(Mutability::Mut, tcx.mk_place_index(self.place, cur)), + Rvalue::RawPtr(Mutability::Mut, tcx.mk_place_index(self.place, cur)), ), self.assign( cur.into(), diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs index 885fdd0d58b..e8e78fb8a89 100644 --- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs +++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs @@ -94,7 +94,7 @@ where match rvalue { // We ignore fake borrows as these get removed after analysis and shouldn't effect // the layout of generators. - Rvalue::AddressOf(_, borrowed_place) + Rvalue::RawPtr(_, borrowed_place) | Rvalue::Ref(_, BorrowKind::Mut { .. } | BorrowKind::Shared, borrowed_place) => { if !borrowed_place.is_indirect() { self.trans.gen_(borrowed_place.local); diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs index 7822fb17f72..ddfd0739358 100644 --- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs +++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs @@ -351,7 +351,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, '_, 'tcx> { && let Some((_, rvalue)) = statement.kind.as_assign() && let mir::Rvalue::Ref(_, mir::BorrowKind::Mut { .. }, place) // FIXME: Does `&raw const foo` allow mutation? See #90413. - | mir::Rvalue::AddressOf(_, place) = rvalue + | mir::Rvalue::RawPtr(_, place) = rvalue && let LookupResult::Exact(mpi) = self.move_data().rev_lookup.find(place.as_ref()) { on_all_children_bits(self.move_data(), mpi, |child| { diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs index 48bdb131601..24a4b32ceb7 100644 --- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs @@ -189,13 +189,13 @@ impl DefUse { // All other contexts are uses... PlaceContext::MutatingUse( - MutatingUseContext::AddressOf + MutatingUseContext::RawBorrow | MutatingUseContext::Borrow | MutatingUseContext::Drop | MutatingUseContext::Retag, ) | PlaceContext::NonMutatingUse( - NonMutatingUseContext::AddressOf + NonMutatingUseContext::RawBorrow | NonMutatingUseContext::Copy | NonMutatingUseContext::Inspect | NonMutatingUseContext::Move diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index c26a72e4543..14390723ba4 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -158,7 +158,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { | ty::Pat(_, _) | ty::Slice(_) | ty::FnDef(_, _) - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::Dynamic(_, _, _) | ty::Closure(..) | ty::CoroutineClosure(..) @@ -201,7 +201,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { | ty::RawPtr(_, _) | ty::Ref(_, _, _) | ty::FnDef(_, _) - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::Dynamic(_, _, _) | ty::CoroutineWitness(..) | ty::Never @@ -432,7 +432,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { } Rvalue::CopyForDeref(..) => unreachable!(), Rvalue::Ref(..) - | Rvalue::AddressOf(..) + | Rvalue::RawPtr(..) | Rvalue::Discriminant(..) | Rvalue::Len(..) | Rvalue::NullaryOp( diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 139fd592f69..2b20a35b61e 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -177,7 +177,7 @@ pub trait ValueAnalysis<'tcx> { match rvalue { Rvalue::Use(operand) => self.handle_operand(operand, state), Rvalue::CopyForDeref(place) => self.handle_operand(&Operand::Copy(*place), state), - Rvalue::Ref(..) | Rvalue::AddressOf(..) => { + Rvalue::Ref(..) | Rvalue::RawPtr(..) => { // We don't track such places. ValueOrPlace::TOP } diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs index f52a4524d78..edb6bc4fbea 100644 --- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs +++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs @@ -64,7 +64,7 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls { let ty = func.ty(body, tcx); let sig = ty.fn_sig(tcx); let fn_def_id = match ty.kind() { - ty::FnPtr(_) => None, + ty::FnPtr(..) => None, &ty::FnDef(def_id, _) => Some(def_id), _ => span_bug!(span, "invalid callee of type {:?}", ty), }; diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs index 16977a63c59..12a68790374 100644 --- a/compiler/rustc_mir_transform/src/add_retag.rs +++ b/compiler/rustc_mir_transform/src/add_retag.rs @@ -131,9 +131,9 @@ impl<'tcx> MirPass<'tcx> for AddRetag { // Ptr-creating operations already do their own internal retagging, no // need to also add a retag statement. // *Except* if we are deref'ing a Box, because those get desugared to directly working - // with the inner raw pointer! That's relevant for `AddressOf` as Miri otherwise makes it + // with the inner raw pointer! That's relevant for `RawPtr` as Miri otherwise makes it // a NOP when the original pointer is already raw. - Rvalue::AddressOf(_mutbl, place) => { + Rvalue::RawPtr(_mutbl, place) => { // Using `is_box_global` here is a bit sketchy: if this code is // generic over the allocator, we'll not add a retag! This is a hack // to make Stacked Borrows compatible with custom allocator code. diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs index a1dbd7dc50e..5dfdcfc8b94 100644 --- a/compiler/rustc_mir_transform/src/check_alignment.rs +++ b/compiler/rustc_mir_transform/src/check_alignment.rs @@ -71,7 +71,7 @@ struct PointerFinder<'tcx, 'a> { impl<'tcx, 'a> Visitor<'tcx> for PointerFinder<'tcx, 'a> { fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) { // We want to only check reads and writes to Places, so we specifically exclude - // Borrows and AddressOf. + // Borrow and RawBorrow. match context { PlaceContext::MutatingUse( MutatingUseContext::Store diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 82528109be9..d9d2abc554a 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -53,7 +53,7 @@ mod by_move_body; use std::{iter, ops}; -pub use by_move_body::ByMoveBody; +pub use by_move_body::coroutine_by_move_body_def_id; use rustc_data_structures::fx::FxHashSet; use rustc_errors::pluralize; use rustc_hir as hir; @@ -931,7 +931,7 @@ fn compute_storage_conflicts<'mir, 'tcx>( // Compute the storage conflicts for all eligible locals. let mut visitor = StorageConflictVisitor { body, - saved_locals: saved_locals, + saved_locals, local_conflicts: BitMatrix::from_row_n(&ineligible_locals, body.local_decls.len()), eligible_storage_live: BitSet::new_empty(body.local_decls.len()), }; diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs index 69d21a63f55..ebe8d2eff4f 100644 --- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs +++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs @@ -69,140 +69,172 @@ //! in case precise captures (edition 2021 closure capture rules) caused the inner coroutine //! to split one field capture into two. +use rustc_data_structures::steal::Steal; use rustc_data_structures::unord::UnordMap; use rustc_hir as hir; +use rustc_hir::def::DefKind; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::bug; use rustc_middle::hir::place::{Projection, ProjectionKind}; use rustc_middle::mir::visit::MutVisitor; -use rustc_middle::mir::{self, dump_mir, MirPass}; +use rustc_middle::mir::{self, dump_mir}; use rustc_middle::ty::{self, InstanceKind, Ty, TyCtxt, TypeVisitableExt}; +use rustc_span::symbol::kw; use rustc_target::abi::{FieldIdx, VariantIdx}; -pub struct ByMoveBody; +pub fn coroutine_by_move_body_def_id<'tcx>( + tcx: TyCtxt<'tcx>, + coroutine_def_id: LocalDefId, +) -> DefId { + let body = tcx.mir_built(coroutine_def_id).borrow(); -impl<'tcx> MirPass<'tcx> for ByMoveBody { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut mir::Body<'tcx>) { - // We only need to generate by-move coroutine bodies for coroutines that come - // from coroutine-closures. - let Some(coroutine_def_id) = body.source.def_id().as_local() else { - return; - }; - let Some(hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure)) = - tcx.coroutine_kind(coroutine_def_id) - else { - return; - }; + let Some(hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure)) = + tcx.coroutine_kind(coroutine_def_id) + else { + bug!("should only be invoked on coroutine-closures"); + }; - // Also, let's skip processing any bodies with errors, since there's no guarantee - // the MIR body will be constructed well. - let coroutine_ty = body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty; - if coroutine_ty.references_error() { - return; - } + // Also, let's skip processing any bodies with errors, since there's no guarantee + // the MIR body will be constructed well. + let coroutine_ty = body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty; - // We don't need to generate a by-move coroutine if the coroutine body was - // produced by the `CoroutineKindShim`, since it's already by-move. - if matches!(body.source.instance, ty::InstanceKind::CoroutineKindShim { .. }) { - return; - } + let ty::Coroutine(_, args) = *coroutine_ty.kind() else { bug!("{body:#?}") }; + let args = args.as_coroutine(); - let ty::Coroutine(_, args) = *coroutine_ty.kind() else { bug!("{body:#?}") }; - let args = args.as_coroutine(); + let coroutine_kind = args.kind_ty().to_opt_closure_kind().unwrap(); - let coroutine_kind = args.kind_ty().to_opt_closure_kind().unwrap(); - - let parent_def_id = tcx.local_parent(coroutine_def_id); - let ty::CoroutineClosure(_, parent_args) = - *tcx.type_of(parent_def_id).instantiate_identity().kind() - else { - bug!(); - }; - let parent_closure_args = parent_args.as_coroutine_closure(); - let num_args = parent_closure_args - .coroutine_closure_sig() - .skip_binder() - .tupled_inputs_ty - .tuple_fields() - .len(); - - let field_remapping: UnordMap<_, _> = ty::analyze_coroutine_closure_captures( - tcx.closure_captures(parent_def_id).iter().copied(), - tcx.closure_captures(coroutine_def_id).iter().skip(num_args).copied(), - |(parent_field_idx, parent_capture), (child_field_idx, child_capture)| { - // Store this set of additional projections (fields and derefs). - // We need to re-apply them later. - let child_precise_captures = - &child_capture.place.projections[parent_capture.place.projections.len()..]; - - // If the parent captures by-move, and the child captures by-ref, then we - // need to peel an additional `deref` off of the body of the child. - let needs_deref = child_capture.is_by_ref() && !parent_capture.is_by_ref(); - if needs_deref { - assert_ne!( - coroutine_kind, - ty::ClosureKind::FnOnce, - "`FnOnce` coroutine-closures return coroutines that capture from \ - their body; it will always result in a borrowck error!" - ); - } - - // Finally, store the type of the parent's captured place. We need - // this when building the field projection in the MIR body later on. - let mut parent_capture_ty = parent_capture.place.ty(); - parent_capture_ty = match parent_capture.info.capture_kind { - ty::UpvarCapture::ByValue => parent_capture_ty, - ty::UpvarCapture::ByRef(kind) => Ty::new_ref( - tcx, - tcx.lifetimes.re_erased, - parent_capture_ty, - kind.to_mutbl_lossy(), - ), - }; - - ( - FieldIdx::from_usize(child_field_idx + num_args), - ( - FieldIdx::from_usize(parent_field_idx + num_args), - parent_capture_ty, - needs_deref, - child_precise_captures, - ), - ) - }, - ) - .collect(); - - if coroutine_kind == ty::ClosureKind::FnOnce { - assert_eq!(field_remapping.len(), tcx.closure_captures(parent_def_id).len()); - return; - } - - let by_move_coroutine_ty = tcx - .instantiate_bound_regions_with_erased(parent_closure_args.coroutine_closure_sig()) - .to_coroutine_given_kind_and_upvars( - tcx, - parent_closure_args.parent_args(), - coroutine_def_id.to_def_id(), - ty::ClosureKind::FnOnce, - tcx.lifetimes.re_erased, - parent_closure_args.tupled_upvars_ty(), - parent_closure_args.coroutine_captures_by_ref_ty(), - ); - - let mut by_move_body = body.clone(); - MakeByMoveBody { tcx, field_remapping, by_move_coroutine_ty }.visit_body(&mut by_move_body); - dump_mir(tcx, false, "coroutine_by_move", &0, &by_move_body, |_, _| Ok(())); - // FIXME: use query feeding to generate the body right here and then only store the `DefId` of the new body. - by_move_body.source = mir::MirSource::from_instance(InstanceKind::CoroutineKindShim { - coroutine_def_id: coroutine_def_id.to_def_id(), - }); - body.coroutine.as_mut().unwrap().by_move_body = Some(by_move_body); + let parent_def_id = tcx.local_parent(coroutine_def_id); + let ty::CoroutineClosure(_, parent_args) = + *tcx.type_of(parent_def_id).instantiate_identity().kind() + else { + bug!(); + }; + if parent_args.references_error() { + return coroutine_def_id.to_def_id(); } + + let parent_closure_args = parent_args.as_coroutine_closure(); + let num_args = parent_closure_args + .coroutine_closure_sig() + .skip_binder() + .tupled_inputs_ty + .tuple_fields() + .len(); + + let field_remapping: UnordMap<_, _> = ty::analyze_coroutine_closure_captures( + tcx.closure_captures(parent_def_id).iter().copied(), + tcx.closure_captures(coroutine_def_id).iter().skip(num_args).copied(), + |(parent_field_idx, parent_capture), (child_field_idx, child_capture)| { + // Store this set of additional projections (fields and derefs). + // We need to re-apply them later. + let mut child_precise_captures = + child_capture.place.projections[parent_capture.place.projections.len()..].to_vec(); + + // If the parent capture is by-ref, then we need to apply an additional + // deref before applying any further projections to this place. + if parent_capture.is_by_ref() { + child_precise_captures.insert( + 0, + Projection { ty: parent_capture.place.ty(), kind: ProjectionKind::Deref }, + ); + } + // If the child capture is by-ref, then we need to apply a "ref" + // projection (i.e. `&`) at the end. But wait! We don't have that + // as a projection kind. So instead, we can apply its dual and + // *peel* a deref off of the place when it shows up in the MIR body. + // Luckily, by construction this is always possible. + let peel_deref = if child_capture.is_by_ref() { + assert!( + parent_capture.is_by_ref() || coroutine_kind != ty::ClosureKind::FnOnce, + "`FnOnce` coroutine-closures return coroutines that capture from \ + their body; it will always result in a borrowck error!" + ); + true + } else { + false + }; + + // Regarding the behavior above, you may think that it's redundant to both + // insert a deref and then peel a deref if the parent and child are both + // captured by-ref. This would be correct, except for the case where we have + // precise capturing projections, since the inserted deref is to the *beginning* + // and the peeled deref is at the *end*. I cannot seem to actually find a + // case where this happens, though, but let's keep this code flexible. + + // Finally, store the type of the parent's captured place. We need + // this when building the field projection in the MIR body later on. + let mut parent_capture_ty = parent_capture.place.ty(); + parent_capture_ty = match parent_capture.info.capture_kind { + ty::UpvarCapture::ByValue => parent_capture_ty, + ty::UpvarCapture::ByRef(kind) => Ty::new_ref( + tcx, + tcx.lifetimes.re_erased, + parent_capture_ty, + kind.to_mutbl_lossy(), + ), + }; + + ( + FieldIdx::from_usize(child_field_idx + num_args), + ( + FieldIdx::from_usize(parent_field_idx + num_args), + parent_capture_ty, + peel_deref, + child_precise_captures, + ), + ) + }, + ) + .collect(); + + if coroutine_kind == ty::ClosureKind::FnOnce { + assert_eq!(field_remapping.len(), tcx.closure_captures(parent_def_id).len()); + // The by-move body is just the body :) + return coroutine_def_id.to_def_id(); + } + + let by_move_coroutine_ty = tcx + .instantiate_bound_regions_with_erased(parent_closure_args.coroutine_closure_sig()) + .to_coroutine_given_kind_and_upvars( + tcx, + parent_closure_args.parent_args(), + coroutine_def_id.to_def_id(), + ty::ClosureKind::FnOnce, + tcx.lifetimes.re_erased, + parent_closure_args.tupled_upvars_ty(), + parent_closure_args.coroutine_captures_by_ref_ty(), + ); + + let mut by_move_body = body.clone(); + MakeByMoveBody { tcx, field_remapping, by_move_coroutine_ty }.visit_body(&mut by_move_body); + dump_mir(tcx, false, "coroutine_by_move", &0, &by_move_body, |_, _| Ok(())); + + let body_def = tcx.create_def(coroutine_def_id, kw::Empty, DefKind::SyntheticCoroutineBody); + by_move_body.source = + mir::MirSource::from_instance(InstanceKind::Item(body_def.def_id().to_def_id())); + + // Inherited from the by-ref coroutine. + body_def.codegen_fn_attrs(tcx.codegen_fn_attrs(coroutine_def_id).clone()); + body_def.constness(tcx.constness(coroutine_def_id).clone()); + body_def.coroutine_kind(tcx.coroutine_kind(coroutine_def_id).clone()); + body_def.def_ident_span(tcx.def_ident_span(coroutine_def_id)); + body_def.def_span(tcx.def_span(coroutine_def_id)); + body_def.explicit_predicates_of(tcx.explicit_predicates_of(coroutine_def_id).clone()); + body_def.generics_of(tcx.generics_of(coroutine_def_id).clone()); + body_def.param_env(tcx.param_env(coroutine_def_id).clone()); + body_def.predicates_of(tcx.predicates_of(coroutine_def_id).clone()); + + // The type of the coroutine is the `by_move_coroutine_ty`. + body_def.type_of(ty::EarlyBinder::bind(by_move_coroutine_ty)); + + body_def.mir_built(tcx.arena.alloc(Steal::new(by_move_body))); + + body_def.def_id().to_def_id() } struct MakeByMoveBody<'tcx> { tcx: TyCtxt<'tcx>, - field_remapping: UnordMap, bool, &'tcx [Projection<'tcx>])>, + field_remapping: UnordMap, bool, Vec>)>, by_move_coroutine_ty: Ty<'tcx>, } @@ -223,14 +255,14 @@ impl<'tcx> MutVisitor<'tcx> for MakeByMoveBody<'tcx> { if place.local == ty::CAPTURE_STRUCT_LOCAL && let Some((&mir::ProjectionElem::Field(idx, _), projection)) = place.projection.split_first() - && let Some(&(remapped_idx, remapped_ty, needs_deref, bridging_projections)) = + && let Some(&(remapped_idx, remapped_ty, peel_deref, ref bridging_projections)) = self.field_remapping.get(&idx) { // As noted before, if the parent closure captures a field by value, and // the child captures a field by ref, then for the by-move body we're // generating, we also are taking that field by value. Peel off a deref, // since a layer of ref'ing has now become redundant. - let final_projections = if needs_deref { + let final_projections = if peel_deref { let Some((mir::ProjectionElem::Deref, projection)) = projection.split_first() else { bug!( diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 96ca3b43d5c..af0f1e38a75 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -13,7 +13,7 @@ use rustc_hir::intravisit::{walk_expr, Visitor}; use rustc_middle::hir::map::Map; use rustc_middle::hir::nested_filter; use rustc_middle::mir::coverage::{ - CodeRegion, CoverageKind, DecisionInfo, FunctionCoverageInfo, Mapping, MappingKind, + CoverageKind, DecisionInfo, FunctionCoverageInfo, Mapping, MappingKind, SourceRegion, }; use rustc_middle::mir::{ self, BasicBlock, BasicBlockData, SourceInfo, Statement, StatementKind, Terminator, @@ -159,7 +159,7 @@ fn create_mappings<'tcx>( .expect("all BCBs with spans were given counters") .as_term() }; - let region_for_span = |span: Span| make_code_region(source_map, file_name, span, body_span); + let region_for_span = |span: Span| make_source_region(source_map, file_name, span, body_span); // Fully destructure the mappings struct to make sure we don't miss any kinds. let ExtractedMappings { @@ -175,9 +175,9 @@ fn create_mappings<'tcx>( mappings.extend(code_mappings.iter().filter_map( // Ordinary code mappings are the simplest kind. |&mappings::CodeMapping { span, bcb }| { - let code_region = region_for_span(span)?; + let source_region = region_for_span(span)?; let kind = MappingKind::Code(term_for_bcb(bcb)); - Some(Mapping { kind, code_region }) + Some(Mapping { kind, source_region }) }, )); @@ -186,29 +186,29 @@ fn create_mappings<'tcx>( let true_term = term_for_bcb(true_bcb); let false_term = term_for_bcb(false_bcb); let kind = MappingKind::Branch { true_term, false_term }; - let code_region = region_for_span(span)?; - Some(Mapping { kind, code_region }) + let source_region = region_for_span(span)?; + Some(Mapping { kind, source_region }) }, )); mappings.extend(mcdc_branches.iter().filter_map( |&mappings::MCDCBranch { span, true_bcb, false_bcb, condition_info, decision_depth: _ }| { - let code_region = region_for_span(span)?; + let source_region = region_for_span(span)?; let true_term = term_for_bcb(true_bcb); let false_term = term_for_bcb(false_bcb); let kind = match condition_info { Some(mcdc_params) => MappingKind::MCDCBranch { true_term, false_term, mcdc_params }, None => MappingKind::Branch { true_term, false_term }, }; - Some(Mapping { kind, code_region }) + Some(Mapping { kind, source_region }) }, )); mappings.extend(mcdc_decisions.iter().filter_map( |&mappings::MCDCDecision { span, bitmap_idx, num_conditions, .. }| { - let code_region = region_for_span(span)?; + let source_region = region_for_span(span)?; let kind = MappingKind::MCDCDecision(DecisionInfo { bitmap_idx, num_conditions }); - Some(Mapping { kind, code_region }) + Some(Mapping { kind, source_region }) }, )); @@ -362,19 +362,13 @@ fn inject_statement(mir_body: &mut mir::Body<'_>, counter_kind: CoverageKind, bb /// but it's hard to rule out entirely (especially in the presence of complex macros /// or other expansions), and if it does happen then skipping a span or function is /// better than an ICE or `llvm-cov` failure that the user might have no way to avoid. -fn make_code_region( +#[instrument(level = "debug", skip(source_map))] +fn make_source_region( source_map: &SourceMap, file_name: Symbol, span: Span, body_span: Span, -) -> Option { - debug!( - "Called make_code_region(file_name={}, span={}, body_span={})", - file_name, - source_map.span_to_diagnostic_string(span), - source_map.span_to_diagnostic_string(body_span) - ); - +) -> Option { let lo = span.lo(); let hi = span.hi(); @@ -424,7 +418,7 @@ fn make_code_region( start_line = source_map.doctest_offset_line(&file.name, start_line); end_line = source_map.doctest_offset_line(&file.name, end_line); - check_code_region(CodeRegion { + check_source_region(SourceRegion { file_name, start_line: start_line as u32, start_col: start_col as u32, @@ -433,12 +427,12 @@ fn make_code_region( }) } -/// If `llvm-cov` sees a code region that is improperly ordered (end < start), +/// If `llvm-cov` sees a source region that is improperly ordered (end < start), /// it will immediately exit with a fatal error. To prevent that from happening, /// discard regions that are improperly ordered, or might be interpreted in a /// way that makes them improperly ordered. -fn check_code_region(code_region: CodeRegion) -> Option { - let CodeRegion { file_name: _, start_line, start_col, end_line, end_col } = code_region; +fn check_source_region(source_region: SourceRegion) -> Option { + let SourceRegion { file_name: _, start_line, start_col, end_line, end_col } = source_region; // Line/column coordinates are supposed to be 1-based. If we ever emit // coordinates of 0, `llvm-cov` might misinterpret them. @@ -451,17 +445,17 @@ fn check_code_region(code_region: CodeRegion) -> Option { let is_ordered = (start_line, start_col) <= (end_line, end_col); if all_nonzero && end_col_has_high_bit_unset && is_ordered { - Some(code_region) + Some(source_region) } else { debug!( - ?code_region, + ?source_region, ?all_nonzero, ?end_col_has_high_bit_unset, ?is_ordered, - "Skipping code region that would be misinterpreted or rejected by LLVM" + "Skipping source region that would be misinterpreted or rejected by LLVM" ); // If this happens in a debug build, ICE to make it easier to notice. - debug_assert!(false, "Improper code region: {code_region:?}"); + debug_assert!(false, "Improper source region: {source_region:?}"); None } } diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 0fc4d6b9f4e..f207216d6f4 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -338,7 +338,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { tcx, local_decls: &body.local_decls, ecx: InterpCx::new(tcx, DUMMY_SP, param_env, DummyMachine), - param_env: param_env, + param_env, } } diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs index 370e930b740..71af099199e 100644 --- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs +++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs @@ -40,7 +40,7 @@ impl<'tcx> Visitor<'tcx> for DeduceReadOnly { // This is a mutation, so mark it as such. true } - PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf) => { + PlaceContext::NonMutatingUse(NonMutatingUseContext::RawBorrow) => { // Whether mutating though a `&raw const` is allowed is still undecided, so we // disable any sketchy `readonly` optimizations for now. // But we only need to do this if the pointer would point into the argument. diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index 054cdbc6bad..ed924761892 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -576,7 +576,7 @@ impl WriteInfo { Rvalue::ThreadLocalRef(_) | Rvalue::NullaryOp(_, _) | Rvalue::Ref(_, _, _) - | Rvalue::AddressOf(_, _) + | Rvalue::RawPtr(_, _) | Rvalue::Len(_) | Rvalue::Discriminant(_) | Rvalue::CopyForDeref(_) => (), diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs index 4132e604f20..9a2cc057232 100644 --- a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs +++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs @@ -57,7 +57,7 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool { }; let fn_def_id = match ty.kind() { - ty::FnPtr(_) => None, + ty::FnPtr(..) => None, &ty::FnDef(def_id, _) => { // Rust calls cannot themselves create foreign unwinds (even if they use a non-Rust ABI). // So the leak of the foreign unwind into Rust can only be elsewhere, not here. diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index e16911d79c3..90e3ba26a43 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -45,7 +45,7 @@ //! //! # Handling of references //! -//! We handle references by assigning a different "provenance" index to each Ref/AddressOf rvalue. +//! We handle references by assigning a different "provenance" index to each Ref/RawPtr rvalue. //! This ensure that we do not spuriously merge borrows that should not be merged. Meanwhile, we //! consider all the derefs of an immutable reference to a freeze type to give the same value: //! ```ignore (MIR) @@ -832,7 +832,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { self.simplify_place_projection(place, location); return self.new_pointer(*place, AddressKind::Ref(borrow_kind)); } - Rvalue::AddressOf(mutbl, ref mut place) => { + Rvalue::RawPtr(mutbl, ref mut place) => { self.simplify_place_projection(place, location); return self.new_pointer(*place, AddressKind::Address(mutbl)); } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 324ddc5e799..2d6950be55d 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -341,7 +341,6 @@ impl<'tcx> Inliner<'tcx> { | InstanceKind::FnPtrShim(..) | InstanceKind::ClosureOnceShim { .. } | InstanceKind::ConstructCoroutineInClosureShim { .. } - | InstanceKind::CoroutineKindShim { .. } | InstanceKind::DropGlue(..) | InstanceKind::CloneShim(..) | InstanceKind::ThreadLocalShim(..) @@ -726,7 +725,7 @@ impl<'tcx> Inliner<'tcx> { // Insert all of the (mapped) parts of the callee body into the caller. caller_body.local_decls.extend(callee_body.drain_vars_and_temps()); - caller_body.source_scopes.extend(&mut callee_body.source_scopes.drain(..)); + caller_body.source_scopes.append(&mut callee_body.source_scopes); if self .tcx .sess @@ -740,7 +739,7 @@ impl<'tcx> Inliner<'tcx> { // still getting consistent results from the mir-opt tests. caller_body.var_debug_info.append(&mut callee_body.var_debug_info); } - caller_body.basic_blocks_mut().extend(callee_body.basic_blocks_mut().drain(..)); + caller_body.basic_blocks_mut().append(callee_body.basic_blocks_mut()); caller_body[callsite.block].terminator = Some(Terminator { source_info: callsite.source_info, diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs index f5274c664cf..56e8905bead 100644 --- a/compiler/rustc_mir_transform/src/inline/cycle.rs +++ b/compiler/rustc_mir_transform/src/inline/cycle.rs @@ -88,7 +88,6 @@ pub(crate) fn mir_callgraph_reachable<'tcx>( | InstanceKind::FnPtrShim(..) | InstanceKind::ClosureOnceShim { .. } | InstanceKind::ConstructCoroutineInClosureShim { .. } - | InstanceKind::CoroutineKindShim { .. } | InstanceKind::ThreadLocalShim { .. } | InstanceKind::CloneShim(..) => {} diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index 1589653968c..3ec553d0ba0 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -141,7 +141,7 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> { /// Transform `&(*a)` ==> `a`. fn simplify_ref_deref(&self, source_info: &SourceInfo, rvalue: &mut Rvalue<'tcx>) { - if let Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) = rvalue { + if let Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) = rvalue { if let Some((base, ProjectionElem::Deref)) = place.as_ref().last_projection() { if rvalue.ty(self.local_decls, self.tcx) != base.ty(self.local_decls, self.tcx).ty { return; diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index 7202cc2d042..7eed47cf239 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -419,8 +419,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } // Do not try creating references (#67862) - Rvalue::AddressOf(_, place) | Rvalue::Ref(_, _, place) => { - trace!("skipping AddressOf | Ref for {:?}", place); + Rvalue::RawPtr(_, place) | Rvalue::Ref(_, _, place) => { + trace!("skipping RawPtr | Ref for {:?}", place); // This may be creating mutable references or immutable references to cells. // If that happens, the pointed to value could be mutated via that reference. @@ -616,7 +616,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { ImmTy::from_scalar(Scalar::from_target_usize(len, self), layout).into() } - Ref(..) | AddressOf(..) => return None, + Ref(..) | RawPtr(..) => return None, NullaryOp(ref null_op, ty) => { let op_layout = self.use_ecx(|this| this.ecx.layout_of(ty))?; @@ -969,9 +969,9 @@ impl<'tcx> Visitor<'tcx> for CanConstProp { // mutation. | NonMutatingUse(NonMutatingUseContext::SharedBorrow) | NonMutatingUse(NonMutatingUseContext::FakeBorrow) - | NonMutatingUse(NonMutatingUseContext::AddressOf) + | NonMutatingUse(NonMutatingUseContext::RawBorrow) | MutatingUse(MutatingUseContext::Borrow) - | MutatingUse(MutatingUseContext::AddressOf) => { + | MutatingUse(MutatingUseContext::RawBorrow) => { trace!("local {:?} can't be propagated because it's used: {:?}", local, context); self.can_const_prop[local] = ConstPropMode::NoPropagation; } diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs index e407929c9a7..cbc3169f2f1 100644 --- a/compiler/rustc_mir_transform/src/large_enums.rs +++ b/compiler/rustc_mir_transform/src/large_enums.rs @@ -214,7 +214,7 @@ impl EnumSizeOpt { source_info, kind: StatementKind::Assign(Box::new(( dst, - Rvalue::AddressOf(Mutability::Mut, *lhs), + Rvalue::RawPtr(Mutability::Mut, *lhs), ))), }; @@ -238,7 +238,7 @@ impl EnumSizeOpt { source_info, kind: StatementKind::Assign(Box::new(( src, - Rvalue::AddressOf(Mutability::Not, *rhs), + Rvalue::RawPtr(Mutability::Not, *rhs), ))), }; diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 1f214bc42cb..88094b44edf 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -135,6 +135,7 @@ pub fn provide(providers: &mut Providers) { mir_inliner_callees: inline::cycle::mir_inliner_callees, promoted_mir, deduced_param_attrs: deduce_param_attrs::deduced_param_attrs, + coroutine_by_move_body_def_id: coroutine::coroutine_by_move_body_def_id, ..providers.queries }; } @@ -293,10 +294,6 @@ fn mir_built(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal> { &Lint(check_packed_ref::CheckPackedRef), &Lint(check_const_item_mutation::CheckConstItemMutation), &Lint(function_item_references::FunctionItemReferences), - // If this is an async closure's output coroutine, generate - // by-move and by-mut bodies if needed. We do this first so - // they can be optimized in lockstep with their parent bodies. - &coroutine::ByMoveBody, // What we need to do constant evaluation. &simplify::SimplifyCfg::Initial, &rustc_peek::SanityCheck, // Just a lint @@ -329,8 +326,15 @@ fn mir_promoted( | DefKind::AnonConst => tcx.mir_const_qualif(def), _ => ConstQualifs::default(), }; - // has_ffi_unwind_calls query uses the raw mir, so make sure it is run. + + // the `has_ffi_unwind_calls` query uses the raw mir, so make sure it is run. tcx.ensure_with_value().has_ffi_unwind_calls(def); + + // the `by_move_body` query uses the raw mir, so make sure it is run. + if tcx.needs_coroutine_by_move_body_def_id(def) { + tcx.ensure_with_value().coroutine_by_move_body_def_id(def); + } + let mut body = tcx.mir_built(def).steal(); if let Some(error_reported) = const_qualifs.tainted_by_errors { body.tainted_by_errors = Some(error_reported); @@ -339,14 +343,6 @@ fn mir_promoted( // Collect `required_consts` *before* promotion, so if there are any consts being promoted // we still add them to the list in the outer MIR body. RequiredConstsVisitor::compute_required_consts(&mut body); - // If this has an associated by-move async closure body, that doesn't get run through these - // passes itself, it gets "tagged along" by the pass manager. `RequiredConstsVisitor` is not - // a regular pass so we have to also apply it manually to the other body. - if let Some(coroutine) = body.coroutine.as_mut() { - if let Some(by_move_body) = coroutine.by_move_body.as_mut() { - RequiredConstsVisitor::compute_required_consts(by_move_body); - } - } // What we need to run borrowck etc. let promote_pass = promote_consts::PromoteTemps::default(); @@ -398,7 +394,10 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> & if tcx.is_coroutine(def.to_def_id()) { tcx.ensure_with_value().mir_coroutine_witnesses(def); } - let mir_borrowck = tcx.mir_borrowck(def); + + // We only need to borrowck non-synthetic MIR. + let tainted_by_errors = + if !tcx.is_synthetic_mir(def) { tcx.mir_borrowck(def).tainted_by_errors } else { None }; let is_fn_like = tcx.def_kind(def).is_fn_like(); if is_fn_like { @@ -410,7 +409,8 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> & let (body, _) = tcx.mir_promoted(def); let mut body = body.steal(); - if let Some(error_reported) = mir_borrowck.tainted_by_errors { + + if let Some(error_reported) = tainted_by_errors { body.tainted_by_errors = Some(error_reported); } @@ -660,14 +660,6 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> { // visited does not depend on the optimization level. // We do not use `run_passes` for this as that might skip the pass if `injection_phase` is set. mentioned_items::MentionedItems.run_pass(tcx, &mut body); - // If this has an associated by-move async closure body, that doesn't get run through these - // passes itself, it gets "tagged along" by the pass manager. Since we're not using the pass - // manager we have to do this by hand. - if let Some(coroutine) = body.coroutine.as_mut() { - if let Some(by_move_body) = coroutine.by_move_body.as_mut() { - mentioned_items::MentionedItems.run_pass(tcx, by_move_body); - } - } // If `mir_drops_elaborated_and_const_checked` found that the current body has unsatisfiable // predicates, it will shrink the MIR to a single `unreachable` terminator. @@ -690,7 +682,9 @@ fn promoted_mir(tcx: TyCtxt<'_>, def: LocalDefId) -> &IndexVec( body.pass_count = 1; } - - if let Some(coroutine) = body.coroutine.as_mut() { - if let Some(by_move_body) = coroutine.by_move_body.as_mut() { - run_passes_inner(tcx, by_move_body, passes, phase_change, validate_each); - } - } } pub fn validate_body<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, when: String) { diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index 48a3266ae6f..6e84914ef97 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -551,7 +551,7 @@ impl<'tcx> Validator<'_, 'tcx> { self.validate_operand(rhs)?; } - Rvalue::AddressOf(_, place) => { + Rvalue::RawPtr(_, place) => { // We accept `&raw *`, i.e., raw reborrows -- creating a raw pointer is // no problem, only using it is. if let Some((place_base, ProjectionElem::Deref)) = place.as_ref().last_projection() diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs index 76e65099e90..973a191d786 100644 --- a/compiler/rustc_mir_transform/src/ref_prop.rs +++ b/compiler/rustc_mir_transform/src/ref_prop.rs @@ -227,7 +227,7 @@ fn compute_replacement<'tcx>( } } } - Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => { + Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) => { let mut place = *place; // Try to see through `place` in order to collapse reborrow chains. if place.projection.first() == Some(&PlaceElem::Deref) diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 29185e79bce..86eada0183f 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -78,15 +78,11 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body< receiver_by_ref, } => build_construct_coroutine_by_move_shim(tcx, coroutine_closure_def_id, receiver_by_ref), - ty::InstanceKind::CoroutineKindShim { coroutine_def_id } => { - return tcx.optimized_mir(coroutine_def_id).coroutine_by_move_body().unwrap().clone(); - } - ty::InstanceKind::DropGlue(def_id, ty) => { // FIXME(#91576): Drop shims for coroutines aren't subject to the MIR passes at the end // of this function. Is this intentional? - if let Some(ty::Coroutine(coroutine_def_id, args)) = ty.map(Ty::kind) { - let coroutine_body = tcx.optimized_mir(*coroutine_def_id); + if let Some(&ty::Coroutine(coroutine_def_id, args)) = ty.map(Ty::kind) { + let coroutine_body = tcx.optimized_mir(coroutine_def_id); let ty::Coroutine(_, id_args) = *tcx.type_of(coroutine_def_id).skip_binder().kind() else { @@ -105,7 +101,9 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body< args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap(), ty::ClosureKind::FnOnce ); - coroutine_body.coroutine_by_move_body().unwrap().coroutine_drop().unwrap() + tcx.optimized_mir(tcx.coroutine_by_move_body_def_id(coroutine_def_id)) + .coroutine_drop() + .unwrap() }; let mut body = EarlyBinder::bind(body.clone()).instantiate(tcx, args); @@ -437,7 +435,7 @@ fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) - let src = tcx.mk_place_deref(Place::from(Local::new(1 + 0))); match self_ty.kind() { - ty::FnDef(..) | ty::FnPtr(_) => builder.copy_shim(), + ty::FnDef(..) | ty::FnPtr(..) => builder.copy_shim(), ty::Closure(_, args) => builder.tuple_like_shim(dest, src, args.as_closure().upvar_tys()), ty::CoroutineClosure(_, args) => { builder.tuple_like_shim(dest, src, args.as_coroutine_closure().upvar_tys()) diff --git a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs index ea4f5fca59e..9c3f903e0ea 100644 --- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs +++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs @@ -343,7 +343,7 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> { .tcx .mk_place_elems(&[PlaceElem::Deref, PlaceElem::Field(field, field_ty)]), }; - self.put_temp_rvalue(Rvalue::AddressOf(Mutability::Mut, place)) + self.put_temp_rvalue(Rvalue::RawPtr(Mutability::Mut, place)) } /// If given Self is an enum puts `to_drop: *mut FieldTy` on top of @@ -363,7 +363,7 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> { PlaceElem::Field(field, field_ty), ]), }; - self.put_temp_rvalue(Rvalue::AddressOf(Mutability::Mut, place)) + self.put_temp_rvalue(Rvalue::RawPtr(Mutability::Mut, place)) } /// If given Self is an enum puts `to_drop: *mut FieldTy` on top of diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index 5bbe3bb747f..4fe8cf6213f 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -31,6 +31,7 @@ use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; +use rustc_span::DUMMY_SP; use smallvec::SmallVec; pub enum SimplifyCfg { @@ -318,6 +319,7 @@ pub(crate) fn remove_dead_blocks(body: &mut Body<'_>) { let mut orig_index = 0; let mut used_index = 0; let mut kept_unreachable = None; + let mut deduplicated_unreachable = false; basic_blocks.raw.retain(|bbdata| { let orig_bb = BasicBlock::new(orig_index); if !reachable.contains(orig_bb) { @@ -330,6 +332,7 @@ pub(crate) fn remove_dead_blocks(body: &mut Body<'_>) { let kept_unreachable = *kept_unreachable.get_or_insert(used_bb); if kept_unreachable != used_bb { replacements[orig_index] = kept_unreachable; + deduplicated_unreachable = true; orig_index += 1; return false; } @@ -341,6 +344,14 @@ pub(crate) fn remove_dead_blocks(body: &mut Body<'_>) { true }); + // If we deduplicated unreachable blocks we erase their source_info as we + // can no longer attribute their code to a particular location in the + // source. + if deduplicated_unreachable { + basic_blocks[kept_unreachable.unwrap()].terminator_mut().source_info = + SourceInfo { span: DUMMY_SP, scope: OUTERMOST_SOURCE_SCOPE }; + } + for block in basic_blocks { for target in block.terminator_mut().successors_mut() { *target = replacements[target.index()]; diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs index fb870425f6e..76591f52625 100644 --- a/compiler/rustc_mir_transform/src/ssa.rs +++ b/compiler/rustc_mir_transform/src/ssa.rs @@ -2,9 +2,9 @@ //! 1/ They are only assigned-to once, either as a function parameter, or in an assign statement; //! 2/ This single assignment dominates all uses; //! -//! As we do not track indirect assignments, a local that has its address taken (either by -//! AddressOf or by borrowing) is considered non-SSA. However, it is UB to modify through an -//! immutable borrow of a `Freeze` local. Those can still be considered to be SSA. +//! As we do not track indirect assignments, a local that has its address taken (via a borrow or raw +//! borrow operator) is considered non-SSA. However, it is UB to modify through an immutable borrow +//! of a `Freeze` local. Those can still be considered to be SSA. use rustc_data_structures::graph::dominators::Dominators; use rustc_index::bit_set::BitSet; @@ -262,7 +262,7 @@ impl<'tcx> Visitor<'tcx> for SsaVisitor<'tcx, '_> { PlaceContext::MutatingUse(MutatingUseContext::Projection) | PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) => bug!(), // Anything can happen with raw pointers, so remove them. - PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf) + PlaceContext::NonMutatingUse(NonMutatingUseContext::RawBorrow) | PlaceContext::MutatingUse(_) => { self.assignments[local] = Set1::Many; } diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 491ae1c0d08..99e06f59dd0 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -102,25 +102,6 @@ impl<'tcx> MirPass<'tcx> for Validator { } } } - - // Enforce that coroutine-closure layouts are identical. - if let Some(layout) = body.coroutine_layout_raw() - && let Some(by_move_body) = body.coroutine_by_move_body() - && let Some(by_move_layout) = by_move_body.coroutine_layout_raw() - { - // FIXME(async_closures): We could do other validation here? - if layout.variant_fields.len() != by_move_layout.variant_fields.len() { - cfg_checker.fail( - Location::START, - format!( - "Coroutine layout has different number of variant fields from \ - by-move coroutine layout:\n\ - layout: {layout:#?}\n\ - by_move_layout: {by_move_layout:#?}", - ), - ); - } - } } } @@ -1345,7 +1326,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } Rvalue::Repeat(_, _) | Rvalue::ThreadLocalRef(_) - | Rvalue::AddressOf(_, _) + | Rvalue::RawPtr(_, _) | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::UbChecks, _) | Rvalue::Discriminant(_) => {} } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 0ae635f9b73..36fb2e89af1 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -580,9 +580,9 @@ fn check_recursion_limit<'tcx>( let mut path = PathBuf::new(); let was_written = if let Some(written_to_path) = written_to_path { path = written_to_path; - Some(()) + true } else { - None + false }; tcx.dcx().emit_fatal(RecursionLimit { span, @@ -888,7 +888,9 @@ fn visit_instance_use<'tcx>( if tcx.should_codegen_locally(panic_instance) { output.push(create_fn_mono_item(tcx, panic_instance, source)); } - } else if tcx.has_attr(def_id, sym::rustc_intrinsic) { + } else if tcx.has_attr(def_id, sym::rustc_intrinsic) + && !tcx.has_attr(def_id, sym::rustc_intrinsic_must_be_overridden) + { // Codegen the fallback body of intrinsics with fallback bodies let instance = ty::Instance::new(def_id, instance.args); if tcx.should_codegen_locally(instance) { @@ -918,7 +920,6 @@ fn visit_instance_use<'tcx>( | ty::InstanceKind::ReifyShim(..) | ty::InstanceKind::ClosureOnceShim { .. } | ty::InstanceKind::ConstructCoroutineInClosureShim { .. } - | ty::InstanceKind::CoroutineKindShim { .. } | ty::InstanceKind::Item(..) | ty::InstanceKind::FnPtrShim(..) | ty::InstanceKind::CloneShim(..) @@ -1033,9 +1034,9 @@ fn find_vtable_types_for_unsizing<'tcx>( } }; - match (&source_ty.kind(), &target_ty.kind()) { + match (source_ty.kind(), target_ty.kind()) { (&ty::Ref(_, a, _), &ty::Ref(_, b, _) | &ty::RawPtr(b, _)) - | (&ty::RawPtr(a, _), &ty::RawPtr(b, _)) => ptr_vtable(*a, *b), + | (&ty::RawPtr(a, _), &ty::RawPtr(b, _)) => ptr_vtable(a, b), (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => { ptr_vtable(source_ty.boxed_ty(), target_ty.boxed_ty()) } diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index 88286cb73a6..c97e07ee3ba 100644 --- a/compiler/rustc_monomorphize/src/errors.rs +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -16,7 +16,7 @@ pub struct RecursionLimit { pub def_span: Span, pub def_path_str: String, #[note(monomorphize_written_to_path)] - pub was_written: Option<()>, + pub was_written: bool, pub path: PathBuf, } diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 65a3d8d1742..2f0088fb34f 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -371,7 +371,7 @@ fn merge_codegen_units<'tcx>( // Move the items from `cgu_src` to `cgu_dst`. Some of them may be // duplicate inlined items, in which case the destination CGU is // unaffected. Recalculate size estimates afterwards. - cgu_dst.items_mut().extend(cgu_src.items_mut().drain(..)); + cgu_dst.items_mut().append(cgu_src.items_mut()); cgu_dst.compute_size_estimate(); // Record that `cgu_dst` now contains all the stuff that was in @@ -410,7 +410,7 @@ fn merge_codegen_units<'tcx>( // Move the items from `smallest` to `second_smallest`. Some of them // may be duplicate inlined items, in which case the destination CGU is // unaffected. Recalculate size estimates afterwards. - second_smallest.items_mut().extend(smallest.items_mut().drain(..)); + second_smallest.items_mut().append(smallest.items_mut()); second_smallest.compute_size_estimate(); // Don't update `cgu_contents`, that's only for incremental builds. @@ -626,7 +626,6 @@ fn characteristic_def_id_of_mono_item<'tcx>( | ty::InstanceKind::FnPtrShim(..) | ty::InstanceKind::ClosureOnceShim { .. } | ty::InstanceKind::ConstructCoroutineInClosureShim { .. } - | ty::InstanceKind::CoroutineKindShim { .. } | ty::InstanceKind::Intrinsic(..) | ty::InstanceKind::DropGlue(..) | ty::InstanceKind::Virtual(..) @@ -648,7 +647,9 @@ fn characteristic_def_id_of_mono_item<'tcx>( if let Some(impl_def_id) = tcx.impl_of_method(def_id) { if tcx.sess.opts.incremental.is_some() - && tcx.trait_id_of_impl(impl_def_id) == tcx.lang_items().drop_trait() + && tcx + .trait_id_of_impl(impl_def_id) + .is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::Drop)) { // Put `Drop::drop` into the same cgu as `drop_in_place` // since `drop_in_place` is the only thing that can @@ -794,7 +795,6 @@ fn mono_item_visibility<'tcx>( | InstanceKind::Intrinsic(..) | InstanceKind::ClosureOnceShim { .. } | InstanceKind::ConstructCoroutineInClosureShim { .. } - | InstanceKind::CoroutineKindShim { .. } | InstanceKind::DropGlue(..) | InstanceKind::AsyncDropGlueCtorShim(..) | InstanceKind::CloneShim(..) diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs index 5a24202db65..b59c7bcffa9 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -127,7 +127,7 @@ fn mark_used_by_default_parameters<'tcx>( unused_parameters: &mut UnusedGenericParams, ) { match tcx.def_kind(def_id) { - DefKind::Closure => { + DefKind::Closure | DefKind::SyntheticCoroutineBody => { for param in &generics.own_params { debug!(?param, "(closure/gen)"); unused_parameters.mark_used(param.index); diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs index 82488088e30..394518daa42 100644 --- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs @@ -360,7 +360,7 @@ impl, I: Interner> TypeFolder for Canonicaliz | ty::Ref(_, _, _) | ty::Pat(_, _) | ty::FnDef(_, _) - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::Dynamic(_, _, _) | ty::Closure(..) | ty::CoroutineClosure(..) diff --git a/compiler/rustc_next_trait_solver/src/coherence.rs b/compiler/rustc_next_trait_solver/src/coherence.rs index f22ea41c512..2461ef0c0df 100644 --- a/compiler/rustc_next_trait_solver/src/coherence.rs +++ b/compiler/rustc_next_trait_solver/src/coherence.rs @@ -334,7 +334,7 @@ where | ty::Str | ty::FnDef(..) | ty::Pat(..) - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::Array(..) | ty::Slice(..) | ty::RawPtr(..) diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index 84921e87fb3..bb05eb4c256 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -533,7 +533,7 @@ where | ty::RawPtr(_, _) | ty::Ref(_, _, _) | ty::FnDef(_, _) - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::Dynamic(..) | ty::Closure(..) | ty::CoroutineClosure(..) @@ -620,7 +620,7 @@ where | ty::RawPtr(_, _) | ty::Ref(_, _, _) | ty::FnDef(_, _) - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::Alias(..) | ty::Closure(..) | ty::CoroutineClosure(..) diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index 00837f7cdd8..a57338acaab 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -31,7 +31,7 @@ where | ty::Bool | ty::Float(_) | ty::FnDef(..) - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::Error(_) | ty::Never | ty::Char => Ok(vec![]), @@ -117,7 +117,7 @@ where | ty::Bool | ty::Float(_) | ty::FnDef(..) - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::RawPtr(..) | ty::Char | ty::Ref(..) @@ -178,7 +178,7 @@ where { match ty.kind() { // impl Copy/Clone for FnDef, FnPtr - ty::FnDef(..) | ty::FnPtr(_) | ty::Error(_) => Ok(vec![]), + ty::FnDef(..) | ty::FnPtr(..) | ty::Error(_) => Ok(vec![]), // Implementations are provided in core ty::Uint(_) @@ -269,7 +269,8 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable { + ty::FnPtr(sig_tys, hdr) => { + let sig = sig_tys.with(hdr); if sig.is_fn_trait_compatible() { Ok(Some( sig.map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())), @@ -460,7 +461,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable { let sig = self_ty.fn_sig(cx); - if sig.skip_binder().is_fn_trait_compatible() && !cx.has_target_features(def_id) { + if sig.is_fn_trait_compatible() && !cx.has_target_features(def_id) { fn_item_to_async_callable(cx, sig) } else { Err(NoSolution) @@ -468,7 +469,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable { let sig = self_ty.fn_sig(cx); - if sig.skip_binder().is_fn_trait_compatible() { + if sig.is_fn_trait_compatible() { fn_item_to_async_callable(cx, sig) } else { Err(NoSolution) diff --git a/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs b/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs index a3c21666bd6..86fb036cd3d 100644 --- a/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs +++ b/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs @@ -5,11 +5,10 @@ //! see the comment on [ProofTreeBuilder]. use std::marker::PhantomData; -use std::mem; use derive_where::derive_where; use rustc_type_ir::inherent::*; -use rustc_type_ir::{self as ty, search_graph, Interner}; +use rustc_type_ir::{self as ty, Interner}; use crate::delegate::SolverDelegate; use crate::solve::eval_ctxt::canonical; @@ -94,31 +93,10 @@ impl WipGoalEvaluation { } } -#[derive_where(PartialEq, Eq; I: Interner)] -pub(in crate::solve) enum WipCanonicalGoalEvaluationKind { - Overflow, - CycleInStack, - ProvisionalCacheHit, - Interned { final_revision: I::CanonicalGoalEvaluationStepRef }, -} - -impl std::fmt::Debug for WipCanonicalGoalEvaluationKind { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::Overflow => write!(f, "Overflow"), - Self::CycleInStack => write!(f, "CycleInStack"), - Self::ProvisionalCacheHit => write!(f, "ProvisionalCacheHit"), - Self::Interned { final_revision: _ } => { - f.debug_struct("Interned").finish_non_exhaustive() - } - } - } -} - #[derive_where(PartialEq, Eq, Debug; I: Interner)] struct WipCanonicalGoalEvaluation { goal: CanonicalInput, - kind: Option>, + encountered_overflow: bool, /// Only used for uncached goals. After we finished evaluating /// the goal, this is interned and moved into `kind`. final_revision: Option>, @@ -127,25 +105,17 @@ struct WipCanonicalGoalEvaluation { impl WipCanonicalGoalEvaluation { fn finalize(self) -> inspect::CanonicalGoalEvaluation { - // We've already interned the final revision in - // `fn finalize_canonical_goal_evaluation`. - assert!(self.final_revision.is_none()); - let kind = match self.kind.unwrap() { - WipCanonicalGoalEvaluationKind::Overflow => { + inspect::CanonicalGoalEvaluation { + goal: self.goal, + kind: if self.encountered_overflow { + assert!(self.final_revision.is_none()); inspect::CanonicalGoalEvaluationKind::Overflow - } - WipCanonicalGoalEvaluationKind::CycleInStack => { - inspect::CanonicalGoalEvaluationKind::CycleInStack - } - WipCanonicalGoalEvaluationKind::ProvisionalCacheHit => { - inspect::CanonicalGoalEvaluationKind::ProvisionalCacheHit - } - WipCanonicalGoalEvaluationKind::Interned { final_revision } => { + } else { + let final_revision = self.final_revision.unwrap().finalize(); inspect::CanonicalGoalEvaluationKind::Evaluation { final_revision } - } - }; - - inspect::CanonicalGoalEvaluation { goal: self.goal, kind, result: self.result.unwrap() } + }, + result: self.result.unwrap(), + } } } @@ -308,7 +278,7 @@ impl, I: Interner> ProofTreeBuilder { ) -> ProofTreeBuilder { self.nested(|| WipCanonicalGoalEvaluation { goal, - kind: None, + encountered_overflow: false, final_revision: None, result: None, }) @@ -329,11 +299,11 @@ impl, I: Interner> ProofTreeBuilder { } } - pub fn canonical_goal_evaluation_kind(&mut self, kind: WipCanonicalGoalEvaluationKind) { + pub fn canonical_goal_evaluation_overflow(&mut self) { if let Some(this) = self.as_mut() { match this { DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation) => { - assert_eq!(canonical_goal_evaluation.kind.replace(kind), None); + canonical_goal_evaluation.encountered_overflow = true; } _ => unreachable!(), }; @@ -547,51 +517,3 @@ impl, I: Interner> ProofTreeBuilder { } } } - -impl search_graph::ProofTreeBuilder for ProofTreeBuilder -where - D: SolverDelegate, - I: Interner, -{ - fn try_apply_proof_tree( - &mut self, - proof_tree: Option, - ) -> bool { - if !self.is_noop() { - if let Some(final_revision) = proof_tree { - let kind = WipCanonicalGoalEvaluationKind::Interned { final_revision }; - self.canonical_goal_evaluation_kind(kind); - true - } else { - false - } - } else { - true - } - } - - fn on_provisional_cache_hit(&mut self) { - self.canonical_goal_evaluation_kind(WipCanonicalGoalEvaluationKind::ProvisionalCacheHit); - } - - fn on_cycle_in_stack(&mut self) { - self.canonical_goal_evaluation_kind(WipCanonicalGoalEvaluationKind::CycleInStack); - } - - fn finalize_canonical_goal_evaluation( - &mut self, - tcx: I, - ) -> Option { - self.as_mut().map(|this| match this { - DebugSolver::CanonicalGoalEvaluation(evaluation) => { - let final_revision = mem::take(&mut evaluation.final_revision).unwrap(); - let final_revision = - tcx.intern_canonical_goal_evaluation_step(final_revision.finalize()); - let kind = WipCanonicalGoalEvaluationKind::Interned { final_revision }; - assert_eq!(evaluation.kind.replace(kind), None); - final_revision - } - _ => unreachable!(), - }) - } -} diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 5738173c7a8..c7a9846cd97 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -862,7 +862,7 @@ where _ecx: &mut EvalCtxt<'_, D>, goal: Goal, ) -> Result, NoSolution> { - panic!("`BikeshedIntrinsicFrom` does not have an associated type: {:?}", goal) + panic!("`TransmuteFrom` does not have an associated type: {:?}", goal) } fn consider_builtin_effects_intersection_candidate( diff --git a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs index fe053a506e7..81c89fad8e8 100644 --- a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs +++ b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs @@ -1,12 +1,13 @@ +use std::convert::Infallible; use std::marker::PhantomData; use rustc_type_ir::inherent::*; -use rustc_type_ir::search_graph::{self, CycleKind, UsageKind}; +use rustc_type_ir::search_graph::{self, PathKind}; use rustc_type_ir::solve::{CanonicalInput, Certainty, QueryResult}; use rustc_type_ir::Interner; -use super::inspect::{self, ProofTreeBuilder}; -use super::FIXPOINT_STEP_LIMIT; +use super::inspect::ProofTreeBuilder; +use super::{has_no_inference_or_external_constraints, FIXPOINT_STEP_LIMIT}; use crate::delegate::SolverDelegate; /// This type is never constructed. We only use it to implement `search_graph::Delegate` @@ -22,43 +23,48 @@ where { type Cx = D::Interner; + const ENABLE_PROVISIONAL_CACHE: bool = true; + type ValidationScope = Infallible; + fn enter_validation_scope( + _cx: Self::Cx, + _input: CanonicalInput, + ) -> Option { + None + } + const FIXPOINT_STEP_LIMIT: usize = FIXPOINT_STEP_LIMIT; type ProofTreeBuilder = ProofTreeBuilder; + fn inspect_is_noop(inspect: &mut Self::ProofTreeBuilder) -> bool { + inspect.is_noop() + } + const DIVIDE_AVAILABLE_DEPTH_ON_OVERFLOW: usize = 4; fn recursion_limit(cx: I) -> usize { cx.recursion_limit() } fn initial_provisional_result( cx: I, - kind: CycleKind, + kind: PathKind, input: CanonicalInput, ) -> QueryResult { match kind { - CycleKind::Coinductive => response_no_constraints(cx, input, Certainty::Yes), - CycleKind::Inductive => response_no_constraints(cx, input, Certainty::overflow(false)), + PathKind::Coinductive => response_no_constraints(cx, input, Certainty::Yes), + PathKind::Inductive => response_no_constraints(cx, input, Certainty::overflow(false)), } } - fn reached_fixpoint( - cx: I, - kind: UsageKind, + fn is_initial_provisional_result( + cx: Self::Cx, + kind: PathKind, input: CanonicalInput, - provisional_result: Option>, result: QueryResult, ) -> bool { - if let Some(r) = provisional_result { - r == result - } else { - match kind { - UsageKind::Single(CycleKind::Coinductive) => { - response_no_constraints(cx, input, Certainty::Yes) == result - } - UsageKind::Single(CycleKind::Inductive) => { - response_no_constraints(cx, input, Certainty::overflow(false)) == result - } - UsageKind::Mixed => false, + match kind { + PathKind::Coinductive => response_no_constraints(cx, input, Certainty::Yes) == result, + PathKind::Inductive => { + response_no_constraints(cx, input, Certainty::overflow(false)) == result } } } @@ -68,7 +74,7 @@ where inspect: &mut ProofTreeBuilder, input: CanonicalInput, ) -> QueryResult { - inspect.canonical_goal_evaluation_kind(inspect::WipCanonicalGoalEvaluationKind::Overflow); + inspect.canonical_goal_evaluation_overflow(); response_no_constraints(cx, input, Certainty::overflow(true)) } @@ -76,6 +82,22 @@ where response_no_constraints(cx, input, Certainty::overflow(false)) } + fn is_ambiguous_result(result: QueryResult) -> bool { + result.is_ok_and(|response| { + has_no_inference_or_external_constraints(response) + && matches!(response.value.certainty, Certainty::Maybe(_)) + }) + } + + fn propagate_ambiguity( + cx: I, + for_input: CanonicalInput, + from_result: QueryResult, + ) -> QueryResult { + let certainty = from_result.unwrap().value.certainty; + response_no_constraints(cx, for_input, certainty) + } + fn step_is_coinductive(cx: I, input: CanonicalInput) -> bool { input.value.goal.predicate.is_coinductive(cx) } diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index b1dba712f79..1314b7eb6ff 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -1145,7 +1145,7 @@ where | ty::RawPtr(_, _) | ty::Ref(_, _, _) | ty::FnDef(_, _) - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::Closure(..) | ty::CoroutineClosure(..) | ty::Coroutine(_, _) diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 0d4512be480..abaff7d9c19 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -913,7 +913,7 @@ pub(crate) struct InvalidLiteralSuffixOnTupleIndex { #[help(parse_tuple_exception_line_1)] #[help(parse_tuple_exception_line_2)] #[help(parse_tuple_exception_line_3)] - pub exception: Option<()>, + pub exception: bool, } #[derive(Diagnostic)] @@ -1299,7 +1299,7 @@ pub(crate) struct ComparisonOperatorsCannotBeChained { pub suggest_turbofish: Option, #[help(parse_sugg_turbofish_syntax)] #[help(parse_sugg_parentheses_for_function_args)] - pub help_turbofish: Option<()>, + pub help_turbofish: bool, #[subdiagnostic] pub chaining_sugg: Option, } @@ -1578,7 +1578,7 @@ pub(crate) struct PathSingleColon { pub suggestion: Span, #[note(parse_type_ascription_removed)] - pub type_ascription: Option<()>, + pub type_ascription: bool, } #[derive(Diagnostic)] @@ -1589,7 +1589,7 @@ pub(crate) struct ColonAsSemi { pub span: Span, #[note(parse_type_ascription_removed)] - pub type_ascription: Option<()>, + pub type_ascription: bool, } #[derive(Diagnostic)] @@ -2462,7 +2462,7 @@ pub(crate) struct TrailingVertNotAllowed { pub start: Option, pub token: Token, #[note(parse_note_pattern_alternatives_use_single_vert)] - pub note_double_vert: Option<()>, + pub note_double_vert: bool, } #[derive(Diagnostic)] @@ -2894,7 +2894,7 @@ pub(crate) struct BadItemKind { pub descr: &'static str, pub ctx: &'static str, #[help] - pub help: Option<()>, + pub help: bool, } #[derive(Diagnostic)] diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs index fb4ed5b93b2..e7a7105803f 100644 --- a/compiler/rustc_parse/src/lexer/tokentrees.rs +++ b/compiler/rustc_parse/src/lexer/tokentrees.rs @@ -229,7 +229,7 @@ impl<'psess, 'src> TokenTreesReader<'psess, 'src> { } else { let this_spacing = if next_tok.is_punct() { Spacing::Joint - } else if next_tok.kind == token::Eof { + } else if next_tok == token::Eof { Spacing::Alone } else { Spacing::JointHidden diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 8fdfbcee385..c65cf3f40f6 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -4,11 +4,14 @@ use rustc_ast::token::{self, Delimiter}; use rustc_errors::codes::*; use rustc_errors::{Diag, PResult}; use rustc_span::symbol::kw; -use rustc_span::{sym, BytePos, Span}; +use rustc_span::{BytePos, Span}; use thin_vec::ThinVec; use tracing::debug; -use super::{AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, ParserRange, PathStyle}; +use super::{ + AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, ParserRange, PathStyle, Trailing, + UsePreAttrPos, +}; use crate::{errors, fluent_generated as fluent, maybe_whole}; // Public for rustfmt usage @@ -73,6 +76,7 @@ impl<'a> Parser<'a> { token::CommentKind::Line => OuterAttributeType::DocComment, token::CommentKind::Block => OuterAttributeType::DocBlockComment, }, + true, ) { err.note(fluent::parse_note); err.span_suggestion_verbose( @@ -136,7 +140,11 @@ impl<'a> Parser<'a> { // Emit error if inner attribute is encountered and forbidden. if style == ast::AttrStyle::Inner { - this.error_on_forbidden_inner_attr(attr_sp, inner_parse_policy); + this.error_on_forbidden_inner_attr( + attr_sp, + inner_parse_policy, + item.is_valid_for_outer_style(), + ); } Ok(attr::mk_attr_from_item(&self.psess.attr_id_generator, item, None, style, attr_sp)) @@ -148,6 +156,7 @@ impl<'a> Parser<'a> { err: &mut Diag<'_>, span: Span, attr_type: OuterAttributeType, + suggest_to_outer: bool, ) -> Option { let mut snapshot = self.create_snapshot_for_diagnostic(); let lo = span.lo() @@ -162,7 +171,7 @@ impl<'a> Parser<'a> { } loop { // skip any other attributes, we want the item - if snapshot.token.kind == token::Pound { + if snapshot.token == token::Pound { if let Err(err) = snapshot.parse_attribute(InnerAttrPolicy::Permitted) { err.cancel(); return Some(replacement_span); @@ -182,16 +191,18 @@ impl<'a> Parser<'a> { // FIXME(#100717) err.arg("item", item.kind.descr()); err.span_label(item.span, fluent::parse_label_does_not_annotate_this); - err.span_suggestion_verbose( - replacement_span, - fluent::parse_sugg_change_inner_to_outer, - match attr_type { - OuterAttributeType::Attribute => "", - OuterAttributeType::DocBlockComment => "*", - OuterAttributeType::DocComment => "/", - }, - rustc_errors::Applicability::MachineApplicable, - ); + if suggest_to_outer { + err.span_suggestion_verbose( + replacement_span, + fluent::parse_sugg_change_inner_to_outer, + match attr_type { + OuterAttributeType::Attribute => "", + OuterAttributeType::DocBlockComment => "*", + OuterAttributeType::DocComment => "/", + }, + rustc_errors::Applicability::MachineApplicable, + ); + } return None; } Err(item_err) => { @@ -202,7 +213,12 @@ impl<'a> Parser<'a> { Some(replacement_span) } - pub(super) fn error_on_forbidden_inner_attr(&self, attr_sp: Span, policy: InnerAttrPolicy) { + pub(super) fn error_on_forbidden_inner_attr( + &self, + attr_sp: Span, + policy: InnerAttrPolicy, + suggest_to_outer: bool, + ) { if let InnerAttrPolicy::Forbidden(reason) = policy { let mut diag = match reason.as_ref().copied() { Some(InnerAttrForbiddenReason::AfterOuterDocComment { prev_doc_comment_span }) => { @@ -236,6 +252,7 @@ impl<'a> Parser<'a> { &mut diag, attr_sp, OuterAttributeType::Attribute, + suggest_to_outer, ) .is_some() { @@ -257,11 +274,11 @@ impl<'a> Parser<'a> { pub fn parse_attr_item(&mut self, force_collect: ForceCollect) -> PResult<'a, ast::AttrItem> { maybe_whole!(self, NtMeta, |attr| attr.into_inner()); - let do_parse = |this: &mut Self, _empty_attrs| { + // Attr items don't have attributes. + self.collect_tokens(None, AttrWrapper::empty(), force_collect, |this, _empty_attrs| { let is_unsafe = this.eat_keyword(kw::Unsafe); let unsafety = if is_unsafe { let unsafe_span = this.prev_token.span; - this.psess.gated_spans.gate(sym::unsafe_attributes, unsafe_span); this.expect(&token::OpenDelim(Delimiter::Parenthesis))?; ast::Safety::Unsafe(unsafe_span) } else { @@ -273,10 +290,12 @@ impl<'a> Parser<'a> { if is_unsafe { this.expect(&token::CloseDelim(Delimiter::Parenthesis))?; } - Ok((ast::AttrItem { unsafety, path, args, tokens: None }, false)) - }; - // Attr items don't have attributes. - self.collect_tokens_trailing_token(AttrWrapper::empty(), force_collect, do_parse) + Ok(( + ast::AttrItem { unsafety, path, args, tokens: None }, + Trailing::No, + UsePreAttrPos::No, + )) + }) } /// Parses attributes that appear after the opening of an item. These should @@ -309,8 +328,8 @@ impl<'a> Parser<'a> { }; if let Some(attr) = attr { // If we are currently capturing tokens (i.e. we are within a call to - // `Parser::collect_tokens_trailing_tokens`) record the token positions of this - // inner attribute, for possible later processing in a `LazyAttrTokenStream`. + // `Parser::collect_tokens`) record the token positions of this inner attribute, + // for possible later processing in a `LazyAttrTokenStream`. if let Capturing::Yes = self.capture_state.capturing { let end_pos = self.num_bump_calls; let parser_range = ParserRange(start_pos..end_pos); @@ -343,7 +362,7 @@ impl<'a> Parser<'a> { // Presumably, the majority of the time there will only be one attr. let mut expanded_attrs = Vec::with_capacity(1); - while self.token.kind != token::Eof { + while self.token != token::Eof { let lo = self.token.span; let item = self.parse_attr_item(ForceCollect::Yes)?; expanded_attrs.push((item, lo.to(self.prev_token.span))); @@ -359,7 +378,7 @@ impl<'a> Parser<'a> { pub(crate) fn parse_meta_seq_top(&mut self) -> PResult<'a, ThinVec> { // Presumably, the majority of the time there will only be one attr. let mut nmis = ThinVec::with_capacity(1); - while self.token.kind != token::Eof { + while self.token != token::Eof { nmis.push(self.parse_meta_item_inner()?); if !self.eat(&token::Comma) { break; @@ -400,7 +419,6 @@ impl<'a> Parser<'a> { }; let unsafety = if is_unsafe { let unsafe_span = self.prev_token.span; - self.psess.gated_spans.gate(sym::unsafe_attributes, unsafe_span); self.expect(&token::OpenDelim(Delimiter::Parenthesis))?; ast::Safety::Unsafe(unsafe_span) diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs index abf61036c2d..49df2811d52 100644 --- a/compiler/rustc_parse/src/parser/attr_wrapper.rs +++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs @@ -12,9 +12,23 @@ use rustc_span::{sym, Span, DUMMY_SP}; use super::{ Capturing, FlatToken, ForceCollect, NodeRange, NodeReplacement, Parser, ParserRange, - TokenCursor, + TokenCursor, Trailing, }; +// When collecting tokens, this fully captures the start point. Usually its +// just after outer attributes, but occasionally it's before. +#[derive(Clone, Debug)] +pub(super) struct CollectPos { + start_token: (Token, Spacing), + cursor_snapshot: TokenCursor, + start_pos: u32, +} + +pub(super) enum UsePreAttrPos { + No, + Yes, +} + /// A wrapper type to ensure that the parser handles outer attributes correctly. /// When we parse outer attributes, we need to ensure that we capture tokens /// for the attribute target. This allows us to perform cfg-expansion on @@ -22,30 +36,32 @@ use super::{ /// /// This wrapper prevents direct access to the underlying `ast::AttrVec`. /// Parsing code can only get access to the underlying attributes -/// by passing an `AttrWrapper` to `collect_tokens_trailing_token`. +/// by passing an `AttrWrapper` to `collect_tokens`. /// This makes it difficult to accidentally construct an AST node /// (which stores an `ast::AttrVec`) without first collecting tokens. /// /// This struct has its own module, to ensure that the parser code /// cannot directly access the `attrs` field. #[derive(Debug, Clone)] -pub struct AttrWrapper { +pub(super) struct AttrWrapper { attrs: AttrVec, // The start of the outer attributes in the parser's token stream. // This lets us create a `NodeReplacement` for the entire attribute - // target, including outer attributes. - start_pos: u32, + // target, including outer attributes. `None` if there are no outer + // attributes. + start_pos: Option, } impl AttrWrapper { pub(super) fn new(attrs: AttrVec, start_pos: u32) -> AttrWrapper { - AttrWrapper { attrs, start_pos } - } - pub fn empty() -> AttrWrapper { - AttrWrapper { attrs: AttrVec::new(), start_pos: u32::MAX } + AttrWrapper { attrs, start_pos: Some(start_pos) } } - pub(crate) fn take_for_recovery(self, psess: &ParseSess) -> AttrVec { + pub(super) fn empty() -> AttrWrapper { + AttrWrapper { attrs: AttrVec::new(), start_pos: None } + } + + pub(super) fn take_for_recovery(self, psess: &ParseSess) -> AttrVec { psess.dcx().span_delayed_bug( self.attrs.get(0).map(|attr| attr.span).unwrap_or(DUMMY_SP), "AttrVec is taken for recovery but no error is produced", @@ -56,12 +72,12 @@ impl AttrWrapper { /// Prepend `self.attrs` to `attrs`. // FIXME: require passing an NT to prevent misuse of this method - pub(crate) fn prepend_to_nt_inner(mut self, attrs: &mut AttrVec) { + pub(super) fn prepend_to_nt_inner(mut self, attrs: &mut AttrVec) { mem::swap(attrs, &mut self.attrs); attrs.extend(self.attrs); } - pub fn is_empty(&self) -> bool { + pub(super) fn is_empty(&self) -> bool { self.attrs.is_empty() } } @@ -77,7 +93,7 @@ fn has_cfg_or_cfg_attr(attrs: &[Attribute]) -> bool { } // From a value of this type we can reconstruct the `TokenStream` seen by the -// `f` callback passed to a call to `Parser::collect_tokens_trailing_token`, by +// `f` callback passed to a call to `Parser::collect_tokens`, by // replaying the getting of the tokens. This saves us producing a `TokenStream` // if it is never needed, e.g. a captured `macro_rules!` argument that is never // passed to a proc macro. In practice, token stream creation happens rarely @@ -166,16 +182,30 @@ impl ToAttrTokenStream for LazyAttrTokenStreamImpl { } impl<'a> Parser<'a> { + pub(super) fn collect_pos(&self) -> CollectPos { + CollectPos { + start_token: (self.token.clone(), self.token_spacing), + cursor_snapshot: self.token_cursor.clone(), + start_pos: self.num_bump_calls, + } + } + /// Parses code with `f`. If appropriate, it records the tokens (in /// `LazyAttrTokenStream` form) that were parsed in the result, accessible - /// via the `HasTokens` trait. The second (bool) part of the callback's + /// via the `HasTokens` trait. The `Trailing` part of the callback's /// result indicates if an extra token should be captured, e.g. a comma or - /// semicolon. + /// semicolon. The `UsePreAttrPos` part of the callback's result indicates + /// if we should use `pre_attr_pos` as the collection start position (only + /// required in a few cases). /// /// The `attrs` passed in are in `AttrWrapper` form, which is opaque. The /// `AttrVec` within is passed to `f`. See the comment on `AttrWrapper` for /// details. /// + /// `pre_attr_pos` is the position before the outer attributes (or the node + /// itself, if no outer attributes are present). It is only needed if `f` + /// can return `UsePreAttrPos::Yes`. + /// /// Note: If your callback consumes an opening delimiter (including the /// case where `self.token` is an opening delimiter on entry to this /// function), you must also consume the corresponding closing delimiter. @@ -197,11 +227,12 @@ impl<'a> Parser<'a> { /// } // 32..33 /// } // 33..34 /// ``` - pub fn collect_tokens_trailing_token( + pub(super) fn collect_tokens( &mut self, + pre_attr_pos: Option, attrs: AttrWrapper, force_collect: ForceCollect, - f: impl FnOnce(&mut Self, ast::AttrVec) -> PResult<'a, (R, bool)>, + f: impl FnOnce(&mut Self, AttrVec) -> PResult<'a, (R, Trailing, UsePreAttrPos)>, ) -> PResult<'a, R> { // We must collect if anything could observe the collected tokens, i.e. // if any of the following conditions hold. @@ -220,23 +251,20 @@ impl<'a> Parser<'a> { return Ok(f(self, attrs.attrs)?.0); } - let start_token = (self.token.clone(), self.token_spacing); - let cursor_snapshot = self.token_cursor.clone(); - let start_pos = self.num_bump_calls; + let mut collect_pos = self.collect_pos(); let has_outer_attrs = !attrs.attrs.is_empty(); let parser_replacements_start = self.capture_state.parser_replacements.len(); // We set and restore `Capturing::Yes` on either side of the call to - // `f`, so we can distinguish the outermost call to - // `collect_tokens_trailing_token` (e.g. parsing `m` in the example - // above) from any inner (indirectly recursive) calls (e.g. parsing `g` - // in the example above). This distinction is used below and in - // `Parser::parse_inner_attributes`. - let (mut ret, capture_trailing) = { + // `f`, so we can distinguish the outermost call to `collect_tokens` + // (e.g. parsing `m` in the example above) from any inner (indirectly + // recursive) calls (e.g. parsing `g` in the example above). This + // distinction is used below and in `Parser::parse_inner_attributes`. + let (mut ret, capture_trailing, use_pre_attr_pos) = { let prev_capturing = mem::replace(&mut self.capture_state.capturing, Capturing::Yes); - let ret_and_trailing = f(self, attrs.attrs); + let res = f(self, attrs.attrs); self.capture_state.capturing = prev_capturing; - ret_and_trailing? + res? }; // When we're not in `capture_cfg` mode, then skip collecting and @@ -279,10 +307,18 @@ impl<'a> Parser<'a> { return Ok(ret); } + // Replace the post-attribute collection start position with the + // pre-attribute position supplied, if `f` indicated it is necessary. + // (The caller is responsible for providing a non-`None` `pre_attr_pos` + // if this is a possibility.) + if matches!(use_pre_attr_pos, UsePreAttrPos::Yes) { + collect_pos = pre_attr_pos.unwrap(); + } + let parser_replacements_end = self.capture_state.parser_replacements.len(); assert!( - !(self.break_last_token && capture_trailing), + !(self.break_last_token && matches!(capture_trailing, Trailing::Yes)), "Cannot set break_last_token and have trailing token" ); @@ -294,7 +330,7 @@ impl<'a> Parser<'a> { // `AttrTokenStream`, we will create the proper token. + self.break_last_token as u32; - let num_calls = end_pos - start_pos; + let num_calls = end_pos - collect_pos.start_pos; // Take the captured `ParserRange`s for any inner attributes that we parsed in // `Parser::parse_inner_attributes`, and pair them in a `ParserReplacement` with `None`, @@ -328,7 +364,9 @@ impl<'a> Parser<'a> { .iter() .cloned() .chain(inner_attr_parser_replacements.iter().cloned()) - .map(|(parser_range, data)| (NodeRange::new(parser_range, start_pos), data)) + .map(|(parser_range, data)| { + (NodeRange::new(parser_range, collect_pos.start_pos), data) + }) .collect() }; @@ -355,9 +393,9 @@ impl<'a> Parser<'a> { // - `tokens`: lazy tokens for `g` (with its inner attr deleted). let tokens = LazyAttrTokenStream::new(LazyAttrTokenStreamImpl { - start_token, + start_token: collect_pos.start_token, + cursor_snapshot: collect_pos.cursor_snapshot, num_calls, - cursor_snapshot, break_last_token: self.break_last_token, node_replacements, }); @@ -368,9 +406,9 @@ impl<'a> Parser<'a> { } // If `capture_cfg` is set and we're inside a recursive call to - // `collect_tokens_trailing_token`, then we need to register a replace range - // if we have `#[cfg]` or `#[cfg_attr]`. This allows us to run eager cfg-expansion - // on the captured token stream. + // `collect_tokens`, then we need to register a replace range if we + // have `#[cfg]` or `#[cfg_attr]`. This allows us to run eager + // cfg-expansion on the captured token stream. if self.capture_cfg && matches!(self.capture_state.capturing, Capturing::Yes) && has_cfg_or_cfg_attr(ret.attrs()) @@ -389,7 +427,8 @@ impl<'a> Parser<'a> { // Set things up so that the entire AST node that we just parsed, including attributes, // will be replaced with `target` in the lazy token stream. This will allow us to // cfg-expand this AST node. - let start_pos = if has_outer_attrs { attrs.start_pos } else { start_pos }; + let start_pos = + if has_outer_attrs { attrs.start_pos.unwrap() } else { collect_pos.start_pos }; let target = AttrsTarget { attrs: ret.attrs().iter().cloned().collect(), tokens }; self.capture_state .parser_replacements @@ -490,7 +529,6 @@ mod size_asserts { use super::*; // tidy-alphabetical-start - static_assert_size!(AttrWrapper, 16); static_assert_size!(LazyAttrTokenStreamImpl, 96); // tidy-alphabetical-end } diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 47ca85ba060..fcdc10c0837 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -474,8 +474,8 @@ impl<'a> Parser<'a> { // If this isn't the case however, and the suggestion is a token the // content of which is the same as the found token's, we remove it as well. if !eq { - if let TokenType::Token(kind) = &token { - if kind == &self.token.kind { + if let TokenType::Token(kind) = token { + if self.token == *kind { return false; } } @@ -506,7 +506,7 @@ impl<'a> Parser<'a> { } else if !sm.is_multiline(self.prev_token.span.until(self.token.span)) { // The current token is in the same line as the prior token, not recoverable. } else if [token::Comma, token::Colon].contains(&self.token.kind) - && self.prev_token.kind == token::CloseDelim(Delimiter::Parenthesis) + && self.prev_token == token::CloseDelim(Delimiter::Parenthesis) { // Likely typo: The current token is on a new line and is expected to be // `.`, `;`, `?`, or an operator after a close delimiter token. @@ -518,7 +518,7 @@ impl<'a> Parser<'a> { // https://github.com/rust-lang/rust/issues/72253 } else if self.look_ahead(1, |t| { t == &token::CloseDelim(Delimiter::Brace) - || t.can_begin_expr() && t.kind != token::Colon + || t.can_begin_expr() && *t != token::Colon }) && [token::Comma, token::Colon].contains(&self.token.kind) { // Likely typo: `,` → `;` or `:` → `;`. This is triggered if the current token is @@ -562,7 +562,7 @@ impl<'a> Parser<'a> { } } - if self.token.kind == TokenKind::EqEq + if self.token == TokenKind::EqEq && self.prev_token.is_ident() && expected.iter().any(|tok| matches!(tok, TokenType::Token(TokenKind::Eq))) { @@ -655,9 +655,9 @@ impl<'a> Parser<'a> { // positive for a `cr#` that wasn't intended to start a c-string literal, but identifying // that in the parser requires unbounded lookahead, so we only add a hint to the existing // error rather than replacing it entirely. - if ((self.prev_token.kind == TokenKind::Ident(sym::c, IdentIsRaw::No) + if ((self.prev_token == TokenKind::Ident(sym::c, IdentIsRaw::No) && matches!(&self.token.kind, TokenKind::Literal(token::Lit { kind: token::Str, .. }))) - || (self.prev_token.kind == TokenKind::Ident(sym::cr, IdentIsRaw::No) + || (self.prev_token == TokenKind::Ident(sym::cr, IdentIsRaw::No) && matches!( &self.token.kind, TokenKind::Literal(token::Lit { kind: token::Str, .. }) | token::Pound @@ -673,7 +673,7 @@ impl<'a> Parser<'a> { // `pub` may be used for an item or `pub(crate)` if self.prev_token.is_ident_named(sym::public) && (self.token.can_begin_item() - || self.token.kind == TokenKind::OpenDelim(Delimiter::Parenthesis)) + || self.token == TokenKind::OpenDelim(Delimiter::Parenthesis)) { err.span_suggestion_short( self.prev_token.span, @@ -772,7 +772,7 @@ impl<'a> Parser<'a> { ), ); if self.token == token::Pound - && self.look_ahead(1, |t| t.kind == token::OpenDelim(Delimiter::Bracket)) + && self.look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Bracket)) { // We have // #[attr] @@ -867,7 +867,7 @@ impl<'a> Parser<'a> { let str_span = self.prev_token.span; let mut span = self.token.span; let mut count = 0; - while self.token.kind == TokenKind::Pound + while self.token == TokenKind::Pound && !sm.is_multiline(span.shrink_to_hi().until(self.token.span.shrink_to_lo())) { span = span.with_hi(self.token.span.hi()); @@ -1167,7 +1167,7 @@ impl<'a> Parser<'a> { return; } - if token::PathSep == self.token.kind && segment.args.is_none() { + if self.token == token::PathSep && segment.args.is_none() { let snapshot = self.create_snapshot_for_diagnostic(); self.bump(); let lo = self.token.span; @@ -1176,13 +1176,11 @@ impl<'a> Parser<'a> { let span = lo.to(self.prev_token.span); // Detect trailing `>` like in `x.collect::Vec<_>>()`. let mut trailing_span = self.prev_token.span.shrink_to_hi(); - while self.token.kind == token::BinOp(token::Shr) - || self.token.kind == token::Gt - { + while self.token == token::BinOp(token::Shr) || self.token == token::Gt { trailing_span = trailing_span.to(self.token.span); self.bump(); } - if self.token.kind == token::OpenDelim(Delimiter::Parenthesis) { + if self.token == token::OpenDelim(Delimiter::Parenthesis) { // Recover from bad turbofish: `foo.collect::Vec<_>()`. segment.args = Some(AngleBracketedArgs { args, span }.into()); @@ -1405,7 +1403,7 @@ impl<'a> Parser<'a> { let mut err = ComparisonOperatorsCannotBeChained { span: vec![op.span, self.prev_token.span], suggest_turbofish: None, - help_turbofish: None, + help_turbofish: false, chaining_sugg: None, }; @@ -1430,7 +1428,7 @@ impl<'a> Parser<'a> { self.restore_snapshot(snapshot); } } - return if token::PathSep == self.token.kind { + return if self.token == token::PathSep { // We have some certainty that this was a bad turbofish at this point. // `foo< bar >::` if let ExprKind::Binary(o, ..) = inner_op.kind @@ -1438,7 +1436,7 @@ impl<'a> Parser<'a> { { err.suggest_turbofish = Some(op.span.shrink_to_lo()); } else { - err.help_turbofish = Some(()); + err.help_turbofish = true; } let snapshot = self.create_snapshot_for_diagnostic(); @@ -1462,7 +1460,7 @@ impl<'a> Parser<'a> { Err(self.dcx().create_err(err)) } } - } else if token::OpenDelim(Delimiter::Parenthesis) == self.token.kind { + } else if self.token == token::OpenDelim(Delimiter::Parenthesis) { // We have high certainty that this was a bad turbofish at this point. // `foo< bar >(` if let ExprKind::Binary(o, ..) = inner_op.kind @@ -1470,7 +1468,7 @@ impl<'a> Parser<'a> { { err.suggest_turbofish = Some(op.span.shrink_to_lo()); } else { - err.help_turbofish = Some(()); + err.help_turbofish = true; } // Consume the fn call arguments. match self.consume_fn_args() { @@ -1489,7 +1487,7 @@ impl<'a> Parser<'a> { { // All we know is that this is `foo < bar >` and *nothing* else. Try to // be helpful, but don't attempt to recover. - err.help_turbofish = Some(()); + err.help_turbofish = true; } // If it looks like a genuine attempt to chain operators (as opposed to a @@ -1528,7 +1526,7 @@ impl<'a> Parser<'a> { ]; self.consume_tts(1, &modifiers); - if self.token.kind == token::Eof { + if self.token == token::Eof { // Not entirely sure that what we consumed were fn arguments, rollback. self.restore_snapshot(snapshot); Err(()) @@ -1811,7 +1809,7 @@ impl<'a> Parser<'a> { /// This function gets called in places where a semicolon is NOT expected and if there's a /// semicolon it emits the appropriate error and returns true. pub fn maybe_consume_incorrect_semicolon(&mut self, previous_item: Option<&Item>) -> bool { - if self.token.kind != TokenKind::Semi { + if self.token != TokenKind::Semi { return false; } @@ -1897,7 +1895,7 @@ impl<'a> Parser<'a> { { self.dcx().emit_err(ColonAsSemi { span: self.token.span, - type_ascription: self.psess.unstable_features.is_nightly_build().then_some(()), + type_ascription: self.psess.unstable_features.is_nightly_build(), }); self.bump(); return true; @@ -2405,10 +2403,10 @@ impl<'a> Parser<'a> { modifier: &[(token::TokenKind, i64)], ) { while acc > 0 { - if let Some((_, val)) = modifier.iter().find(|(t, _)| *t == self.token.kind) { + if let Some((_, val)) = modifier.iter().find(|(t, _)| self.token == *t) { acc += *val; } - if self.token.kind == token::Eof { + if self.token == token::Eof { break; } self.bump(); @@ -2489,13 +2487,14 @@ impl<'a> Parser<'a> { pub(super) fn handle_unambiguous_unbraced_const_arg(&mut self) -> PResult<'a, P> { let start = self.token.span; let attrs = self.parse_outer_attributes()?; - let expr = self.parse_expr_res(Restrictions::CONST_EXPR, attrs).map_err(|mut err| { - err.span_label( - start.shrink_to_lo(), - "while parsing a const generic argument starting here", - ); - err - })?; + let (expr, _) = + self.parse_expr_res(Restrictions::CONST_EXPR, attrs).map_err(|mut err| { + err.span_label( + start.shrink_to_lo(), + "while parsing a const generic argument starting here", + ); + err + })?; if !self.expr_is_valid_const_arg(&expr) { self.dcx().emit_err(ConstGenericWithoutBraces { span: expr.span, @@ -2598,7 +2597,7 @@ impl<'a> Parser<'a> { } }) .is_some() - || self.token.kind == TokenKind::Dot; + || self.token == TokenKind::Dot; // This will be true when a trait object type `Foo +` or a path which was a `const fn` with // type params has been parsed. let was_op = @@ -2615,9 +2614,9 @@ impl<'a> Parser<'a> { let attrs = self.parse_outer_attributes()?; self.parse_expr_res(Restrictions::CONST_EXPR, attrs) })() { - Ok(expr) => { + Ok((expr, _)) => { // Find a mistake like `MyTrait`. - if token::EqEq == snapshot.token.kind { + if snapshot.token == token::EqEq { err.span_suggestion( snapshot.token.span, "if you meant to use an associated type binding, replace `==` with `=`", @@ -2627,7 +2626,7 @@ impl<'a> Parser<'a> { let guar = err.emit(); let value = self.mk_expr_err(start.to(expr.span), guar); return Ok(GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value })); - } else if token::Colon == snapshot.token.kind + } else if snapshot.token == token::Colon && expr.span.lo() == snapshot.token.span.hi() && matches!(expr.kind, ExprKind::Path(..)) { @@ -2642,8 +2641,7 @@ impl<'a> Parser<'a> { return Ok(GenericArg::Type( self.mk_ty(start.to(expr.span), TyKind::Err(guar)), )); - } else if token::Comma == self.token.kind || self.token.kind.should_end_const_arg() - { + } else if self.token == token::Comma || self.token.kind.should_end_const_arg() { // Avoid the following output by checking that we consumed a full const arg: // help: expressions must be enclosed in braces to be used as const generic // arguments @@ -2674,7 +2672,7 @@ impl<'a> Parser<'a> { })() { // Since we don't know the exact reason why we failed to parse the type or the // expression, employ a simple heuristic to weed out some pathological cases. - Ok(expr) if let token::Comma | token::Gt = snapshot.token.kind => { + Ok((expr, _)) if let token::Comma | token::Gt = snapshot.token.kind => { self.restore_snapshot(snapshot); Some(expr) } @@ -2846,8 +2844,8 @@ impl<'a> Parser<'a> { pub(crate) fn maybe_recover_unexpected_block_label(&mut self) -> bool { // Check for `'a : {` if !(self.check_lifetime() - && self.look_ahead(1, |tok| tok.kind == token::Colon) - && self.look_ahead(2, |tok| tok.kind == token::OpenDelim(Delimiter::Brace))) + && self.look_ahead(1, |t| *t == token::Colon) + && self.look_ahead(2, |t| *t == token::OpenDelim(Delimiter::Brace))) { return false; } @@ -3001,7 +2999,7 @@ impl<'a> Parser<'a> { // >>>>>>> let mut end = None; loop { - if self.token.kind == TokenKind::Eof { + if self.token == TokenKind::Eof { break; } if let Some(span) = self.conflict_marker(&TokenKind::OrOr, &TokenKind::BinOp(token::Or)) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index cf5d65708ab..84684e808d9 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -36,7 +36,7 @@ use super::pat::{CommaRecoveryMode, Expected, RecoverColon, RecoverComma}; use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; use super::{ AttrWrapper, BlockMode, ClosureSpans, ForceCollect, Parser, PathStyle, Restrictions, - SemiColonMode, SeqSep, TokenType, Trailing, + SemiColonMode, SeqSep, TokenType, Trailing, UsePreAttrPos, }; use crate::{errors, maybe_recover_from_interpolated_ty_qpath}; @@ -59,15 +59,30 @@ impl<'a> Parser<'a> { self.current_closure.take(); let attrs = self.parse_outer_attributes()?; - self.parse_expr_res(Restrictions::empty(), attrs) + self.parse_expr_res(Restrictions::empty(), attrs).map(|res| res.0) } /// Parses an expression, forcing tokens to be collected. pub fn parse_expr_force_collect(&mut self) -> PResult<'a, P> { self.current_closure.take(); + // If the expression is associative (e.g. `1 + 2`), then any preceding + // outer attribute actually belongs to the first inner sub-expression. + // In which case we must use the pre-attr pos to include the attribute + // in the collected tokens for the outer expression. + let pre_attr_pos = self.collect_pos(); let attrs = self.parse_outer_attributes()?; - self.collect_tokens_no_attrs(|this| this.parse_expr_res(Restrictions::empty(), attrs)) + self.collect_tokens( + Some(pre_attr_pos), + AttrWrapper::empty(), + ForceCollect::Yes, + |this, _empty_attrs| { + let (expr, is_assoc) = this.parse_expr_res(Restrictions::empty(), attrs)?; + let use_pre_attr_pos = + if is_assoc { UsePreAttrPos::Yes } else { UsePreAttrPos::No }; + Ok((expr, Trailing::No, use_pre_attr_pos)) + }, + ) } pub fn parse_expr_anon_const(&mut self) -> PResult<'a, AnonConst> { @@ -77,7 +92,7 @@ impl<'a> Parser<'a> { fn parse_expr_catch_underscore(&mut self, restrictions: Restrictions) -> PResult<'a, P> { let attrs = self.parse_outer_attributes()?; match self.parse_expr_res(restrictions, attrs) { - Ok(expr) => Ok(expr), + Ok((expr, _)) => Ok(expr), Err(err) => match self.token.ident() { Some((Ident { name: kw::Underscore, .. }, IdentIsRaw::No)) if self.may_recover() && self.look_ahead(1, |t| t == &token::Comma) => @@ -104,18 +119,20 @@ impl<'a> Parser<'a> { &mut self, r: Restrictions, attrs: AttrWrapper, - ) -> PResult<'a, P> { + ) -> PResult<'a, (P, bool)> { self.with_res(r, |this| this.parse_expr_assoc_with(0, attrs)) } /// Parses an associative expression with operators of at least `min_prec` precedence. + /// The `bool` in the return value indicates if it was an assoc expr, i.e. with an operator + /// followed by a subexpression (e.g. `1 + 2`). pub(super) fn parse_expr_assoc_with( &mut self, min_prec: usize, attrs: AttrWrapper, - ) -> PResult<'a, P> { + ) -> PResult<'a, (P, bool)> { let lhs = if self.token.is_range_separator() { - return self.parse_expr_prefix_range(attrs); + return self.parse_expr_prefix_range(attrs).map(|res| (res, false)); } else { self.parse_expr_prefix(attrs)? }; @@ -123,15 +140,17 @@ impl<'a> Parser<'a> { } /// Parses the rest of an associative expression (i.e. the part after the lhs) with operators - /// of at least `min_prec` precedence. + /// of at least `min_prec` precedence. The `bool` in the return value indicates if something + /// was actually parsed. pub(super) fn parse_expr_assoc_rest_with( &mut self, min_prec: usize, starts_stmt: bool, mut lhs: P, - ) -> PResult<'a, P> { + ) -> PResult<'a, (P, bool)> { + let mut parsed_something = false; if !self.should_continue_as_assoc_expr(&lhs) { - return Ok(lhs); + return Ok((lhs, parsed_something)); } self.expected_tokens.push(TokenType::Operator); @@ -156,16 +175,17 @@ impl<'a> Parser<'a> { self.err_larrow_operator(self.token.span); } + parsed_something = true; self.bump(); if op.node.is_comparison() { if let Some(expr) = self.check_no_chained_comparison(&lhs, &op)? { - return Ok(expr); + return Ok((expr, parsed_something)); } } // Look for JS' `===` and `!==` and recover if (op.node == AssocOp::Equal || op.node == AssocOp::NotEqual) - && self.token.kind == token::Eq + && self.token == token::Eq && self.prev_token.span.hi() == self.token.span.lo() { let sp = op.span.to(self.token.span); @@ -190,7 +210,7 @@ impl<'a> Parser<'a> { // Look for PHP's `<>` and recover if op.node == AssocOp::Less - && self.token.kind == token::Gt + && self.token == token::Gt && self.prev_token.span.hi() == self.token.span.lo() { let sp = op.span.to(self.token.span); @@ -208,7 +228,7 @@ impl<'a> Parser<'a> { // Look for C++'s `<=>` and recover if op.node == AssocOp::LessEqual - && self.token.kind == token::Gt + && self.token == token::Gt && self.prev_token.span.hi() == self.token.span.lo() { let sp = op.span.to(self.token.span); @@ -263,7 +283,7 @@ impl<'a> Parser<'a> { // the special cases. The code is here only for future convenience. Fixity::None => 1, }; - let rhs = self.with_res(restrictions - Restrictions::STMT_EXPR, |this| { + let (rhs, _) = self.with_res(restrictions - Restrictions::STMT_EXPR, |this| { let attrs = this.parse_outer_attributes()?; this.parse_expr_assoc_with(prec + prec_adjustment, attrs) })?; @@ -319,7 +339,7 @@ impl<'a> Parser<'a> { } } - Ok(lhs) + Ok((lhs, parsed_something)) } fn should_continue_as_assoc_expr(&mut self, lhs: &Expr) -> bool { @@ -441,7 +461,8 @@ impl<'a> Parser<'a> { let attrs = self.parse_outer_attributes()?; Some( self.parse_expr_assoc_with(prec + 1, attrs) - .map_err(|err| self.maybe_err_dotdotlt_syntax(maybe_lt, err))?, + .map_err(|err| self.maybe_err_dotdotlt_syntax(maybe_lt, err))? + .0, ) } else { None @@ -498,7 +519,7 @@ impl<'a> Parser<'a> { // RHS must be parsed with more associativity than the dots. let attrs = this.parse_outer_attributes()?; this.parse_expr_assoc_with(op.unwrap().precedence() + 1, attrs) - .map(|x| (lo.to(x.span), Some(x))) + .map(|(x, _)| (lo.to(x.span), Some(x))) .map_err(|err| this.maybe_err_dotdotlt_syntax(maybe_lt, err))? } else { (lo, None) @@ -830,7 +851,7 @@ impl<'a> Parser<'a> { self.expect_and()?; let has_lifetime = self.token.is_lifetime() && self.look_ahead(1, |t| t != &token::Colon); let lifetime = has_lifetime.then(|| self.expect_lifetime()); // For recovery, see below. - let (borrow_kind, mutbl) = self.parse_borrow_modifiers(lo); + let (borrow_kind, mutbl) = self.parse_borrow_modifiers(); let attrs = self.parse_outer_attributes()?; let expr = if self.token.is_range_separator() { self.parse_expr_prefix_range(attrs) @@ -850,13 +871,12 @@ impl<'a> Parser<'a> { } /// Parse `mut?` or `raw [ const | mut ]`. - fn parse_borrow_modifiers(&mut self, lo: Span) -> (ast::BorrowKind, ast::Mutability) { + fn parse_borrow_modifiers(&mut self) -> (ast::BorrowKind, ast::Mutability) { if self.check_keyword(kw::Raw) && self.look_ahead(1, Token::is_mutability) { // `raw [ const | mut ]`. let found_raw = self.eat_keyword(kw::Raw); assert!(found_raw); let mutability = self.parse_const_or_mut().unwrap(); - self.psess.gated_spans.gate(sym::raw_ref_op, lo.to(self.prev_token.span)); (ast::BorrowKind::Raw, mutability) } else { // `mut?` @@ -882,7 +902,7 @@ impl<'a> Parser<'a> { let mut res = ensure_sufficient_stack(|| { loop { let has_question = - if self.prev_token.kind == TokenKind::Ident(kw::Return, IdentIsRaw::No) { + if self.prev_token == TokenKind::Ident(kw::Return, IdentIsRaw::No) { // We are using noexpect here because we don't expect a `?` directly after // a `return` which could be suggested otherwise. self.eat_noexpect(&token::Question) @@ -894,20 +914,19 @@ impl<'a> Parser<'a> { e = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Try(e)); continue; } - let has_dot = - if self.prev_token.kind == TokenKind::Ident(kw::Return, IdentIsRaw::No) { - // We are using noexpect here because we don't expect a `.` directly after - // a `return` which could be suggested otherwise. - self.eat_noexpect(&token::Dot) - } else if self.token.kind == TokenKind::RArrow && self.may_recover() { - // Recovery for `expr->suffix`. - self.bump(); - let span = self.prev_token.span; - self.dcx().emit_err(errors::ExprRArrowCall { span }); - true - } else { - self.eat(&token::Dot) - }; + let has_dot = if self.prev_token == TokenKind::Ident(kw::Return, IdentIsRaw::No) { + // We are using noexpect here because we don't expect a `.` directly after + // a `return` which could be suggested otherwise. + self.eat_noexpect(&token::Dot) + } else if self.token == TokenKind::RArrow && self.may_recover() { + // Recovery for `expr->suffix`. + self.bump(); + let span = self.prev_token.span; + self.dcx().emit_err(errors::ExprRArrowCall { span }); + true + } else { + self.eat(&token::Dot) + }; if has_dot { // expr.f e = self.parse_dot_suffix_expr(lo, e)?; @@ -1206,7 +1225,7 @@ impl<'a> Parser<'a> { } fn mk_expr_tuple_field_access( - &mut self, + &self, lo: Span, ident_span: Span, base: P, @@ -1221,7 +1240,7 @@ impl<'a> Parser<'a> { /// Parse a function call expression, `expr(...)`. fn parse_expr_fn_call(&mut self, lo: Span, fun: P) -> P { - let snapshot = if self.token.kind == token::OpenDelim(Delimiter::Parenthesis) { + let snapshot = if self.token == token::OpenDelim(Delimiter::Parenthesis) { Some((self.create_snapshot_for_diagnostic(), fun.kind.clone())) } else { None @@ -1585,7 +1604,7 @@ impl<'a> Parser<'a> { // Suggests using '<=' if there is an error parsing qpath when the previous token // is an '=' token. Only emits suggestion if the '<' token and '=' token are // directly adjacent (i.e. '=<') - if maybe_eq_tok.kind == TokenKind::Eq && maybe_eq_tok.span.hi() == lt_span.lo() { + if maybe_eq_tok == TokenKind::Eq && maybe_eq_tok.span.hi() == lt_span.lo() { let eq_lt = maybe_eq_tok.span.to(lt_span); err.span_suggestion(eq_lt, "did you mean", "<=", Applicability::Unspecified); } @@ -2143,13 +2162,13 @@ impl<'a> Parser<'a> { self.dcx().emit_warn(errors::InvalidLiteralSuffixOnTupleIndex { span, suffix, - exception: Some(()), + exception: true, }); } else { self.dcx().emit_err(errors::InvalidLiteralSuffixOnTupleIndex { span, suffix, - exception: None, + exception: false, }); } } @@ -2230,7 +2249,7 @@ impl<'a> Parser<'a> { return Ok(()); } - if self.token.kind == token::Comma { + if self.token == token::Comma { if !self.psess.source_map().is_multiline(prev_span.until(self.token.span)) { return Ok(()); } @@ -2336,7 +2355,7 @@ impl<'a> Parser<'a> { let token = self.token.clone(); let attrs = self.parse_outer_attributes()?; match self.parse_expr_res(restrictions, attrs) { - Ok(expr) => expr, + Ok((expr, _)) => expr, Err(err) => self.recover_closure_body(err, before, prev, token, lo, decl_hi)?, } } @@ -2360,7 +2379,7 @@ impl<'a> Parser<'a> { None => {} } - if self.token.kind == TokenKind::Semi + if self.token == TokenKind::Semi && matches!(self.token_cursor.stack.last(), Some((.., Delimiter::Parenthesis))) && self.may_recover() { @@ -2446,7 +2465,7 @@ impl<'a> Parser<'a> { fn parse_fn_block_param(&mut self) -> PResult<'a, Param> { let lo = self.token.span; let attrs = self.parse_outer_attributes()?; - self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { + self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| { let pat = this.parse_pat_no_top_alt(Some(Expected::ParameterName), None)?; let ty = if this.eat(&token::Colon) { this.parse_ty()? @@ -2463,7 +2482,8 @@ impl<'a> Parser<'a> { id: DUMMY_NODE_ID, is_placeholder: false, }, - this.token == token::Comma, + Trailing::from(this.token == token::Comma), + UsePreAttrPos::No, )) }) } @@ -2557,7 +2577,7 @@ impl<'a> Parser<'a> { ); } else { // Look for usages of '=>' where '>=' might be intended - if maybe_fatarrow.kind == token::FatArrow { + if maybe_fatarrow == token::FatArrow { err.span_suggestion( maybe_fatarrow.span, "you might have meant to write a \"greater than or equal to\" comparison", @@ -2584,7 +2604,7 @@ impl<'a> Parser<'a> { /// Parses the condition of a `if` or `while` expression. fn parse_expr_cond(&mut self) -> PResult<'a, P> { let attrs = self.parse_outer_attributes()?; - let mut cond = + let (mut cond, _) = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL | Restrictions::ALLOW_LET, attrs)?; CondChecker::new(self).visit_expr(&mut cond); @@ -2606,7 +2626,7 @@ impl<'a> Parser<'a> { missing_let: None, comparison: None, }; - if self.prev_token.kind == token::BinOp(token::Or) { + if self.prev_token == token::BinOp(token::Or) { // This was part of a closure, the that part of the parser recover. return Err(self.dcx().create_err(err)); } else { @@ -2633,7 +2653,7 @@ impl<'a> Parser<'a> { self.expect(&token::Eq)?; } let attrs = self.parse_outer_attributes()?; - let expr = self.parse_expr_assoc_with(1 + prec_let_scrutinee_needs_par(), attrs)?; + let (expr, _) = self.parse_expr_assoc_with(1 + prec_let_scrutinee_needs_par(), attrs)?; let span = lo.to(expr.span); Ok(self.mk_expr(span, ExprKind::Let(pat, expr, span, recovered))) } @@ -2742,7 +2762,7 @@ impl<'a> Parser<'a> { } fn parse_for_head(&mut self) -> PResult<'a, (P, P)> { - let begin_paren = if self.token.kind == token::OpenDelim(Delimiter::Parenthesis) { + let begin_paren = if self.token == token::OpenDelim(Delimiter::Parenthesis) { // Record whether we are about to parse `for (`. // This is used below for recovery in case of `for ( $stuff ) $block` // in which case we will suggest `for $stuff $block`. @@ -2767,7 +2787,7 @@ impl<'a> Parser<'a> { // We know for sure we have seen `for ($SOMETHING in`. In the happy path this would // happen right before the return of this method. let attrs = self.parse_outer_attributes()?; - let expr = match self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, attrs) { + let (expr, _) = match self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, attrs) { Ok(expr) => expr, Err(expr_err) => { // We don't know what followed the `in`, so cancel and bubble up the @@ -2776,7 +2796,7 @@ impl<'a> Parser<'a> { return Err(err); } }; - return if self.token.kind == token::CloseDelim(Delimiter::Parenthesis) { + return if self.token == token::CloseDelim(Delimiter::Parenthesis) { // We know for sure we have seen `for ($SOMETHING in $EXPR)`, so we recover the // parser state and emit a targeted suggestion. let span = vec![start_span, self.token.span]; @@ -2802,7 +2822,7 @@ impl<'a> Parser<'a> { } self.check_for_for_in_in_typo(self.prev_token.span); let attrs = self.parse_outer_attributes()?; - let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, attrs)?; + let (expr, _) = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, attrs)?; Ok((pat, expr)) } @@ -2922,7 +2942,7 @@ impl<'a> Parser<'a> { fn parse_expr_match(&mut self) -> PResult<'a, P> { let match_span = self.prev_token.span; let attrs = self.parse_outer_attributes()?; - let scrutinee = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, attrs)?; + let (scrutinee, _) = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, attrs)?; self.parse_match_block(match_span, match_span, scrutinee, MatchKind::Prefix) } @@ -2995,7 +3015,7 @@ impl<'a> Parser<'a> { first_expr: &P, arrow_span: Span, ) -> Option<(Span, ErrorGuaranteed)> { - if self.token.kind != token::Semi { + if self.token != token::Semi { return None; } let start_snapshot = self.create_snapshot_for_diagnostic(); @@ -3024,18 +3044,18 @@ impl<'a> Parser<'a> { // We might have either a `,` -> `;` typo, or a block without braces. We need // a more subtle parsing strategy. loop { - if self.token.kind == token::CloseDelim(Delimiter::Brace) { + if self.token == token::CloseDelim(Delimiter::Brace) { // We have reached the closing brace of the `match` expression. return Some(err(self, stmts)); } - if self.token.kind == token::Comma { + if self.token == token::Comma { self.restore_snapshot(start_snapshot); return None; } let pre_pat_snapshot = self.create_snapshot_for_diagnostic(); match self.parse_pat_no_top_alt(None, None) { Ok(_pat) => { - if self.token.kind == token::FatArrow { + if self.token == token::FatArrow { // Reached arm end. self.restore_snapshot(pre_pat_snapshot); return Some(err(self, stmts)); @@ -3070,7 +3090,7 @@ impl<'a> Parser<'a> { pub(super) fn parse_arm(&mut self) -> PResult<'a, Arm> { let attrs = self.parse_outer_attributes()?; - self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { + self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| { let lo = this.token.span; let (pat, guard) = this.parse_match_arm_pat_and_guard()?; @@ -3127,7 +3147,7 @@ impl<'a> Parser<'a> { let arm_start_span = this.token.span; let attrs = this.parse_outer_attributes()?; - let expr = + let (expr, _) = this.parse_expr_res(Restrictions::STMT_EXPR, attrs).map_err(|mut err| { err.span_label(arrow_span, "while parsing the `match` arm starting here"); err @@ -3244,7 +3264,8 @@ impl<'a> Parser<'a> { id: DUMMY_NODE_ID, is_placeholder: false, }, - false, + Trailing::No, + UsePreAttrPos::No, )) }) } @@ -3286,7 +3307,7 @@ impl<'a> Parser<'a> { } fn parse_match_arm_pat_and_guard(&mut self) -> PResult<'a, (P, Option>)> { - if self.token.kind == token::OpenDelim(Delimiter::Parenthesis) { + if self.token == token::OpenDelim(Delimiter::Parenthesis) { // Detect and recover from `($pat if $cond) => $arm`. let left = self.token.span; match self.parse_pat_allow_top_alt( @@ -3335,8 +3356,9 @@ impl<'a> Parser<'a> { fn parse_match_guard_condition(&mut self) -> PResult<'a, P> { let attrs = self.parse_outer_attributes()?; - self.parse_expr_res(Restrictions::ALLOW_LET | Restrictions::IN_IF_GUARD, attrs).map_err( - |mut err| { + match self.parse_expr_res(Restrictions::ALLOW_LET | Restrictions::IN_IF_GUARD, attrs) { + Ok((expr, _)) => Ok(expr), + Err(mut err) => { if self.prev_token == token::OpenDelim(Delimiter::Brace) { let sugg_sp = self.prev_token.span.shrink_to_lo(); // Consume everything within the braces, let's avoid further parse @@ -3344,7 +3366,7 @@ impl<'a> Parser<'a> { self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore); let msg = "you might have meant to start a match arm after the match guard"; if self.eat(&token::CloseDelim(Delimiter::Brace)) { - let applicability = if self.token.kind != token::FatArrow { + let applicability = if self.token != token::FatArrow { // We have high confidence that we indeed didn't have a struct // literal in the match guard, but rather we had some operation // that ended in a path, immediately followed by a block that was @@ -3356,9 +3378,9 @@ impl<'a> Parser<'a> { err.span_suggestion_verbose(sugg_sp, msg, "=> ", applicability); } } - err - }, - ) + Err(err) + } + } } pub(crate) fn is_builtin(&self) -> bool { @@ -3565,7 +3587,7 @@ impl<'a> Parser<'a> { && self.look_ahead(1, |t| { AssocOp::from_token(t).is_some() || matches!(t.kind, token::OpenDelim(_)) - || t.kind == token::Dot + || *t == token::Dot }) { // Looks like they tried to write a shorthand, complex expression. @@ -3709,7 +3731,7 @@ impl<'a> Parser<'a> { fn parse_expr_field(&mut self) -> PResult<'a, ExprField> { let attrs = self.parse_outer_attributes()?; self.recover_vcs_conflict_marker(); - self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { + self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| { let lo = this.token.span; // Check if a colon exists one ahead. This means we're parsing a fieldname. @@ -3753,7 +3775,8 @@ impl<'a> Parser<'a> { id: DUMMY_NODE_ID, is_placeholder: false, }, - this.token == token::Comma, + Trailing::from(this.token == token::Comma), + UsePreAttrPos::No, )) }) } @@ -3847,15 +3870,17 @@ impl<'a> Parser<'a> { attrs: AttrWrapper, f: impl FnOnce(&mut Self, ast::AttrVec) -> PResult<'a, P>, ) -> PResult<'a, P> { - self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { + self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| { let res = f(this, attrs)?; - let trailing = (this.restrictions.contains(Restrictions::STMT_EXPR) - && this.token.kind == token::Semi) - // FIXME: pass an additional condition through from the place - // where we know we need a comma, rather than assuming that - // `#[attr] expr,` always captures a trailing comma. - || this.token.kind == token::Comma; - Ok((res, trailing)) + let trailing = Trailing::from( + this.restrictions.contains(Restrictions::STMT_EXPR) + && this.token == token::Semi + // FIXME: pass an additional condition through from the place + // where we know we need a comma, rather than assuming that + // `#[attr] expr,` always captures a trailing comma. + || this.token == token::Comma, + ); + Ok((res, trailing, UsePreAttrPos::No)) }) } } diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index 9124c15707d..af3b6f740e3 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -7,7 +7,7 @@ use rustc_span::symbol::{kw, Ident}; use rustc_span::Span; use thin_vec::ThinVec; -use super::{ForceCollect, Parser}; +use super::{ForceCollect, Parser, Trailing, UsePreAttrPos}; use crate::errors::{ self, MultipleWhereClauses, UnexpectedDefaultValueForLifetimeInGenericParameters, UnexpectedSelfInGenericParameters, WhereClauseBeforeTupleStructBody, @@ -169,94 +169,88 @@ impl<'a> Parser<'a> { let mut done = false; while !done { let attrs = self.parse_outer_attributes()?; - let param = - self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { - if this.eat_keyword_noexpect(kw::SelfUpper) { - // `Self` as a generic param is invalid. Here we emit the diagnostic and continue parsing - // as if `Self` never existed. - this.dcx().emit_err(UnexpectedSelfInGenericParameters { - span: this.prev_token.span, - }); + let param = self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| { + if this.eat_keyword_noexpect(kw::SelfUpper) { + // `Self` as a generic param is invalid. Here we emit the diagnostic and continue parsing + // as if `Self` never existed. + this.dcx() + .emit_err(UnexpectedSelfInGenericParameters { span: this.prev_token.span }); - // Eat a trailing comma, if it exists. - let _ = this.eat(&token::Comma); - } + // Eat a trailing comma, if it exists. + let _ = this.eat(&token::Comma); + } - let param = if this.check_lifetime() { - let lifetime = this.expect_lifetime(); - // Parse lifetime parameter. - let (colon_span, bounds) = if this.eat(&token::Colon) { - (Some(this.prev_token.span), this.parse_lt_param_bounds()) - } else { - (None, Vec::new()) - }; - - if this.check_noexpect(&token::Eq) - && this.look_ahead(1, |t| t.is_lifetime()) - { - let lo = this.token.span; - // Parse `= 'lifetime`. - this.bump(); // `=` - this.bump(); // `'lifetime` - let span = lo.to(this.prev_token.span); - this.dcx().emit_err( - UnexpectedDefaultValueForLifetimeInGenericParameters { span }, - ); - } - - Some(ast::GenericParam { - ident: lifetime.ident, - id: lifetime.id, - attrs, - bounds, - kind: ast::GenericParamKind::Lifetime, - is_placeholder: false, - colon_span, - }) - } else if this.check_keyword(kw::Const) { - // Parse const parameter. - Some(this.parse_const_param(attrs)?) - } else if this.check_ident() { - // Parse type parameter. - Some(this.parse_ty_param(attrs)?) - } else if this.token.can_begin_type() { - // Trying to write an associated type bound? (#26271) - let snapshot = this.create_snapshot_for_diagnostic(); - match this.parse_ty_where_predicate() { - Ok(where_predicate) => { - this.dcx().emit_err(errors::BadAssocTypeBounds { - span: where_predicate.span(), - }); - // FIXME - try to continue parsing other generics? - return Ok((None, false)); - } - Err(err) => { - err.cancel(); - // FIXME - maybe we should overwrite 'self' outside of `collect_tokens`? - this.restore_snapshot(snapshot); - return Ok((None, false)); - } - } + let param = if this.check_lifetime() { + let lifetime = this.expect_lifetime(); + // Parse lifetime parameter. + let (colon_span, bounds) = if this.eat(&token::Colon) { + (Some(this.prev_token.span), this.parse_lt_param_bounds()) } else { - // Check for trailing attributes and stop parsing. - if !attrs.is_empty() { - if !params.is_empty() { - this.dcx() - .emit_err(errors::AttrAfterGeneric { span: attrs[0].span }); - } else { - this.dcx() - .emit_err(errors::AttrWithoutGenerics { span: attrs[0].span }); - } - } - return Ok((None, false)); + (None, Vec::new()) }; - if !this.eat(&token::Comma) { - done = true; + if this.check_noexpect(&token::Eq) && this.look_ahead(1, |t| t.is_lifetime()) { + let lo = this.token.span; + // Parse `= 'lifetime`. + this.bump(); // `=` + this.bump(); // `'lifetime` + let span = lo.to(this.prev_token.span); + this.dcx().emit_err(UnexpectedDefaultValueForLifetimeInGenericParameters { + span, + }); } - // We just ate the comma, so no need to capture the trailing token. - Ok((param, false)) - })?; + + Some(ast::GenericParam { + ident: lifetime.ident, + id: lifetime.id, + attrs, + bounds, + kind: ast::GenericParamKind::Lifetime, + is_placeholder: false, + colon_span, + }) + } else if this.check_keyword(kw::Const) { + // Parse const parameter. + Some(this.parse_const_param(attrs)?) + } else if this.check_ident() { + // Parse type parameter. + Some(this.parse_ty_param(attrs)?) + } else if this.token.can_begin_type() { + // Trying to write an associated type bound? (#26271) + let snapshot = this.create_snapshot_for_diagnostic(); + match this.parse_ty_where_predicate() { + Ok(where_predicate) => { + this.dcx().emit_err(errors::BadAssocTypeBounds { + span: where_predicate.span(), + }); + // FIXME - try to continue parsing other generics? + } + Err(err) => { + err.cancel(); + // FIXME - maybe we should overwrite 'self' outside of `collect_tokens`? + this.restore_snapshot(snapshot); + } + } + return Ok((None, Trailing::No, UsePreAttrPos::No)); + } else { + // Check for trailing attributes and stop parsing. + if !attrs.is_empty() { + if !params.is_empty() { + this.dcx().emit_err(errors::AttrAfterGeneric { span: attrs[0].span }); + } else { + this.dcx() + .emit_err(errors::AttrWithoutGenerics { span: attrs[0].span }); + } + } + return Ok((None, Trailing::No, UsePreAttrPos::No)); + }; + + if !this.eat(&token::Comma) { + done = true; + } + // We just ate the comma, so no need to capture the trailing token. + Ok((param, Trailing::No, UsePreAttrPos::No)) + })?; if let Some(param) = param { params.push(param); @@ -393,7 +387,7 @@ impl<'a> Parser<'a> { if let Some(struct_) = struct_ && self.may_recover() - && self.token.kind == token::OpenDelim(Delimiter::Parenthesis) + && self.token == token::OpenDelim(Delimiter::Parenthesis) { snapshot = Some((struct_, self.create_snapshot_for_diagnostic())); }; diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 8775d792c3d..c6a5e1908f7 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -20,7 +20,9 @@ use tracing::debug; use super::diagnostics::{dummy_arg, ConsumeClosingDelim}; use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; -use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, Trailing}; +use super::{ + AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, Trailing, UsePreAttrPos, +}; use crate::errors::{self, MacroExpandsToAdtField}; use crate::{fluent_generated as fluent, maybe_whole}; @@ -49,7 +51,9 @@ impl<'a> Parser<'a> { } /// Parses the contents of a module (inner attributes followed by module items). - /// We exit once we hit `term` + /// We exit once we hit `term` which can be either + /// - EOF (for files) + /// - `}` for mod items pub fn parse_mod( &mut self, term: &TokenKind, @@ -127,7 +131,7 @@ impl<'a> Parser<'a> { Some(item.into_inner()) }); - self.collect_tokens_trailing_token(attrs, force_collect, |this, mut attrs| { + self.collect_tokens(None, attrs, force_collect, |this, mut attrs| { let lo = this.token.span; let vis = this.parse_visibility(FollowedByType::No)?; let mut def = this.parse_defaultness(); @@ -145,7 +149,7 @@ impl<'a> Parser<'a> { let span = lo.to(this.prev_token.span); let id = DUMMY_NODE_ID; let item = Item { ident, attrs, id, kind, vis, span, tokens: None }; - return Ok((Some(item), false)); + return Ok((Some(item), Trailing::No, UsePreAttrPos::No)); } // At this point, we have failed to parse an item. @@ -160,7 +164,7 @@ impl<'a> Parser<'a> { if !attrs_allowed { this.recover_attrs_no_item(&attrs)?; } - Ok((None, false)) + Ok((None, Trailing::No, UsePreAttrPos::No)) }) } @@ -354,7 +358,7 @@ impl<'a> Parser<'a> { fn is_reuse_path_item(&mut self) -> bool { // no: `reuse ::path` for compatibility reasons with macro invocations self.token.is_keyword(kw::Reuse) - && self.look_ahead(1, |t| t.is_path_start() && t.kind != token::PathSep) + && self.look_ahead(1, |t| t.is_path_start() && *t != token::PathSep) } /// Are we sure this could not possibly be a macro invocation? @@ -499,7 +503,7 @@ impl<'a> Parser<'a> { let mut err = self.dcx().struct_span_err(end.span, msg); if end.is_doc_comment() { err.span_label(end.span, "this doc comment doesn't document anything"); - } else if self.token.kind == TokenKind::Semi { + } else if self.token == TokenKind::Semi { err.span_suggestion_verbose( self.token.span, "consider removing this semicolon", @@ -777,12 +781,12 @@ impl<'a> Parser<'a> { && self .span_to_snippet(self.prev_token.span) .is_ok_and(|snippet| snippet == "}") - && self.token.kind == token::Semi; + && self.token == token::Semi; let mut semicolon_span = self.token.span; if !is_unnecessary_semicolon { // #105369, Detect spurious `;` before assoc fn body is_unnecessary_semicolon = self.token == token::OpenDelim(Delimiter::Brace) - && self.prev_token.kind == token::Semi; + && self.prev_token == token::Semi; semicolon_span = self.prev_token.span; } // We have to bail or we'll potentially never make progress. @@ -1194,7 +1198,7 @@ impl<'a> Parser<'a> { // FIXME: This recovery should be tested better. if safety == Safety::Default && self.token.is_keyword(kw::Unsafe) - && self.look_ahead(1, |t| t.kind == token::OpenDelim(Delimiter::Brace)) + && self.look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Brace)) { self.expect(&token::OpenDelim(Delimiter::Brace)).unwrap_err().emit(); safety = Safety::Unsafe(self.token.span); @@ -1246,8 +1250,8 @@ impl<'a> Parser<'a> { let span = self.psess.source_map().guess_head_span(span); let descr = kind.descr(); let help = match kind { - ItemKind::DelegationMac(deleg) if deleg.suffixes.is_none() => None, - _ => Some(()), + ItemKind::DelegationMac(deleg) if deleg.suffixes.is_none() => false, + _ => true, }; self.dcx().emit_err(errors::BadItemKind { span, descr, ctx, help }); None @@ -1258,7 +1262,7 @@ impl<'a> Parser<'a> { && self.is_keyword_ahead(1, &[kw::Extern]) && self.look_ahead( 2 + self.look_ahead(2, |t| t.can_begin_string_literal() as usize), - |t| t.kind == token::OpenDelim(Delimiter::Brace), + |t| *t == token::OpenDelim(Delimiter::Brace), ) } @@ -1343,7 +1347,7 @@ impl<'a> Parser<'a> { ) -> PResult<'a, (Ident, StaticItem)> { let ident = self.parse_ident()?; - if self.token.kind == TokenKind::Lt && self.may_recover() { + if self.token == TokenKind::Lt && self.may_recover() { let generics = self.parse_generics()?; self.dcx().emit_err(errors::StaticWithGenerics { span: generics.span }); } @@ -1546,86 +1550,82 @@ impl<'a> Parser<'a> { self.recover_vcs_conflict_marker(); let help = "enum variants can be `Variant`, `Variant = `, \ `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`"; - self.collect_tokens_trailing_token( - variant_attrs, - ForceCollect::No, - |this, variant_attrs| { - let vlo = this.token.span; + self.collect_tokens(None, variant_attrs, ForceCollect::No, |this, variant_attrs| { + let vlo = this.token.span; - let vis = this.parse_visibility(FollowedByType::No)?; - if !this.recover_nested_adt_item(kw::Enum)? { - return Ok((None, false)); - } - let ident = this.parse_field_ident("enum", vlo)?; + let vis = this.parse_visibility(FollowedByType::No)?; + if !this.recover_nested_adt_item(kw::Enum)? { + return Ok((None, Trailing::No, UsePreAttrPos::No)); + } + let ident = this.parse_field_ident("enum", vlo)?; - if this.token == token::Not { - if let Err(err) = this.unexpected() { - err.with_note(fluent::parse_macro_expands_to_enum_variant).emit(); - } - - this.bump(); - this.parse_delim_args()?; - - return Ok((None, this.token == token::Comma)); + if this.token == token::Not { + if let Err(err) = this.unexpected() { + err.with_note(fluent::parse_macro_expands_to_enum_variant).emit(); } - let struct_def = if this.check(&token::OpenDelim(Delimiter::Brace)) { - // Parse a struct variant. - let (fields, recovered) = - match this.parse_record_struct_body("struct", ident.span, false) { - Ok((fields, recovered)) => (fields, recovered), - Err(mut err) => { - if this.token == token::Colon { - // We handle `enum` to `struct` suggestion in the caller. - return Err(err); - } - this.eat_to_tokens(&[&token::CloseDelim(Delimiter::Brace)]); - this.bump(); // } - err.span_label(span, "while parsing this enum"); - err.help(help); - let guar = err.emit(); - (thin_vec![], Recovered::Yes(guar)) - } - }; - VariantData::Struct { fields, recovered: recovered.into() } - } else if this.check(&token::OpenDelim(Delimiter::Parenthesis)) { - let body = match this.parse_tuple_struct_body() { - Ok(body) => body, + this.bump(); + this.parse_delim_args()?; + + return Ok((None, Trailing::from(this.token == token::Comma), UsePreAttrPos::No)); + } + + let struct_def = if this.check(&token::OpenDelim(Delimiter::Brace)) { + // Parse a struct variant. + let (fields, recovered) = + match this.parse_record_struct_body("struct", ident.span, false) { + Ok((fields, recovered)) => (fields, recovered), Err(mut err) => { if this.token == token::Colon { // We handle `enum` to `struct` suggestion in the caller. return Err(err); } - this.eat_to_tokens(&[&token::CloseDelim(Delimiter::Parenthesis)]); - this.bump(); // ) + this.eat_to_tokens(&[&token::CloseDelim(Delimiter::Brace)]); + this.bump(); // } err.span_label(span, "while parsing this enum"); err.help(help); - err.emit(); - thin_vec![] + let guar = err.emit(); + (thin_vec![], Recovered::Yes(guar)) } }; - VariantData::Tuple(body, DUMMY_NODE_ID) - } else { - VariantData::Unit(DUMMY_NODE_ID) + VariantData::Struct { fields, recovered: recovered.into() } + } else if this.check(&token::OpenDelim(Delimiter::Parenthesis)) { + let body = match this.parse_tuple_struct_body() { + Ok(body) => body, + Err(mut err) => { + if this.token == token::Colon { + // We handle `enum` to `struct` suggestion in the caller. + return Err(err); + } + this.eat_to_tokens(&[&token::CloseDelim(Delimiter::Parenthesis)]); + this.bump(); // ) + err.span_label(span, "while parsing this enum"); + err.help(help); + err.emit(); + thin_vec![] + } }; + VariantData::Tuple(body, DUMMY_NODE_ID) + } else { + VariantData::Unit(DUMMY_NODE_ID) + }; - let disr_expr = - if this.eat(&token::Eq) { Some(this.parse_expr_anon_const()?) } else { None }; + let disr_expr = + if this.eat(&token::Eq) { Some(this.parse_expr_anon_const()?) } else { None }; - let vr = ast::Variant { - ident, - vis, - id: DUMMY_NODE_ID, - attrs: variant_attrs, - data: struct_def, - disr_expr, - span: vlo.to(this.prev_token.span), - is_placeholder: false, - }; + let vr = ast::Variant { + ident, + vis, + id: DUMMY_NODE_ID, + attrs: variant_attrs, + data: struct_def, + disr_expr, + span: vlo.to(this.prev_token.span), + is_placeholder: false, + }; - Ok((Some(vr), this.token == token::Comma)) - }, - ) + Ok((Some(vr), Trailing::from(this.token == token::Comma), UsePreAttrPos::No)) + }) .map_err(|mut err| { err.help(help); err @@ -1777,7 +1777,7 @@ impl<'a> Parser<'a> { // Unit like structs are handled in parse_item_struct function self.parse_paren_comma_seq(|p| { let attrs = p.parse_outer_attributes()?; - p.collect_tokens_trailing_token(attrs, ForceCollect::No, |p, attrs| { + p.collect_tokens(None, attrs, ForceCollect::No, |p, attrs| { let mut snapshot = None; if p.is_vcs_conflict_marker(&TokenKind::BinOp(token::Shl), &TokenKind::Lt) { // Account for `<<<<<<<` diff markers. We can't proactively error here because @@ -1815,7 +1815,8 @@ impl<'a> Parser<'a> { attrs, is_placeholder: false, }, - p.token == token::Comma, + Trailing::from(p.token == token::Comma), + UsePreAttrPos::No, )) }) }) @@ -1827,10 +1828,11 @@ impl<'a> Parser<'a> { self.recover_vcs_conflict_marker(); let attrs = self.parse_outer_attributes()?; self.recover_vcs_conflict_marker(); - self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { + self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| { let lo = this.token.span; let vis = this.parse_visibility(FollowedByType::No)?; - this.parse_single_struct_field(adt_ty, lo, vis, attrs).map(|field| (field, false)) + this.parse_single_struct_field(adt_ty, lo, vis, attrs) + .map(|field| (field, Trailing::No, UsePreAttrPos::No)) }) } @@ -1914,7 +1916,7 @@ impl<'a> Parser<'a> { let mut err = self.dcx().struct_span_err(sp, msg); if self.token.is_ident() - || (self.token.kind == TokenKind::Pound + || (self.token == TokenKind::Pound && (self.look_ahead(1, |t| t == &token::OpenDelim(Delimiter::Bracket)))) { // This is likely another field, TokenKind::Pound is used for `#[..]` @@ -1937,8 +1939,8 @@ impl<'a> Parser<'a> { fn expect_field_ty_separator(&mut self) -> PResult<'a, ()> { if let Err(err) = self.expect(&token::Colon) { let sm = self.psess.source_map(); - let eq_typo = self.token.kind == token::Eq && self.look_ahead(1, |t| t.is_path_start()); - let semi_typo = self.token.kind == token::Semi + let eq_typo = self.token == token::Eq && self.look_ahead(1, |t| t.is_path_start()); + let semi_typo = self.token == token::Semi && self.look_ahead(1, |t| { t.is_path_start() // We check that we are in a situation like `foo; bar` to avoid bad suggestions @@ -1974,7 +1976,7 @@ impl<'a> Parser<'a> { attrs: AttrVec, ) -> PResult<'a, FieldDef> { let name = self.parse_field_ident(adt_ty, lo)?; - if self.token.kind == token::Not { + if self.token == token::Not { if let Err(mut err) = self.unexpected() { // Encounter the macro invocation err.subdiagnostic(MacroExpandsToAdtField { adt_ty }); @@ -1983,10 +1985,10 @@ impl<'a> Parser<'a> { } self.expect_field_ty_separator()?; let ty = self.parse_ty_for_field_def()?; - if self.token.kind == token::Colon && self.look_ahead(1, |tok| tok.kind != token::Colon) { + if self.token == token::Colon && self.look_ahead(1, |t| *t != token::Colon) { self.dcx().emit_err(errors::SingleColonStructType { span: self.token.span }); } - if self.token.kind == token::Eq { + if self.token == token::Eq { self.bump(); let const_expr = self.parse_expr_anon_const()?; let sp = ty.span.shrink_to_hi().to(const_expr.value.span); @@ -2064,7 +2066,7 @@ impl<'a> Parser<'a> { .parse_ident_common(false) // Cancel this error, we don't need it. .map_err(|err| err.cancel()) - && self.token.kind == TokenKind::Colon + && self.token == TokenKind::Colon { err.span_suggestion( removal_span, @@ -2367,12 +2369,12 @@ impl<'a> Parser<'a> { match self.expected_one_of_not_found(&[], expected) { Ok(error_guaranteed) => Ok(error_guaranteed), Err(mut err) => { - if self.token.kind == token::CloseDelim(Delimiter::Brace) { + if self.token == token::CloseDelim(Delimiter::Brace) { // The enclosing `mod`, `trait` or `impl` is being closed, so keep the `fn` in // the AST for typechecking. err.span_label(ident_span, "while parsing this `fn`"); Ok(err.emit()) - } else if self.token.kind == token::RArrow + } else if self.token == token::RArrow && let Some(fn_params_end) = fn_params_end { // Instead of a function body, the parser has encountered a right arrow @@ -2445,7 +2447,7 @@ impl<'a> Parser<'a> { fn_params_end: Option, ) -> PResult<'a, Option>> { let has_semi = if req_body { - self.token.kind == TokenKind::Semi + self.token == TokenKind::Semi } else { // Only include `;` in list of expected tokens if body is not required self.check(&TokenKind::Semi) @@ -2458,7 +2460,7 @@ impl<'a> Parser<'a> { } else if self.check(&token::OpenDelim(Delimiter::Brace)) || self.token.is_whole_block() { self.parse_block_common(self.token.span, BlockCheckMode::Default, false) .map(|(attrs, body)| (attrs, Some(body)))? - } else if self.token.kind == token::Eq { + } else if self.token == token::Eq { // Recover `fn foo() = $expr;`. self.bump(); // `=` let eq_sp = self.prev_token.span; @@ -2761,7 +2763,7 @@ impl<'a> Parser<'a> { pub(super) fn parse_fn_params(&mut self, req_name: ReqName) -> PResult<'a, ThinVec> { let mut first_param = true; // Parse the arguments, starting out with `self` being allowed... - if self.token.kind != TokenKind::OpenDelim(Delimiter::Parenthesis) + if self.token != TokenKind::OpenDelim(Delimiter::Parenthesis) // might be typo'd trait impl, handled elsewhere && !self.token.is_keyword(kw::For) { @@ -2805,12 +2807,12 @@ impl<'a> Parser<'a> { fn parse_param_general(&mut self, req_name: ReqName, first_param: bool) -> PResult<'a, Param> { let lo = self.token.span; let attrs = self.parse_outer_attributes()?; - self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { + self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| { // Possibly parse `self`. Recover if we parsed it and it wasn't allowed here. if let Some(mut param) = this.parse_self_param()? { param.attrs = attrs; let res = if first_param { Ok(param) } else { this.recover_bad_self_param(param) }; - return Ok((res?, false)); + return Ok((res?, Trailing::No, UsePreAttrPos::No)); } let is_name_required = match this.token.kind { @@ -2826,7 +2828,7 @@ impl<'a> Parser<'a> { this.parameter_without_type(&mut err, pat, is_name_required, first_param) { let guar = err.emit(); - Ok((dummy_arg(ident, guar), false)) + Ok((dummy_arg(ident, guar), Trailing::No, UsePreAttrPos::No)) } else { Err(err) }; @@ -2869,7 +2871,8 @@ impl<'a> Parser<'a> { Ok(( Param { attrs, id: ast::DUMMY_NODE_ID, is_placeholder: false, pat, span, ty }, - false, + Trailing::No, + UsePreAttrPos::No, )) }) } diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 9b3b6d5f9ad..61e3fa2e6c5 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -14,7 +14,7 @@ use std::assert_matches::debug_assert_matches; use std::ops::Range; use std::{fmt, mem, slice}; -use attr_wrapper::AttrWrapper; +use attr_wrapper::{AttrWrapper, UsePreAttrPos}; pub use diagnostics::AttemptLocalParseRecovery; pub(crate) use expr::ForbiddenLetReason; pub(crate) use item::FnParseMode; @@ -238,6 +238,7 @@ impl NodeRange { // is the position of the function's start token. This gives // `NodeRange(10..15)`. fn new(ParserRange(parser_range): ParserRange, start_pos: u32) -> NodeRange { + assert!(parser_range.start >= start_pos && parser_range.end >= start_pos); NodeRange((parser_range.start - start_pos)..(parser_range.end - start_pos)) } } @@ -253,7 +254,7 @@ enum Capturing { Yes, } -// This state is used by `Parser::collect_tokens_trailing_token`. +// This state is used by `Parser::collect_tokens`. #[derive(Clone, Debug)] struct CaptureState { capturing: Capturing, @@ -388,6 +389,12 @@ enum Trailing { Yes, } +impl From for Trailing { + fn from(b: bool) -> Trailing { + if b { Trailing::Yes } else { Trailing::No } + } +} + #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub(super) enum TokenDescription { ReservedIdentifier, @@ -459,8 +466,8 @@ impl<'a> Parser<'a> { parser.bump(); // Change this from 1 back to 0 after the bump. This eases debugging of - // `Parser::collect_tokens_trailing_token` nicer because it makes the - // token positions 0-indexed which is nicer than 1-indexed. + // `Parser::collect_tokens` because 0-indexed token positions are nicer + // than 1-indexed token positions. parser.num_bump_calls = 0; parser @@ -527,7 +534,7 @@ impl<'a> Parser<'a> { } else if inedible.contains(&self.token.kind) { // leave it in the input Ok(Recovered::No) - } else if self.token.kind != token::Eof + } else if self.token != token::Eof && self.last_unexpected_token_span == Some(self.token.span) { FatalError.raise(); @@ -756,7 +763,7 @@ impl<'a> Parser<'a> { /// compound tokens like multi-character operators in process. /// Returns `true` if the token was eaten. fn break_and_eat(&mut self, expected: TokenKind) -> bool { - if self.token.kind == expected { + if self.token == expected { self.bump(); return true; } @@ -882,7 +889,7 @@ impl<'a> Parser<'a> { let token_str = pprust::token_kind_to_string(t); match self.current_closure.take() { - Some(closure_spans) if self.token.kind == TokenKind::Semi => { + Some(closure_spans) if self.token == TokenKind::Semi => { // Finding a semicolon instead of a comma // after a closure body indicates that the // closure body may be a block but the user @@ -910,7 +917,7 @@ impl<'a> Parser<'a> { // If this was a missing `@` in a binding pattern // bail with a suggestion // https://github.com/rust-lang/rust/issues/72373 - if self.prev_token.is_ident() && self.token.kind == token::DotDot { + if self.prev_token.is_ident() && self.token == token::DotDot { let msg = format!( "if you meant to bind the contents of the rest of the array \ pattern into `{}`, use `@`", @@ -1546,11 +1553,9 @@ impl<'a> Parser<'a> { ) -> PResult<'a, R> { // The only reason to call `collect_tokens_no_attrs` is if you want tokens, so use // `ForceCollect::Yes` - self.collect_tokens_trailing_token( - AttrWrapper::empty(), - ForceCollect::Yes, - |this, _attrs| Ok((f(this)?, false)), - ) + self.collect_tokens(None, AttrWrapper::empty(), ForceCollect::Yes, |this, _attrs| { + Ok((f(this)?, Trailing::No, UsePreAttrPos::No)) + }) } /// `::{` or `::*` diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 5bfb8bdf776..cc68ae237ba 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -13,7 +13,7 @@ use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{BytePos, ErrorGuaranteed, Span}; use thin_vec::{thin_vec, ThinVec}; -use super::{ForceCollect, Parser, PathStyle, Restrictions, Trailing}; +use super::{ForceCollect, Parser, PathStyle, Restrictions, Trailing, UsePreAttrPos}; use crate::errors::{ self, AmbiguousRangePattern, DotDotDotForRemainingFields, DotDotDotRangeToPatternNotAllowed, DotDotDotRestPattern, EnumPatternInsteadOfIdentifier, ExpectedBindingLeftOfAt, @@ -333,7 +333,7 @@ impl<'a> Parser<'a> { span: self.token.span, start: lo, token: self.token.clone(), - note_double_vert: matches!(self.token.kind, token::OrOr).then_some(()), + note_double_vert: matches!(self.token.kind, token::OrOr), }); self.bump(); true @@ -369,7 +369,7 @@ impl<'a> Parser<'a> { .and_then(|(ident, _)| ident.name.as_str().chars().next()) .is_some_and(char::is_lowercase) }) - && self.look_ahead(2, |tok| tok.kind == token::OpenDelim(Delimiter::Parenthesis)); + && self.look_ahead(2, |t| *t == token::OpenDelim(Delimiter::Parenthesis)); // Check for operators. // `|` is excluded as it is used in pattern alternatives and lambdas, @@ -377,9 +377,9 @@ impl<'a> Parser<'a> { // `[` is included for indexing operations, // `[]` is excluded as `a[]` isn't an expression and should be recovered as `a, []` (cf. `tests/ui/parser/pat-lt-bracket-7.rs`) let has_trailing_operator = matches!(self.token.kind, token::BinOp(op) if op != BinOpToken::Or) - || self.token.kind == token::Question - || (self.token.kind == token::OpenDelim(Delimiter::Bracket) - && self.look_ahead(1, |tok| tok.kind != token::CloseDelim(Delimiter::Bracket))); + || self.token == token::Question + || (self.token == token::OpenDelim(Delimiter::Bracket) + && self.look_ahead(1, |t| *t != token::CloseDelim(Delimiter::Bracket))); if !has_trailing_method && !has_trailing_operator { // Nothing to recover here. @@ -403,7 +403,7 @@ impl<'a> Parser<'a> { // Parse an associative expression such as `+ expr`, `% expr`, ... // Assignements, ranges and `|` are disabled by [`Restrictions::IS_PAT`]. - if let Ok(expr) = + if let Ok((expr, _)) = snapshot.parse_expr_assoc_rest_with(0, false, expr).map_err(|err| err.cancel()) { // We got a valid expression. @@ -413,7 +413,7 @@ impl<'a> Parser<'a> { let is_bound = is_end_bound // is_start_bound: either `..` or `)..` || self.token.is_range_separator() - || self.token.kind == token::CloseDelim(Delimiter::Parenthesis) + || self.token == token::CloseDelim(Delimiter::Parenthesis) && self.look_ahead(1, Token::is_range_separator); // Check that `parse_expr_assoc_with` didn't eat a rhs. @@ -450,7 +450,7 @@ impl<'a> Parser<'a> { lo = self.token.span; } - let pat = if self.check(&token::BinOp(token::And)) || self.token.kind == token::AndAnd { + let pat = if self.check(&token::BinOp(token::And)) || self.token == token::AndAnd { self.parse_pat_deref(expected)? } else if self.check(&token::OpenDelim(Delimiter::Parenthesis)) { self.parse_pat_tuple_or_parens()? @@ -625,7 +625,7 @@ impl<'a> Parser<'a> { /// /// [and]: https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/pattern-matching fn recover_intersection_pat(&mut self, lhs: P) -> PResult<'a, P> { - if self.token.kind != token::At { + if self.token != token::At { // Next token is not `@` so it's not going to be an intersection pattern. return Ok(lhs); } @@ -958,14 +958,14 @@ impl<'a> Parser<'a> { self.check_inline_const(dist) || self.look_ahead(dist, |t| { t.is_path_start() // e.g. `MY_CONST`; - || t.kind == token::Dot // e.g. `.5` for recovery; + || *t == token::Dot // e.g. `.5` for recovery; || matches!(t.kind, token::Literal(..) | token::BinOp(token::Minus)) || t.is_bool_lit() || t.is_whole_expr() || t.is_lifetime() // recover `'a` instead of `'a'` || (self.may_recover() // recover leading `(` - && t.kind == token::OpenDelim(Delimiter::Parenthesis) - && self.look_ahead(dist + 1, |t| t.kind != token::OpenDelim(Delimiter::Parenthesis)) + && *t == token::OpenDelim(Delimiter::Parenthesis) + && self.look_ahead(dist + 1, |t| *t != token::OpenDelim(Delimiter::Parenthesis)) && self.is_pat_range_end_start(dist + 1)) }) } @@ -1302,24 +1302,23 @@ impl<'a> Parser<'a> { } } - let field = - self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { - let field = match this.parse_pat_field(lo, attrs) { - Ok(field) => Ok(field), - Err(err) => { - if let Some(delayed_err) = delayed_err.take() { - delayed_err.emit(); - } - return Err(err); + let field = self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| { + let field = match this.parse_pat_field(lo, attrs) { + Ok(field) => Ok(field), + Err(err) => { + if let Some(delayed_err) = delayed_err.take() { + delayed_err.emit(); } - }?; - ate_comma = this.eat(&token::Comma); + return Err(err); + } + }?; + ate_comma = this.eat(&token::Comma); - last_non_comma_dotdot_span = Some(this.prev_token.span); + last_non_comma_dotdot_span = Some(this.prev_token.span); - // We just ate a comma, so there's no need to capture a trailing token. - Ok((field, false)) - })?; + // We just ate a comma, so there's no need to capture a trailing token. + Ok((field, Trailing::No, UsePreAttrPos::No)) + })?; fields.push(field) } diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 6f82d6b9826..d8bf10e6021 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -261,11 +261,7 @@ impl<'a> Parser<'a> { self.dcx().emit_err(PathSingleColon { span: self.prev_token.span, suggestion: self.prev_token.span.shrink_to_hi(), - type_ascription: self - .psess - .unstable_features - .is_nightly_build() - .then_some(()), + type_ascription: self.psess.unstable_features.is_nightly_build(), }); } continue; @@ -334,11 +330,7 @@ impl<'a> Parser<'a> { err = self.dcx().create_err(PathSingleColon { span: self.token.span, suggestion: self.prev_token.span.shrink_to_hi(), - type_ascription: self - .psess - .unstable_features - .is_nightly_build() - .then_some(()), + type_ascription: self.psess.unstable_features.is_nightly_build(), }); } // Attempt to find places where a missing `>` might belong. @@ -358,9 +350,9 @@ impl<'a> Parser<'a> { })?; let span = lo.to(self.prev_token.span); AngleBracketedArgs { args, span }.into() - } else if self.token.kind == token::OpenDelim(Delimiter::Parenthesis) + } else if self.token == token::OpenDelim(Delimiter::Parenthesis) // FIXME(return_type_notation): Could also recover `...` here. - && self.look_ahead(1, |tok| tok.kind == token::DotDot) + && self.look_ahead(1, |t| *t == token::DotDot) { self.bump(); // ( self.bump(); // .. @@ -384,7 +376,7 @@ impl<'a> Parser<'a> { let token_before_parsing = self.token.clone(); let mut snapshot = None; if self.may_recover() - && prev_token_before_parsing.kind == token::PathSep + && prev_token_before_parsing == token::PathSep && (style == PathStyle::Expr && self.token.can_begin_expr() || style == PathStyle::Pat && self.token.can_begin_pattern()) { @@ -393,7 +385,7 @@ impl<'a> Parser<'a> { let (inputs, _) = match self.parse_paren_comma_seq(|p| p.parse_ty()) { Ok(output) => output, - Err(mut error) if prev_token_before_parsing.kind == token::PathSep => { + Err(mut error) if prev_token_before_parsing == token::PathSep => { error.span_label( prev_token_before_parsing.span.to(token_before_parsing.span), "while parsing this parenthesized list of type arguments starting here", @@ -913,7 +905,7 @@ impl<'a> Parser<'a> { let snapshot = self.create_snapshot_for_diagnostic(); let attrs = self.parse_outer_attributes()?; match self.parse_expr_res(Restrictions::CONST_EXPR, attrs) { - Ok(expr) => { + Ok((expr, _)) => { return Ok(Some(self.dummy_const_arg_needs_braces( self.dcx().struct_span_err(expr.span, "invalid const generic expression"), expr.span, diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index b206f134f0e..26ad39e06cd 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -21,6 +21,7 @@ use super::pat::{PatternLocation, RecoverComma}; use super::path::PathStyle; use super::{ AttrWrapper, BlockMode, FnParseMode, ForceCollect, Parser, Restrictions, SemiColonMode, + Trailing, UsePreAttrPos, }; use crate::errors::MalformedLoopLabel; use crate::{errors, maybe_whole}; @@ -45,6 +46,7 @@ impl<'a> Parser<'a> { capture_semi: bool, force_collect: ForceCollect, ) -> PResult<'a, Option> { + let pre_attr_pos = self.collect_pos(); let attrs = self.parse_outer_attributes()?; let lo = self.token.span; @@ -65,11 +67,15 @@ impl<'a> Parser<'a> { } Ok(Some(if self.token.is_keyword(kw::Let) { - self.collect_tokens_trailing_token(attrs, force_collect, |this, attrs| { + self.collect_tokens(None, attrs, force_collect, |this, attrs| { this.expect_keyword(kw::Let)?; let local = this.parse_local(attrs)?; - let trailing = capture_semi && this.token.kind == token::Semi; - Ok((this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)), trailing)) + let trailing = Trailing::from(capture_semi && this.token == token::Semi); + Ok(( + this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)), + trailing, + UsePreAttrPos::No, + )) })? } else if self.is_kw_followed_by_ident(kw::Mut) && self.may_recover() { self.recover_stmt_local_after_let( @@ -103,10 +109,18 @@ impl<'a> Parser<'a> { // or `auto trait` items. We aim to parse an arbitrary path `a::b` but not something // that starts like a path (1 token), but it fact not a path. // Also, we avoid stealing syntax from `parse_item_`. - let stmt = self.collect_tokens_trailing_token( + // + // `UsePreAttrPos::Yes` here means the attribute belongs unconditionally to the + // expression, not the statement. (But the statement attributes/tokens are obtained + // from the expression anyway, because `Stmt` delegates `HasAttrs`/`HasTokens` to + // the things within `StmtKind`.) + let stmt = self.collect_tokens( + Some(pre_attr_pos), AttrWrapper::empty(), force_collect, - |this, _empty_attrs| Ok((this.parse_stmt_path_start(lo, attrs)?, false)), + |this, _empty_attrs| { + Ok((this.parse_stmt_path_start(lo, attrs)?, Trailing::No, UsePreAttrPos::Yes)) + }, ); match stmt { Ok(stmt) => stmt, @@ -128,12 +142,15 @@ impl<'a> Parser<'a> { self.error_outer_attrs(attrs); self.mk_stmt(lo, StmtKind::Empty) } else if self.token != token::CloseDelim(Delimiter::Brace) { - // Remainder are line-expr stmts. - let e = self.collect_tokens_trailing_token( + // Remainder are line-expr stmts. This is similar to the `parse_stmt_path_start` case + // above. + let e = self.collect_tokens( + Some(pre_attr_pos), AttrWrapper::empty(), force_collect, |this, _empty_attrs| { - Ok((this.parse_expr_res(Restrictions::STMT_EXPR, attrs)?, false)) + let (expr, _) = this.parse_expr_res(Restrictions::STMT_EXPR, attrs)?; + Ok((expr, Trailing::No, UsePreAttrPos::Yes)) }, )?; if matches!(e.kind, ExprKind::Assign(..)) && self.eat_keyword(kw::Else) { @@ -150,12 +167,16 @@ impl<'a> Parser<'a> { } fn parse_stmt_path_start(&mut self, lo: Span, attrs: AttrWrapper) -> PResult<'a, Stmt> { - let stmt = self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { + let stmt = self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| { let path = this.parse_path(PathStyle::Expr)?; if this.eat(&token::Not) { let stmt_mac = this.parse_stmt_mac(lo, attrs, path)?; - return Ok((stmt_mac, this.token == token::Semi)); + return Ok(( + stmt_mac, + Trailing::from(this.token == token::Semi), + UsePreAttrPos::No, + )); } let expr = if this.eat(&token::OpenDelim(Delimiter::Brace)) { @@ -169,13 +190,17 @@ impl<'a> Parser<'a> { this.parse_expr_dot_or_call_with(attrs, expr, lo) })?; // `DUMMY_SP` will get overwritten later in this function - Ok((this.mk_stmt(rustc_span::DUMMY_SP, StmtKind::Expr(expr)), false)) + Ok(( + this.mk_stmt(rustc_span::DUMMY_SP, StmtKind::Expr(expr)), + Trailing::No, + UsePreAttrPos::No, + )) })?; if let StmtKind::Expr(expr) = stmt.kind { - // Perform this outside of the `collect_tokens_trailing_token` closure, - // since our outer attributes do not apply to this part of the expression - let expr = self.with_res(Restrictions::STMT_EXPR, |this| { + // Perform this outside of the `collect_tokens` closure, since our + // outer attributes do not apply to this part of the expression. + let (expr, _) = self.with_res(Restrictions::STMT_EXPR, |this| { this.parse_expr_assoc_rest_with(0, true, expr) })?; Ok(self.mk_stmt(lo.to(self.prev_token.span), StmtKind::Expr(expr))) @@ -209,7 +234,7 @@ impl<'a> Parser<'a> { let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac)); let e = self.maybe_recover_from_bad_qpath(e)?; let e = self.parse_expr_dot_or_call_with(attrs, e, lo)?; - let e = self.parse_expr_assoc_rest_with(0, false, e)?; + let (e, _) = self.parse_expr_assoc_rest_with(0, false, e)?; StmtKind::Expr(e) }; Ok(self.mk_stmt(lo.to(hi), kind)) @@ -239,10 +264,14 @@ impl<'a> Parser<'a> { subdiagnostic: fn(Span) -> errors::InvalidVariableDeclarationSub, force_collect: ForceCollect, ) -> PResult<'a, Stmt> { - let stmt = self.collect_tokens_trailing_token(attrs, force_collect, |this, attrs| { + let stmt = self.collect_tokens(None, attrs, force_collect, |this, attrs| { let local = this.parse_local(attrs)?; // FIXME - maybe capture semicolon in recovery? - Ok((this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)), false)) + Ok(( + this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)), + Trailing::No, + UsePreAttrPos::No, + )) })?; self.dcx() .emit_err(errors::InvalidVariableDeclaration { span: lo, sub: subdiagnostic(lo) }); @@ -430,11 +459,16 @@ impl<'a> Parser<'a> { pub fn parse_block(&mut self) -> PResult<'a, P> { let (attrs, block) = self.parse_inner_attrs_and_block()?; if let [.., last] = &*attrs { + let suggest_to_outer = match &last.kind { + ast::AttrKind::Normal(attr) => attr.item.is_valid_for_outer_style(), + _ => false, + }; self.error_on_forbidden_inner_attr( last.span, super::attr::InnerAttrPolicy::Forbidden(Some( InnerAttrForbiddenReason::InCodeBlock, )), + suggest_to_outer, ); } Ok(block) @@ -760,7 +794,7 @@ impl<'a> Parser<'a> { ) ), ); - let suggest_eq = if self.token.kind == token::Dot + let suggest_eq = if self.token == token::Dot && let _ = self.bump() && let mut snapshot = self.create_snapshot_for_diagnostic() && let Ok(_) = snapshot diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 352ddd9eac4..52f0b1c1b04 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -420,7 +420,7 @@ impl<'a> Parser<'a> { let mut trailing_plus = false; let (ts, trailing) = self.parse_paren_comma_seq(|p| { let ty = p.parse_ty()?; - trailing_plus = p.prev_token.kind == TokenKind::BinOp(token::Plus); + trailing_plus = p.prev_token == TokenKind::BinOp(token::Plus); Ok(ty) })?; @@ -499,8 +499,8 @@ impl<'a> Parser<'a> { let elt_ty = match self.parse_ty() { Ok(ty) => ty, Err(err) - if self.look_ahead(1, |t| t.kind == token::CloseDelim(Delimiter::Bracket)) - | self.look_ahead(1, |t| t.kind == token::Semi) => + if self.look_ahead(1, |t| *t == token::CloseDelim(Delimiter::Bracket)) + | self.look_ahead(1, |t| *t == token::Semi) => { // Recover from `[LIT; EXPR]` and `[LIT]` self.bump(); @@ -601,7 +601,7 @@ impl<'a> Parser<'a> { let span_start = self.token.span; let ast::FnHeader { ext, safety, constness, coroutine_kind } = self.parse_fn_front_matter(&inherited_vis, Case::Sensitive)?; - if self.may_recover() && self.token.kind == TokenKind::Lt { + if self.may_recover() && self.token == TokenKind::Lt { self.recover_fn_ptr_with_generics(lo, &mut params, param_insertion_point)?; } let decl = self.parse_fn_decl(|_| false, AllowPlus::No, recover_return_sign)?; @@ -681,7 +681,7 @@ impl<'a> Parser<'a> { // Always parse bounds greedily for better error recovery. let bounds = self.parse_generic_bounds()?; - *impl_dyn_multi = bounds.len() > 1 || self.prev_token.kind == TokenKind::BinOp(token::Plus); + *impl_dyn_multi = bounds.len() > 1 || self.prev_token == TokenKind::BinOp(token::Plus); Ok(TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds)) } @@ -727,8 +727,7 @@ impl<'a> Parser<'a> { self.check_keyword(kw::Dyn) && (self.token.uninterpolated_span().at_least_rust_2018() || self.look_ahead(1, |t| { - (can_begin_dyn_bound_in_edition_2015(t) - || t.kind == TokenKind::BinOp(token::Star)) + (can_begin_dyn_bound_in_edition_2015(t) || *t == TokenKind::BinOp(token::Star)) && !can_continue_type_after_non_fn_ident(t) })) } @@ -750,7 +749,7 @@ impl<'a> Parser<'a> { // Always parse bounds greedily for better error recovery. let bounds = self.parse_generic_bounds()?; - *impl_dyn_multi = bounds.len() > 1 || self.prev_token.kind == TokenKind::BinOp(token::Plus); + *impl_dyn_multi = bounds.len() > 1 || self.prev_token == TokenKind::BinOp(token::Plus); Ok(TyKind::TraitObject(bounds, syntax)) } @@ -852,7 +851,6 @@ impl<'a> Parser<'a> { // lifetimes and ident params (including SelfUpper). These are validated later // for order, duplication, and whether they actually reference params. let use_span = self.prev_token.span; - self.psess.gated_spans.gate(sym::precise_capturing, use_span); let (args, args_span) = self.parse_precise_capturing_args()?; GenericBound::Use(args, use_span.to(args_span)) } else { @@ -1060,7 +1058,7 @@ impl<'a> Parser<'a> { } let mut path = if self.token.is_keyword(kw::Fn) - && self.look_ahead(1, |tok| tok.kind == TokenKind::OpenDelim(Delimiter::Parenthesis)) + && self.look_ahead(1, |t| *t == TokenKind::OpenDelim(Delimiter::Parenthesis)) && let Some(path) = self.recover_path_from_fn() { path diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index a64c00f3b6c..fce41bd90be 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -7,9 +7,7 @@ use rustc_ast::{ NestedMetaItem, Safety, }; use rustc_errors::{Applicability, FatalError, PResult}; -use rustc_feature::{ - AttributeSafety, AttributeTemplate, BuiltinAttribute, Features, BUILTIN_ATTRIBUTE_MAP, -}; +use rustc_feature::{AttributeSafety, AttributeTemplate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; use rustc_session::errors::report_lit_error; use rustc_session::lint::builtin::{ILL_FORMED_ATTRIBUTE_INPUT, UNSAFE_ATTR_OUTSIDE_UNSAFE}; use rustc_session::lint::BuiltinLintDiag; @@ -18,7 +16,7 @@ use rustc_span::{sym, BytePos, Span, Symbol}; use crate::{errors, parse_in}; -pub fn check_attr(features: &Features, psess: &ParseSess, attr: &Attribute) { +pub fn check_attr(psess: &ParseSess, attr: &Attribute) { if attr.is_doc_comment() { return; } @@ -28,7 +26,7 @@ pub fn check_attr(features: &Features, psess: &ParseSess, attr: &Attribute) { // All non-builtin attributes are considered safe let safety = attr_info.map(|x| x.safety).unwrap_or(AttributeSafety::Normal); - check_attribute_safety(features, psess, safety, attr); + check_attribute_safety(psess, safety, attr); // Check input tokens for built-in and key-value attributes. match attr_info { @@ -36,9 +34,9 @@ pub fn check_attr(features: &Features, psess: &ParseSess, attr: &Attribute) { Some(BuiltinAttribute { name, template, .. }) if *name != sym::rustc_dummy => { match parse_meta(psess, attr) { // Don't check safety again, we just did that - Ok(meta) => check_builtin_meta_item( - features, psess, &meta, attr.style, *name, *template, false, - ), + Ok(meta) => { + check_builtin_meta_item(psess, &meta, attr.style, *name, *template, false) + } Err(err) => { err.emit(); } @@ -157,16 +155,7 @@ fn is_attr_template_compatible(template: &AttributeTemplate, meta: &ast::MetaIte } } -pub fn check_attribute_safety( - features: &Features, - psess: &ParseSess, - safety: AttributeSafety, - attr: &Attribute, -) { - if !features.unsafe_attributes { - return; - } - +pub fn check_attribute_safety(psess: &ParseSess, safety: AttributeSafety, attr: &Attribute) { let attr_item = attr.get_normal_item(); if safety == AttributeSafety::Unsafe { @@ -215,21 +204,18 @@ pub fn check_attribute_safety( // Called by `check_builtin_meta_item` and code that manually denies // `unsafe(...)` in `cfg` -pub fn deny_builtin_meta_unsafety(features: &Features, psess: &ParseSess, meta: &MetaItem) { +pub fn deny_builtin_meta_unsafety(psess: &ParseSess, meta: &MetaItem) { // This only supports denying unsafety right now - making builtin attributes // support unsafety will requite us to thread the actual `Attribute` through // for the nice diagnostics. - if features.unsafe_attributes { - if let Safety::Unsafe(unsafe_span) = meta.unsafety { - psess - .dcx() - .emit_err(errors::InvalidAttrUnsafe { span: unsafe_span, name: meta.path.clone() }); - } + if let Safety::Unsafe(unsafe_span) = meta.unsafety { + psess + .dcx() + .emit_err(errors::InvalidAttrUnsafe { span: unsafe_span, name: meta.path.clone() }); } } pub fn check_builtin_meta_item( - features: &Features, psess: &ParseSess, meta: &MetaItem, style: ast::AttrStyle, @@ -246,7 +232,7 @@ pub fn check_builtin_meta_item( } if deny_unsafety { - deny_builtin_meta_unsafety(features, psess, meta); + deny_builtin_meta_unsafety(psess, meta); } } diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 0318d34fb73..38450fc288a 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -430,6 +430,10 @@ passes_link_section = .warn = {-passes_previously_accepted} .label = not a function or static +passes_linkage = + attribute should be applied to a function or static + .label = not a function definition or static + passes_macro_export = `#[macro_export]` only has an effect on macro definitions @@ -440,6 +444,9 @@ passes_macro_export_on_decl_macro = passes_macro_use = `#[{$name}]` only has an effect on `extern crate` and modules +passes_may_dangle = + `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl + passes_maybe_string_interpolation = you might have meant to use string interpolation in this string literal passes_missing_const_err = attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const` @@ -471,12 +478,8 @@ passes_multiple_start_functions = .previous = previous `#[start]` function here passes_must_not_suspend = - `must_not_suspend` attribute should be applied to a struct, enum, or trait - .label = is not a struct, enum, or trait - -passes_must_use_async = - `must_use` attribute on `async` functions applies to the anonymous `Future` returned by the function, not the value within - .label = this attribute does nothing, the `Future`s returned by async functions are already `must_use` + `must_not_suspend` attribute should be applied to a struct, enum, union, or trait + .label = is not a struct, enum, union, or trait passes_must_use_no_effect = `#[must_use]` has no effect when applied to {$article} {$target} @@ -650,6 +653,10 @@ passes_rustc_lint_opt_ty = `#[rustc_lint_opt_ty]` should be applied to a struct .label = not a struct +passes_rustc_pub_transparent = + attribute should be applied to `#[repr(transparent)]` types + .label = not a `#[repr(transparent)]` type + passes_rustc_safe_intrinsic = attribute should be applied to intrinsic functions .label = not an intrinsic function @@ -665,6 +672,10 @@ passes_should_be_applied_to_fn = *[false] not a function definition } +passes_should_be_applied_to_fn_or_unit_struct = + attribute should be applied to a function definition or unit struct + .label = not a function definition or a unit struct + passes_should_be_applied_to_static = attribute should be applied to a static .label = not a static diff --git a/compiler/rustc_passes/src/abi_test.rs b/compiler/rustc_passes/src/abi_test.rs index 839b96fb3de..d0cc123c41a 100644 --- a/compiler/rustc_passes/src/abi_test.rs +++ b/compiler/rustc_passes/src/abi_test.rs @@ -127,14 +127,17 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut for meta_item in meta_items { match meta_item.name_or_empty() { sym::debug => { - let ty::FnPtr(sig) = ty.kind() else { + let ty::FnPtr(sig_tys, hdr) = ty.kind() else { span_bug!( meta_item.span(), "`#[rustc_abi(debug)]` on a type alias requires function pointer type" ); }; let abi = unwrap_fn_abi( - tcx.fn_abi_of_fn_ptr(param_env.and((*sig, /* extra_args */ ty::List::empty()))), + tcx.fn_abi_of_fn_ptr( + param_env + .and((sig_tys.with(*hdr), /* extra_args */ ty::List::empty())), + ), tcx, item_def_id, ); @@ -155,7 +158,7 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut "`#[rustc_abi(assert_eq)]` on a type alias requires pair type" ); }; - let ty::FnPtr(sig1) = field1.kind() else { + let ty::FnPtr(sig_tys1, hdr1) = field1.kind() else { span_bug!( meta_item.span(), "`#[rustc_abi(assert_eq)]` on a type alias requires pair of function pointer types" @@ -163,12 +166,13 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut }; let abi1 = unwrap_fn_abi( tcx.fn_abi_of_fn_ptr( - param_env.and((*sig1, /* extra_args */ ty::List::empty())), + param_env + .and((sig_tys1.with(*hdr1), /* extra_args */ ty::List::empty())), ), tcx, item_def_id, ); - let ty::FnPtr(sig2) = field2.kind() else { + let ty::FnPtr(sig_tys2, hdr2) = field2.kind() else { span_bug!( meta_item.span(), "`#[rustc_abi(assert_eq)]` on a type alias requires pair of function pointer types" @@ -176,7 +180,8 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut }; let abi2 = unwrap_fn_abi( tcx.fn_abi_of_fn_ptr( - param_env.and((*sig2, /* extra_args */ ty::List::empty())), + param_env + .and((sig_tys2.with(*hdr2), /* extra_args */ ty::List::empty())), ), tcx, item_def_id, diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index bd157d1d619..5dbb3854c8f 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -189,6 +189,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { [sym::collapse_debuginfo, ..] => self.check_collapse_debuginfo(attr, span, target), [sym::must_not_suspend, ..] => self.check_must_not_suspend(attr, span, target), [sym::must_use, ..] => self.check_must_use(hir_id, attr, target), + [sym::may_dangle, ..] => self.check_may_dangle(hir_id, attr), [sym::rustc_pass_by_value, ..] => self.check_pass_by_value(attr, span, target), [sym::rustc_allow_incoherent_impl, ..] => { self.check_allow_incoherent_impl(attr, span, target) @@ -243,6 +244,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> { [sym::coroutine, ..] => { self.check_coroutine(attr, target); } + [sym::linkage, ..] => self.check_linkage(attr, span, target), + [sym::rustc_pub_transparent, ..] => self.check_rustc_pub_transparent( attr.span, span, attrs), [ // ok sym::allow @@ -254,9 +257,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::cfg_attr // need to be fixed | sym::cfi_encoding // FIXME(cfi_encoding) - | sym::may_dangle // FIXME(dropck_eyepatch) | sym::pointee // FIXME(derive_smart_pointer) - | sym::linkage // FIXME(linkage) | sym::omit_gdb_pretty_printer_section // FIXME(omit_gdb_pretty_printer_section) | sym::used // handled elsewhere to restrict to static items | sym::repr // handled elsewhere to restrict to type decls items @@ -516,6 +517,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { sym::no_mangle, sym::naked, sym::instruction_set, + sym::repr, // code generation sym::cold, sym::target_feature, @@ -745,12 +747,35 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Target::Field | Target::Arm | Target::MacroDef => { self.inline_attr_str_error_with_macro_def(hir_id, attr, "target_feature"); } + Target::Struct if self.tcx.features().struct_target_features => { + let ty = self.tcx.hir_node(hir_id).expect_item(); + match ty.kind { + ItemKind::Struct(data, _) => { + if data.fields().len() != 0 { + self.dcx().emit_err(errors::AttrShouldBeAppliedToFnOrUnitStruct { + attr_span: attr.span, + defn_span: span, + }); + } + } + _ => { + panic!("Target::Struct for a non-struct"); + } + } + } _ => { - self.dcx().emit_err(errors::AttrShouldBeAppliedToFn { - attr_span: attr.span, - defn_span: span, - on_crate: hir_id == CRATE_HIR_ID, - }); + if self.tcx.features().struct_target_features { + self.dcx().emit_err(errors::AttrShouldBeAppliedToFnOrUnitStruct { + attr_span: attr.span, + defn_span: span, + }); + } else { + self.dcx().emit_err(errors::AttrShouldBeAppliedToFn { + attr_span: attr.span, + defn_span: span, + on_crate: hir_id == CRATE_HIR_ID, + }); + } } } } @@ -951,6 +976,16 @@ impl<'tcx> CheckAttrVisitor<'tcx> { bare_fn_ty.decl.inputs.len() == 1 } else { false + } + || if let Some(&[hir::GenericArg::Type(ty)]) = i + .of_trait + .as_ref() + .and_then(|trait_ref| trait_ref.path.segments.last()) + .map(|last_segment| last_segment.args().args) + { + matches!(&ty.kind, hir::TyKind::Tup([_])) + } else { + false }; if !is_valid { self.dcx().emit_err(errors::DocFakeVariadicNotValid { span: meta.span() }); @@ -1363,7 +1398,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - /// Checks if `#[must_not_suspend]` is applied to a function. + /// Checks if `#[must_not_suspend]` is applied to a struct, enum, union, or trait. fn check_must_not_suspend(&self, attr: &Attribute, span: Span, target: Target) { match target { Target::Struct | Target::Enum | Target::Union | Target::Trait => {} @@ -1373,6 +1408,27 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } + /// Checks if `#[may_dangle]` is applied to a lifetime or type generic parameter in `Drop` impl. + fn check_may_dangle(&self, hir_id: HirId, attr: &Attribute) { + if let hir::Node::GenericParam(param) = self.tcx.hir_node(hir_id) + && matches!( + param.kind, + hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. } + ) + && matches!(param.source, hir::GenericParamSource::Generics) + && let parent_hir_id = self.tcx.parent_hir_id(hir_id) + && let hir::Node::Item(item) = self.tcx.hir_node(parent_hir_id) + && let hir::ItemKind::Impl(impl_) = item.kind + && let Some(trait_) = impl_.of_trait + && let Some(def_id) = trait_.trait_def_id() + && self.tcx.is_lang_item(def_id, hir::LangItem::Drop) + { + return; + } + + self.dcx().emit_err(errors::InvalidMayDangle { attr_span: attr.span }); + } + /// Checks if `#[cold]` is applied to a non-function. fn check_cold(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) { match target { @@ -2347,6 +2403,31 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } } + + fn check_linkage(&self, attr: &Attribute, span: Span, target: Target) { + match target { + Target::Fn + | Target::Method(..) + | Target::Static + | Target::ForeignStatic + | Target::ForeignFn => {} + _ => { + self.dcx().emit_err(errors::Linkage { attr_span: attr.span, span }); + } + } + } + + fn check_rustc_pub_transparent(&self, attr_span: Span, span: Span, attrs: &[Attribute]) { + if !attrs + .iter() + .filter(|attr| attr.has_name(sym::repr)) + .filter_map(|attr| attr.meta_item_list()) + .flatten() + .any(|nmi| nmi.has_name(sym::transparent)) + { + self.dcx().emit_err(errors::RustcPubTransparent { span, attr_span }); + } + } } impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> { @@ -2585,8 +2666,7 @@ fn check_duplicates( warning: matches!( duplicates, FutureWarnFollowing | FutureWarnPreceding - ) - .then_some(()), + ), }, ); } diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs index 659281c5e71..624ebb2f9f2 100644 --- a/compiler/rustc_passes/src/diagnostic_items.rs +++ b/compiler/rustc_passes/src/diagnostic_items.rs @@ -49,7 +49,7 @@ fn report_duplicate_item( orig_span, crate_name: tcx.crate_name(item_def_id.krate), orig_crate_name: tcx.crate_name(original_def_id.krate), - different_crates: (item_def_id.krate != original_def_id.krate).then_some(()), + different_crates: (item_def_id.krate != original_def_id.krate), name, }); } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 36dfc40e762..32db0823cf7 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -82,6 +82,15 @@ pub struct AttrShouldBeAppliedToFn { pub on_crate: bool, } +#[derive(Diagnostic)] +#[diag(passes_should_be_applied_to_fn_or_unit_struct)] +pub struct AttrShouldBeAppliedToFnOrUnitStruct { + #[primary_span] + pub attr_span: Span, + #[label] + pub defn_span: Span, +} + #[derive(Diagnostic)] #[diag(passes_should_be_applied_to_fn, code = E0739)] pub struct TrackedCallerWrongLocation { @@ -371,13 +380,6 @@ pub struct FfiConstInvalidTarget { pub attr_span: Span, } -#[derive(LintDiagnostic)] -#[diag(passes_must_use_async)] -pub struct MustUseAsync { - #[label] - pub span: Span, -} - #[derive(LintDiagnostic)] #[diag(passes_must_use_no_effect)] pub struct MustUseNoEffect { @@ -622,6 +624,15 @@ pub struct RustcStdInternalSymbol { pub span: Span, } +#[derive(Diagnostic)] +#[diag(passes_rustc_pub_transparent)] +pub struct RustcPubTransparent { + #[primary_span] + pub attr_span: Span, + #[label] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(passes_link_ordinal)] pub struct LinkOrdinal { @@ -643,6 +654,15 @@ pub struct CoroutineOnNonClosure { pub span: Span, } +#[derive(Diagnostic)] +#[diag(passes_linkage)] +pub struct Linkage { + #[primary_span] + pub attr_span: Span, + #[label] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(passes_empty_confusables)] pub(crate) struct EmptyConfusables { @@ -728,6 +748,13 @@ pub struct NonExportedMacroInvalidAttrs { pub attr_span: Span, } +#[derive(Diagnostic)] +#[diag(passes_may_dangle)] +pub struct InvalidMayDangle { + #[primary_span] + pub attr_span: Span, +} + #[derive(LintDiagnostic)] #[diag(passes_unused_duplicate)] pub struct UnusedDuplicate { @@ -736,7 +763,7 @@ pub struct UnusedDuplicate { #[note] pub other: Span, #[warning] - pub warning: Option<()>, + pub warning: bool, } #[derive(Diagnostic)] @@ -895,7 +922,7 @@ pub struct DuplicateDiagnosticItemInCrate { #[note(passes_diagnostic_item_first_defined)] pub orig_span: Option, #[note] - pub different_crates: Option<()>, + pub different_crates: bool, pub crate_name: Symbol, pub orig_crate_name: Symbol, pub name: Symbol, diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index 3f1be87a73f..71b0ebb0e21 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -130,7 +130,7 @@ impl<'ast, 'tcx> LanguageItemCollector<'ast, 'tcx> { if first_defined_span.is_none() { orig_crate_name = self.tcx.crate_name(original_def_id.krate); if let Some(ExternCrate { dependency_of: inner_dependency_of, .. }) = - self.tcx.extern_crate(original_def_id) + self.tcx.extern_crate(original_def_id.krate) { orig_dependency_of = self.tcx.crate_name(*inner_dependency_of); } @@ -139,7 +139,7 @@ impl<'ast, 'tcx> LanguageItemCollector<'ast, 'tcx> { let duplicate = if item_span.is_some() { Duplicate::Plain } else { - match self.tcx.extern_crate(item_def_id) { + match self.tcx.extern_crate(item_def_id.krate) { Some(ExternCrate { dependency_of: inner_dependency_of, .. }) => { dependency_of = self.tcx.crate_name(*inner_dependency_of); Duplicate::CrateDepends diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 10b7968a1a7..d7885e05a2f 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -413,7 +413,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { | ty::Foreign(_) | ty::RawPtr(_, _) | ty::FnDef(_, _) - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::Pat(_, _) | ty::Dynamic(_, _, _) | ty::Closure(..) @@ -774,17 +774,16 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { } } - /// Convert to a [`print::Pat`] for diagnostic purposes. - fn hoist_pat_range(&self, range: &IntRange, ty: RevealedTy<'tcx>) -> print::Pat<'tcx> { - use print::{Pat, PatKind}; + /// Prints an [`IntRange`] to a string for diagnostic purposes. + fn print_pat_range(&self, range: &IntRange, ty: RevealedTy<'tcx>) -> String { use MaybeInfiniteInt::*; let cx = self; - let kind = if matches!((range.lo, range.hi), (NegInfinity, PosInfinity)) { - PatKind::Wild + if matches!((range.lo, range.hi), (NegInfinity, PosInfinity)) { + "_".to_string() } else if range.is_singleton() { let lo = cx.hoist_pat_range_bdy(range.lo, ty); let value = lo.as_finite().unwrap(); - PatKind::Constant { value } + value.to_string() } else { // We convert to an inclusive range for diagnostics. let mut end = rustc_hir::RangeEnd::Included; @@ -807,32 +806,24 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { range.hi }; let hi = cx.hoist_pat_range_bdy(hi, ty); - PatKind::Range(Box::new(PatRange { lo, hi, end, ty: ty.inner() })) - }; - - Pat { ty: ty.inner(), kind } + PatRange { lo, hi, end, ty: ty.inner() }.to_string() + } } /// Prints a [`WitnessPat`] to an owned string, for diagnostic purposes. + /// + /// This panics for patterns that don't appear in diagnostics, like float ranges. pub fn print_witness_pat(&self, pat: &WitnessPat<'p, 'tcx>) -> String { - // This works by converting the witness pattern to a `print::Pat` - // and then printing that, but callers don't need to know that. - self.hoist_witness_pat(pat).to_string() - } - - /// Convert to a [`print::Pat`] for diagnostic purposes. This panics for patterns that don't - /// appear in diagnostics, like float ranges. - fn hoist_witness_pat(&self, pat: &WitnessPat<'p, 'tcx>) -> print::Pat<'tcx> { - use print::{FieldPat, Pat, PatKind}; let cx = self; - let hoist = |p| Box::new(cx.hoist_witness_pat(p)); - let kind = match pat.ctor() { - Bool(b) => PatKind::Constant { value: mir::Const::from_bool(cx.tcx, *b) }, - IntRange(range) => return self.hoist_pat_range(range, *pat.ty()), + let print = |p| cx.print_witness_pat(p); + match pat.ctor() { + Bool(b) => b.to_string(), + Str(s) => s.to_string(), + IntRange(range) => return self.print_pat_range(range, *pat.ty()), Struct if pat.ty().is_box() => { // Outside of the `alloc` crate, the only way to create a struct pattern // of type `Box` is to use a `box` pattern via #[feature(box_patterns)]. - PatKind::Box { subpattern: hoist(&pat.fields[0]) } + format!("box {}", print(&pat.fields[0])) } Struct | Variant(_) | UnionField => { let enum_info = match *pat.ty().kind() { @@ -847,12 +838,29 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { let subpatterns = pat .iter_fields() .enumerate() - .map(|(i, pat)| FieldPat { field: FieldIdx::new(i), pattern: hoist(pat) }) + .map(|(i, pat)| print::FieldPat { + field: FieldIdx::new(i), + pattern: print(pat), + is_wildcard: would_print_as_wildcard(cx.tcx, pat), + }) .collect::>(); - PatKind::StructLike { enum_info, subpatterns } + let mut s = String::new(); + print::write_struct_like( + &mut s, + self.tcx, + pat.ty().inner(), + &enum_info, + &subpatterns, + ) + .unwrap(); + s + } + Ref => { + let mut s = String::new(); + print::write_ref_like(&mut s, pat.ty().inner(), &print(&pat.fields[0])).unwrap(); + s } - Ref => PatKind::Deref { subpattern: hoist(&pat.fields[0]) }, Slice(slice) => { let (prefix_len, has_dot_dot) = match slice.kind { SliceKind::FixedLen(len) => (len, false), @@ -879,14 +887,15 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { } } - let prefix = prefix.iter().map(hoist).collect(); - let suffix = suffix.iter().map(hoist).collect(); + let prefix = prefix.iter().map(print).collect::>(); + let suffix = suffix.iter().map(print).collect::>(); - PatKind::Slice { prefix, has_dot_dot, suffix } + let mut s = String::new(); + print::write_slice_like(&mut s, &prefix, has_dot_dot, &suffix).unwrap(); + s } - &Str(value) => PatKind::Constant { value }, - Never if self.tcx.features().never_patterns => PatKind::Never, - Never | Wildcard | NonExhaustive | Hidden | PrivateUninhabited => PatKind::Wild, + Never if self.tcx.features().never_patterns => "!".to_string(), + Never | Wildcard | NonExhaustive | Hidden | PrivateUninhabited => "_".to_string(), Missing { .. } => bug!( "trying to convert a `Missing` constructor into a `Pat`; this is probably a bug, `Missing` should have been processed in `apply_constructors`" @@ -894,9 +903,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { F16Range(..) | F32Range(..) | F64Range(..) | F128Range(..) | Opaque(..) | Or => { bug!("can't convert to pattern: {:?}", pat) } - }; - - Pat { ty: pat.ty().inner(), kind } + } } } @@ -972,7 +979,7 @@ impl<'p, 'tcx: 'p> PatCx for RustcPatCtxt<'p, 'tcx> { overlaps_on: IntRange, overlaps_with: &[&crate::pat::DeconstructedPat], ) { - let overlap_as_pat = self.hoist_pat_range(&overlaps_on, *pat.ty()); + let overlap_as_pat = self.print_pat_range(&overlaps_on, *pat.ty()); let overlaps: Vec<_> = overlaps_with .iter() .map(|pat| pat.data().span) @@ -1012,7 +1019,7 @@ impl<'p, 'tcx: 'p> PatCx for RustcPatCtxt<'p, 'tcx> { suggested_range.end = rustc_hir::RangeEnd::Included; suggested_range.to_string() }; - let gap_as_pat = self.hoist_pat_range(&gap, *pat.ty()); + let gap_as_pat = self.print_pat_range(&gap, *pat.ty()); if gapped_with.is_empty() { // If `gapped_with` is empty, `gap == T::MAX`. self.tcx.emit_node_span_lint( diff --git a/compiler/rustc_pattern_analysis/src/rustc/print.rs b/compiler/rustc_pattern_analysis/src/rustc/print.rs index 7d638714605..17e389df17e 100644 --- a/compiler/rustc_pattern_analysis/src/rustc/print.rs +++ b/compiler/rustc_pattern_analysis/src/rustc/print.rs @@ -11,75 +11,16 @@ use std::fmt; -use rustc_middle::thir::PatRange; +use rustc_middle::bug; use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt}; -use rustc_middle::{bug, mir}; use rustc_span::sym; use rustc_target::abi::{FieldIdx, VariantIdx}; #[derive(Clone, Debug)] -pub(crate) struct FieldPat<'tcx> { +pub(crate) struct FieldPat { pub(crate) field: FieldIdx, - pub(crate) pattern: Box>, -} - -#[derive(Clone, Debug)] -pub(crate) struct Pat<'tcx> { - pub(crate) ty: Ty<'tcx>, - pub(crate) kind: PatKind<'tcx>, -} - -#[derive(Clone, Debug)] -pub(crate) enum PatKind<'tcx> { - Wild, - - StructLike { - enum_info: EnumInfo<'tcx>, - subpatterns: Vec>, - }, - - Box { - subpattern: Box>, - }, - - Deref { - subpattern: Box>, - }, - - Constant { - value: mir::Const<'tcx>, - }, - - Range(Box>), - - Slice { - prefix: Box<[Box>]>, - /// True if this slice-like pattern should include a `..` between the - /// prefix and suffix. - has_dot_dot: bool, - suffix: Box<[Box>]>, - }, - - Never, -} - -impl<'tcx> fmt::Display for Pat<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.kind { - PatKind::Wild => write!(f, "_"), - PatKind::Never => write!(f, "!"), - PatKind::Box { ref subpattern } => write!(f, "box {subpattern}"), - PatKind::StructLike { ref enum_info, ref subpatterns } => { - ty::tls::with(|tcx| write_struct_like(f, tcx, self.ty, enum_info, subpatterns)) - } - PatKind::Deref { ref subpattern } => write_ref_like(f, self.ty, subpattern), - PatKind::Constant { value } => write!(f, "{value}"), - PatKind::Range(ref range) => write!(f, "{range}"), - PatKind::Slice { ref prefix, has_dot_dot, ref suffix } => { - write_slice_like(f, prefix, has_dot_dot, suffix) - } - } - } + pub(crate) pattern: String, + pub(crate) is_wildcard: bool, } /// Returns a closure that will return `""` when called the first time, @@ -103,12 +44,12 @@ pub(crate) enum EnumInfo<'tcx> { NotEnum, } -fn write_struct_like<'tcx>( +pub(crate) fn write_struct_like<'tcx>( f: &mut impl fmt::Write, tcx: TyCtxt<'_>, ty: Ty<'tcx>, enum_info: &EnumInfo<'tcx>, - subpatterns: &[FieldPat<'tcx>], + subpatterns: &[FieldPat], ) -> fmt::Result { let variant_and_name = match *enum_info { EnumInfo::Enum { adt_def, variant_index } => { @@ -139,12 +80,12 @@ fn write_struct_like<'tcx>( write!(f, " {{ ")?; let mut printed = 0; - for p in subpatterns { - if let PatKind::Wild = p.pattern.kind { + for &FieldPat { field, ref pattern, is_wildcard } in subpatterns { + if is_wildcard { continue; } - let name = variant.fields[p.field].name; - write!(f, "{}{}: {}", start_or_comma(), name, p.pattern)?; + let field_name = variant.fields[field].name; + write!(f, "{}{field_name}: {pattern}", start_or_comma())?; printed += 1; } @@ -184,10 +125,10 @@ fn write_struct_like<'tcx>( Ok(()) } -fn write_ref_like<'tcx>( +pub(crate) fn write_ref_like<'tcx>( f: &mut impl fmt::Write, ty: Ty<'tcx>, - subpattern: &Pat<'tcx>, + subpattern: &str, ) -> fmt::Result { match ty.kind() { ty::Ref(_, _, mutbl) => { @@ -198,11 +139,11 @@ fn write_ref_like<'tcx>( write!(f, "{subpattern}") } -fn write_slice_like<'tcx>( +pub(crate) fn write_slice_like( f: &mut impl fmt::Write, - prefix: &[Box>], + prefix: &[String], has_dot_dot: bool, - suffix: &[Box>], + suffix: &[String], ) -> fmt::Result { let mut start_or_comma = start_or_comma(); write!(f, "[")?; diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index d1d1e5e901f..9f78215bfd1 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -626,7 +626,8 @@ impl<'tcx> EmbargoVisitor<'tcx> { | DefKind::Field | DefKind::GlobalAsm | DefKind::Impl { .. } - | DefKind::Closure => (), + | DefKind::Closure + | DefKind::SyntheticCoroutineBody => (), } } } diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 18f97d6fb8f..f4a4c602f69 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -214,7 +214,7 @@ pub fn query_system<'tcx>( local_providers, extern_providers, encode_query_results: encode_all_query_results, - try_mark_green: try_mark_green, + try_mark_green, }, jobs: AtomicU64::new(1), } diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index b9e700c1938..c064b2bd6c1 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -702,11 +702,17 @@ macro_rules! define_queries { let name = stringify!($name); $crate::plumbing::create_query_frame(tcx, rustc_middle::query::descs::$name, key, kind, name) }; - tcx.query_system.states.$name.try_collect_active_jobs( + let res = tcx.query_system.states.$name.try_collect_active_jobs( tcx, make_query, qmap, - ).unwrap(); + ); + // this can be called during unwinding, and the function has a `try_`-prefix, so + // don't `unwrap()` here, just manually check for `None` and do best-effort error + // reporting. + if res.is_none() { + tracing::warn!("Failed to collect active jobs for query with name `{}`!", stringify!($name)); + } } pub fn alloc_self_profile_query_strings<'tcx>(tcx: TyCtxt<'tcx>, string_cache: &mut QueryKeyStringCache) { diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs index ff1c3431b7c..ab4a8be0fbf 100644 --- a/compiler/rustc_query_system/src/dep_graph/serialized.rs +++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs @@ -547,7 +547,7 @@ impl EncoderState { /// Encodes a node that was promoted from the previous graph. It reads the information directly from /// the previous dep graph for performance reasons. /// - /// This differs from `encode_node` where you have to explictly provide the relevant `NodeInfo`. + /// This differs from `encode_node` where you have to explicitly provide the relevant `NodeInfo`. /// /// It expects all edges to already have a new dep node index assigned. #[inline] diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 8ef680cdb6c..6dbd6e89fe9 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -181,8 +181,15 @@ where cache.complete(key, result, dep_node_index); let job = { - let mut lock = state.active.lock_shard_by_value(&key); - lock.remove(&key).unwrap().expect_job() + let val = { + // don't keep the lock during the `unwrap()` of the retrieved value, or we taint the + // underlying shard. + // since unwinding also wants to look at this map, this can also prevent a double + // panic. + let mut lock = state.active.lock_shard_by_value(&key); + lock.remove(&key) + }; + val.unwrap().expect_job() }; job.signal_complete(); diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index d57dabdd78d..3ea782b62f1 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -197,8 +197,78 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pub(crate) fn build_reduced_graph_external(&mut self, module: Module<'a>) { for child in self.tcx.module_children(module.def_id()) { let parent_scope = ParentScope::module(module, self); - BuildReducedGraphVisitor { r: self, parent_scope } - .build_reduced_graph_for_external_crate_res(child); + self.build_reduced_graph_for_external_crate_res(child, parent_scope) + } + } + + /// Builds the reduced graph for a single item in an external crate. + fn build_reduced_graph_for_external_crate_res( + &mut self, + child: &ModChild, + parent_scope: ParentScope<'a>, + ) { + let parent = parent_scope.module; + let ModChild { ident, res, vis, ref reexport_chain } = *child; + let span = self.def_span( + reexport_chain + .first() + .and_then(|reexport| reexport.id()) + .unwrap_or_else(|| res.def_id()), + ); + let res = res.expect_non_local(); + let expansion = parent_scope.expansion; + // Record primary definitions. + match res { + Res::Def(DefKind::Mod | DefKind::Enum | DefKind::Trait, def_id) => { + let module = self.expect_module(def_id); + self.define(parent, ident, TypeNS, (module, vis, span, expansion)); + } + Res::Def( + DefKind::Struct + | DefKind::Union + | DefKind::Variant + | DefKind::TyAlias + | DefKind::ForeignTy + | DefKind::OpaqueTy + | DefKind::TraitAlias + | DefKind::AssocTy, + _, + ) + | Res::PrimTy(..) + | Res::ToolMod => self.define(parent, ident, TypeNS, (res, vis, span, expansion)), + Res::Def( + DefKind::Fn + | DefKind::AssocFn + | DefKind::Static { .. } + | DefKind::Const + | DefKind::AssocConst + | DefKind::Ctor(..), + _, + ) => self.define(parent, ident, ValueNS, (res, vis, span, expansion)), + Res::Def(DefKind::Macro(..), _) | Res::NonMacroAttr(..) => { + self.define(parent, ident, MacroNS, (res, vis, span, expansion)) + } + Res::Def( + DefKind::TyParam + | DefKind::ConstParam + | DefKind::ExternCrate + | DefKind::Use + | DefKind::ForeignMod + | DefKind::AnonConst + | DefKind::InlineConst + | DefKind::Field + | DefKind::LifetimeParam + | DefKind::GlobalAsm + | DefKind::Closure + | DefKind::SyntheticCoroutineBody + | DefKind::Impl { .. }, + _, + ) + | Res::Local(..) + | Res::SelfTyParam { .. } + | Res::SelfTyAlias { .. } + | Res::SelfCtor(..) + | Res::Err => bug!("unexpected resolution: {:?}", res), } } } @@ -896,7 +966,8 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.r.potentially_unused_imports.push(import); let imported_binding = self.r.import(binding, import); if parent == self.r.graph_root { - if let Some(entry) = self.r.extern_prelude.get(&ident.normalize_to_macros_2_0()) { + let ident = ident.normalize_to_macros_2_0(); + if let Some(entry) = self.r.extern_prelude.get(&ident) { if expansion != LocalExpnId::ROOT && orig_name.is_some() && !entry.is_import() { self.r.dcx().emit_err( errors::MacroExpandedExternCrateCannotShadowExternArguments { @@ -913,14 +984,21 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { let entry = self .r .extern_prelude - .entry(ident.normalize_to_macros_2_0()) + .entry(ident) .or_insert(ExternPreludeEntry { binding: None, introduced_by_item: true }); - // Binding from `extern crate` item in source code can replace - // a binding from `--extern` on command line here. - entry.binding = Some(imported_binding); if orig_name.is_some() { entry.introduced_by_item = true; } + // Binding from `extern crate` item in source code can replace + // a binding from `--extern` on command line here. + if !entry.is_import() { + entry.binding = Some(imported_binding) + } else if ident.name != kw::Underscore { + self.r.dcx().span_delayed_bug( + item.span, + format!("it had been define the external module '{ident}' multiple times"), + ); + } } self.r.define(parent, ident, TypeNS, imported_binding); } @@ -959,72 +1037,6 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } } - /// Builds the reduced graph for a single item in an external crate. - fn build_reduced_graph_for_external_crate_res(&mut self, child: &ModChild) { - let parent = self.parent_scope.module; - let ModChild { ident, res, vis, ref reexport_chain } = *child; - let span = self.r.def_span( - reexport_chain - .first() - .and_then(|reexport| reexport.id()) - .unwrap_or_else(|| res.def_id()), - ); - let res = res.expect_non_local(); - let expansion = self.parent_scope.expansion; - // Record primary definitions. - match res { - Res::Def(DefKind::Mod | DefKind::Enum | DefKind::Trait, def_id) => { - let module = self.r.expect_module(def_id); - self.r.define(parent, ident, TypeNS, (module, vis, span, expansion)); - } - Res::Def( - DefKind::Struct - | DefKind::Union - | DefKind::Variant - | DefKind::TyAlias - | DefKind::ForeignTy - | DefKind::OpaqueTy - | DefKind::TraitAlias - | DefKind::AssocTy, - _, - ) - | Res::PrimTy(..) - | Res::ToolMod => self.r.define(parent, ident, TypeNS, (res, vis, span, expansion)), - Res::Def( - DefKind::Fn - | DefKind::AssocFn - | DefKind::Static { .. } - | DefKind::Const - | DefKind::AssocConst - | DefKind::Ctor(..), - _, - ) => self.r.define(parent, ident, ValueNS, (res, vis, span, expansion)), - Res::Def(DefKind::Macro(..), _) | Res::NonMacroAttr(..) => { - self.r.define(parent, ident, MacroNS, (res, vis, span, expansion)) - } - Res::Def( - DefKind::TyParam - | DefKind::ConstParam - | DefKind::ExternCrate - | DefKind::Use - | DefKind::ForeignMod - | DefKind::AnonConst - | DefKind::InlineConst - | DefKind::Field - | DefKind::LifetimeParam - | DefKind::GlobalAsm - | DefKind::Closure - | DefKind::Impl { .. }, - _, - ) - | Res::Local(..) - | Res::SelfTyParam { .. } - | Res::SelfTyAlias { .. } - | Res::SelfCtor(..) - | Res::Err => bug!("unexpected resolution: {:?}", res), - } - } - fn add_macro_use_binding( &mut self, name: Symbol, @@ -1150,7 +1162,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { fn contains_macro_use(&mut self, attrs: &[ast::Attribute]) -> bool { for attr in attrs { if attr.has_name(sym::macro_escape) { - let inner_attribute = matches!(attr.style, ast::AttrStyle::Inner).then_some(()); + let inner_attribute = matches!(attr.style, ast::AttrStyle::Inner); self.r .dcx() .emit_warn(errors::MacroExternDeprecated { span: attr.span, inner_attribute }); diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index ed23870dfdf..3595db78e93 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -314,13 +314,15 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { } fn visit_anon_const(&mut self, constant: &'a AnonConst) { - // HACK(min_generic_const_args): don't create defs for anon consts if we think they will - // later be turned into ConstArgKind::Path's. because this is before resolve is done, we - // may accidentally identify a construction of a unit struct as a param and not create a - // def. we'll then create a def later in ast lowering in this case. the parent of nested - // items will be messed up, but that's ok because there can't be any if we're just looking - // for bare idents. - if constant.value.is_potential_trivial_const_arg() { + if self.resolver.tcx.features().const_arg_path + && constant.value.is_potential_trivial_const_arg() + { + // HACK(min_generic_const_args): don't create defs for anon consts if we think they will + // later be turned into ConstArgKind::Path's. because this is before resolve is done, we + // may accidentally identify a construction of a unit struct as a param and not create a + // def. we'll then create a def later in ast lowering in this case. the parent of nested + // items will be messed up, but that's ok because there can't be any if we're just looking + // for bare idents. visit::walk_anon_const(self, constant) } else { let def = diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 942026ef012..bcbdf627b56 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1456,7 +1456,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let label_span = ident.span.shrink_to_hi(); let mut spans = MultiSpan::from_span(label_span); spans.push_span_label(label_span, "put a macro name here"); - err.subdiagnostic(MaybeMissingMacroRulesName { spans: spans }); + err.subdiagnostic(MaybeMissingMacroRulesName { spans }); return; } diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index ad1841e3e89..662b772413b 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -850,7 +850,7 @@ pub(crate) struct MacroExternDeprecated { #[primary_span] pub(crate) span: Span, #[help] - pub inner_attribute: Option<()>, + pub inner_attribute: bool, } #[derive(Diagnostic)] diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 4a70fc0f308..40fdb01a72c 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2677,14 +2677,14 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // We also can't shadow bindings from associated parent items. for ns in [ValueNS, TypeNS] { for parent_rib in self.ribs[ns].iter().rev() { - seen_bindings - .extend(parent_rib.bindings.keys().map(|ident| (*ident, ident.span))); - // Break at mod level, to account for nested items which are // allowed to shadow generic param names. if matches!(parent_rib.kind, RibKind::Module(..)) { break; } + + seen_bindings + .extend(parent_rib.bindings.keys().map(|ident| (*ident, ident.span))); } } diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs index 61de338eab1..a4e4f50e8f2 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs @@ -607,10 +607,15 @@ pub fn encode_ty<'tcx>( typeid.push_str(&s); } - ty::FnPtr(fn_sig) => { + ty::FnPtr(sig_tys, hdr) => { // PFE let mut s = String::from("P"); - s.push_str(&encode_fnsig(tcx, &fn_sig.skip_binder(), dict, TypeIdOptions::empty())); + s.push_str(&encode_fnsig( + tcx, + &sig_tys.with(*hdr).skip_binder(), + dict, + TypeIdOptions::empty(), + )); compress(dict, DictKey::Ty(ty, TyQ::None), &mut s); typeid.push_str(&s); } diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs index e628c17aca3..2f43199796c 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs @@ -146,7 +146,7 @@ impl<'tcx> TypeFolder> for TransformTy<'tcx> { !is_zst }); if let Some(field) = field { - let ty0 = self.tcx.type_of(field.did).instantiate(self.tcx, args); + let ty0 = self.tcx.erase_regions(field.ty(self.tcx, args)); // Generalize any repr(transparent) user-defined type that is either a // pointer or reference, and either references itself or any other type that // contains or references itself, to avoid a reference cycle. @@ -316,7 +316,7 @@ pub fn transform_instance<'tcx>( .drop_trait() .unwrap_or_else(|| bug!("typeid_for_instance: couldn't get drop_trait lang item")); let predicate = ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef { - def_id: def_id, + def_id, args: List::empty(), }); let predicates = tcx.mk_poly_existential_predicates(&[ty::Binder::dummy(predicate)]); diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl index b84280a3ccf..01c371ee498 100644 --- a/compiler/rustc_session/messages.ftl +++ b/compiler/rustc_session/messages.ftl @@ -14,6 +14,10 @@ session_crate_name_empty = crate name must not be empty session_crate_name_invalid = crate names cannot start with a `-`, but `{$s}` has a leading hyphen +session_embed_source_insufficient_dwarf_version = `-Zembed-source=y` requires at least `-Z dwarf-version=5` but DWARF version is {$dwarf_version} + +session_embed_source_requires_debug_info = `-Zembed-source=y` requires debug information to be enabled + session_expr_parentheses_needed = parentheses are required to parse this as an expression session_failed_to_create_profiler = failed to create profiler: {$err} diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 95d171409d8..4fb3702b05d 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2893,6 +2893,7 @@ pub enum PpHirMode { } #[derive(Copy, Clone, PartialEq, Debug)] +/// Pretty print mode pub enum PpMode { /// Options that print the source code, i.e. /// `-Zunpretty=normal` and `-Zunpretty=expanded` diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 5cc54a5855b..15bbd4ff7bf 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -165,6 +165,16 @@ pub(crate) struct UnsupportedDwarfVersion { pub(crate) dwarf_version: u32, } +#[derive(Diagnostic)] +#[diag(session_embed_source_insufficient_dwarf_version)] +pub(crate) struct EmbedSourceInsufficientDwarfVersion { + pub(crate) dwarf_version: u32, +} + +#[derive(Diagnostic)] +#[diag(session_embed_source_requires_debug_info)] +pub(crate) struct EmbedSourceRequiresDebugInfo; + #[derive(Diagnostic)] #[diag(session_target_stack_protector_not_supported)] pub(crate) struct StackProtectorNotSupportedForTarget<'a> { diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs index 63ca5fefd9f..d78f4a78de7 100644 --- a/compiler/rustc_session/src/filesearch.rs +++ b/compiler/rustc_session/src/filesearch.rs @@ -5,14 +5,11 @@ use std::{env, fs}; use rustc_fs_util::{fix_windows_verbatim_for_gcc, try_canonicalize}; use smallvec::{smallvec, SmallVec}; -use tracing::debug; use crate::search_paths::{PathKind, SearchPath}; #[derive(Clone)] pub struct FileSearch<'a> { - sysroot: &'a Path, - triple: &'a str, cli_search_paths: &'a [SearchPath], tlib_path: &'a SearchPath, kind: PathKind, @@ -32,23 +29,12 @@ impl<'a> FileSearch<'a> { .chain(std::iter::once(self.tlib_path)) } - pub fn get_lib_path(&self) -> PathBuf { - make_target_lib_path(self.sysroot, self.triple) - } - - pub fn get_self_contained_lib_path(&self) -> PathBuf { - self.get_lib_path().join("self-contained") - } - pub fn new( - sysroot: &'a Path, - triple: &'a str, cli_search_paths: &'a [SearchPath], tlib_path: &'a SearchPath, kind: PathKind, ) -> FileSearch<'a> { - debug!("using sysroot = {}, triple = {}", sysroot.display(), triple); - FileSearch { sysroot, triple, cli_search_paths, tlib_path, kind } + FileSearch { cli_search_paths, tlib_path, kind } } } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index df72e2430fd..23231fbffbf 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1701,6 +1701,8 @@ options! { them only if an error has not been emitted"), ehcont_guard: bool = (false, parse_bool, [TRACKED], "generate Windows EHCont Guard tables"), + embed_source: bool = (false, parse_bool, [TRACKED], + "embed source text in DWARF debug sections (default: no)"), emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED], "emit a section containing stack size metadata (default: no)"), emit_thin_lto: bool = (true, parse_bool, [TRACKED], diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 672dddf871e..70430d82ab5 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -37,8 +37,9 @@ use rustc_target::spec::{ use crate::code_stats::CodeStats; pub use crate::code_stats::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo}; use crate::config::{ - self, CoverageLevel, CrateType, ErrorOutputType, FunctionReturn, Input, InstrumentCoverage, - OptLevel, OutFileName, OutputType, RemapPathScopeComponents, SwitchWithOptPath, + self, CoverageLevel, CrateType, DebugInfo, ErrorOutputType, FunctionReturn, Input, + InstrumentCoverage, OptLevel, OutFileName, OutputType, RemapPathScopeComponents, + SwitchWithOptPath, }; use crate::parse::{add_feature_diagnostics, ParseSess}; use crate::search_paths::{PathKind, SearchPath}; @@ -439,22 +440,10 @@ impl Session { } pub fn target_filesearch(&self, kind: PathKind) -> filesearch::FileSearch<'_> { - filesearch::FileSearch::new( - &self.sysroot, - self.opts.target_triple.triple(), - &self.opts.search_paths, - &self.target_tlib_path, - kind, - ) + filesearch::FileSearch::new(&self.opts.search_paths, &self.target_tlib_path, kind) } pub fn host_filesearch(&self, kind: PathKind) -> filesearch::FileSearch<'_> { - filesearch::FileSearch::new( - &self.sysroot, - config::host_triple(), - &self.opts.search_paths, - &self.host_tlib_path, - kind, - ) + filesearch::FileSearch::new(&self.opts.search_paths, &self.host_tlib_path, kind) } /// Returns a list of directories where target-specific tool binaries are located. Some fallback @@ -1188,7 +1177,12 @@ fn validate_commandline_args_with_session_available(sess: &Session) { // Sanitizers can only be used on platforms that we know have working sanitizer codegen. let supported_sanitizers = sess.target.options.supported_sanitizers; - let unsupported_sanitizers = sess.opts.unstable_opts.sanitizer - supported_sanitizers; + let mut unsupported_sanitizers = sess.opts.unstable_opts.sanitizer - supported_sanitizers; + // Niche: if `fixed-x18`, or effectively switching on `reserved-x18` flag, is enabled + // we should allow Shadow Call Stack sanitizer. + if sess.opts.unstable_opts.fixed_x18 && sess.target.arch == "aarch64" { + unsupported_sanitizers -= SanitizerSet::SHADOWCALLSTACK; + } match unsupported_sanitizers.into_iter().count() { 0 => {} 1 => { @@ -1301,6 +1295,19 @@ fn validate_commandline_args_with_session_available(sess: &Session) { .emit_err(errors::SplitDebugInfoUnstablePlatform { debuginfo: sess.split_debuginfo() }); } + if sess.opts.unstable_opts.embed_source { + let dwarf_version = + sess.opts.unstable_opts.dwarf_version.unwrap_or(sess.target.default_dwarf_version); + + if dwarf_version < 5 { + sess.dcx().emit_warn(errors::EmbedSourceInsufficientDwarfVersion { dwarf_version }); + } + + if sess.opts.debuginfo == DebugInfo::None { + sess.dcx().emit_warn(errors::EmbedSourceRequiresDebugInfo); + } + } + if sess.opts.unstable_opts.instrument_xray.is_some() && !sess.target.options.supports_xray { sess.dcx().emit_err(errors::InstrumentationNotSupported { us: "XRay".to_string() }); } diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs index a4577461094..f52cb010a87 100644 --- a/compiler/rustc_smir/src/rustc_internal/internal.rs +++ b/compiler/rustc_smir/src/rustc_internal/internal.rs @@ -131,7 +131,10 @@ impl RustcInternal for RigidTy { RigidTy::FnDef(def, args) => { rustc_ty::TyKind::FnDef(def.0.internal(tables, tcx), args.internal(tables, tcx)) } - RigidTy::FnPtr(sig) => rustc_ty::TyKind::FnPtr(sig.internal(tables, tcx)), + RigidTy::FnPtr(sig) => { + let (sig_tys, hdr) = sig.internal(tables, tcx).split(); + rustc_ty::TyKind::FnPtr(sig_tys, hdr) + } RigidTy::Closure(def, args) => { rustc_ty::TyKind::Closure(def.0.internal(tables, tcx), args.internal(tables, tcx)) } diff --git a/compiler/rustc_smir/src/rustc_smir/alloc.rs b/compiler/rustc_smir/src/rustc_smir/alloc.rs index 0519722e4be..677b4c7a9c0 100644 --- a/compiler/rustc_smir/src/rustc_smir/alloc.rs +++ b/compiler/rustc_smir/src/rustc_smir/alloc.rs @@ -132,7 +132,7 @@ pub(super) fn allocation_filter<'tcx>( )); } Allocation { - bytes: bytes, + bytes, provenance: ProvenanceMap { ptrs }, align: alloc.align.bytes(), mutability: alloc.mutability.stable(tables), diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs index da705e6f959..c442ca861d3 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs @@ -174,7 +174,7 @@ impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> { ThreadLocalRef(def_id) => { stable_mir::mir::Rvalue::ThreadLocalRef(tables.crate_item(*def_id)) } - AddressOf(mutability, place) => { + RawPtr(mutability, place) => { stable_mir::mir::Rvalue::AddressOf(mutability.stable(tables), place.stable(tables)) } Len(place) => stable_mir::mir::Rvalue::Len(place.stable(tables)), diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index ef2eb7d52ea..9afd732486c 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -352,7 +352,9 @@ impl<'tcx> Stable<'tcx> for ty::TyKind<'tcx> { ty::FnDef(def_id, generic_args) => { TyKind::RigidTy(RigidTy::FnDef(tables.fn_def(*def_id), generic_args.stable(tables))) } - ty::FnPtr(poly_fn_sig) => TyKind::RigidTy(RigidTy::FnPtr(poly_fn_sig.stable(tables))), + ty::FnPtr(sig_tys, hdr) => { + TyKind::RigidTy(RigidTy::FnPtr(sig_tys.with(*hdr).stable(tables))) + } ty::Dynamic(existential_predicates, region, dyn_kind) => { TyKind::RigidTy(RigidTy::Dynamic( existential_predicates @@ -849,7 +851,6 @@ impl<'tcx> Stable<'tcx> for ty::Instance<'tcx> { | ty::InstanceKind::FnPtrAddrShim(..) | ty::InstanceKind::ClosureOnceShim { .. } | ty::InstanceKind::ConstructCoroutineInClosureShim { .. } - | ty::InstanceKind::CoroutineKindShim { .. } | ty::InstanceKind::ThreadLocalShim(..) | ty::InstanceKind::DropGlue(..) | ty::InstanceKind::CloneShim(..) diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 41e9698242b..9b27b94fb5a 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -114,7 +114,9 @@ pub(crate) fn new_item_kind(kind: DefKind) -> ItemKind { | DefKind::GlobalAsm => { unreachable!("Not a valid item kind: {kind:?}"); } - DefKind::Closure | DefKind::AssocFn | DefKind::Fn => ItemKind::Fn, + DefKind::Closure | DefKind::AssocFn | DefKind::Fn | DefKind::SyntheticCoroutineBody => { + ItemKind::Fn + } DefKind::Const | DefKind::InlineConst | DefKind::AssocConst | DefKind::AnonConst => { ItemKind::Const } diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 434df35a515..5e1b1b44bc2 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -1415,6 +1415,14 @@ pub fn decode_syntax_context SyntaxContext // Overwrite the dummy data with our decoded SyntaxContextData HygieneData::with(|hygiene_data| { + if let Some(old) = hygiene_data.syntax_context_data.get(raw_id as usize) + && old.outer_expn == ctxt_data.outer_expn + && old.outer_transparency == ctxt_data.outer_transparency + && old.parent == ctxt_data.parent + { + ctxt_data = old.clone(); + } + let dummy = std::mem::replace( &mut hygiene_data.syntax_context_data[ctxt.as_u32() as usize], ctxt_data, diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 35fe28c5d42..7b020f11cdd 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -26,7 +26,6 @@ #![feature(let_chains)] #![feature(min_specialization)] #![feature(negative_impls)] -#![feature(new_uninit)] #![feature(read_buf)] #![feature(round_char_boundary)] #![feature(rustc_attrs)] diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 9cb729ec485..aba56732725 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -356,6 +356,7 @@ symbols! { _task_context, a32, aarch64_target_feature, + aarch64_unstable_target_feature, aarch64_ver_target_feature, abi, abi_amdgpu_kernel, @@ -472,6 +473,7 @@ symbols! { attr, attr_literals, attributes, + audit_that, augmented_assignments, auto_traits, automatically_derived, @@ -594,6 +596,7 @@ symbols! { conservative_impl_trait, console, const_allocate, + const_arg_path, const_async_blocks, const_closures, const_compare_raw_pointers, @@ -672,6 +675,7 @@ symbols! { crate_visibility_modifier, crt_dash_static: "crt-static", csky_target_feature, + cstr_type, cstring_type, ctlz, ctlz_nonzero, @@ -1671,6 +1675,7 @@ symbols! { rustc_private, rustc_proc_macro_decls, rustc_promotable, + rustc_pub_transparent, rustc_reallocator, rustc_regions, rustc_reservation_impl, @@ -1848,6 +1853,7 @@ symbols! { stringify, struct_field_attributes, struct_inherit, + struct_target_features, struct_variant, structural_match, structural_peq, @@ -1892,6 +1898,7 @@ symbols! { three_way_compare, thumb2, thumb_mode: "thumb-mode", + time, tmm_reg, to_owned_method, to_string, diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 0f91684a3a4..59ccd6dff85 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -92,9 +92,6 @@ pub(super) fn mangle<'tcx>( .write_str(if receiver_by_ref { "{{by-move-shim}}" } else { "{{by-ref-shim}}" }) .unwrap(); } - ty::InstanceKind::CoroutineKindShim { .. } => { - printer.write_str("{{by-move-body-shim}}").unwrap(); - } _ => {} } diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index c2451c08d11..75f4499352b 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -56,7 +56,6 @@ pub(super) fn mangle<'tcx>( ty::InstanceKind::ConstructCoroutineInClosureShim { receiver_by_ref: false, .. } => { Some("by_ref") } - ty::InstanceKind::CoroutineKindShim { .. } => Some("by_move_body"), _ => None, }; @@ -427,7 +426,8 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { self.print_def_path(def_id, &[])?; } - ty::FnPtr(sig) => { + ty::FnPtr(sig_tys, hdr) => { + let sig = sig_tys.with(hdr); self.push("F"); self.in_binder(&sig, |cx, sig| { if sig.safety == hir::Safety::Unsafe { diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 5bfc528dffc..082c169b210 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -652,6 +652,21 @@ impl<'a, Ty> ArgAbi<'a, Ty> { } } + /// Same as `make_indirect`, but for arguments that are ignored. Only needed for ABIs that pass + /// ZSTs indirectly. + pub fn make_indirect_from_ignore(&mut self) { + match self.mode { + PassMode::Ignore => { + self.mode = Self::indirect_pass_mode(&self.layout); + } + PassMode::Indirect { attrs: _, meta_attrs: _, on_stack: false } => { + // already indirect + return; + } + _ => panic!("Tried to make {:?} indirect (expected `PassMode::Ignore`)", self.mode), + } + } + /// Pass this argument indirectly, by placing it at a fixed stack offset. /// This corresponds to the `byval` LLVM argument attribute. /// This is only valid for sized arguments. @@ -730,10 +745,25 @@ impl<'a, Ty> ArgAbi<'a, Ty> { /// Checks if these two `ArgAbi` are equal enough to be considered "the same for all /// function call ABIs". - pub fn eq_abi(&self, other: &Self) -> bool { + pub fn eq_abi(&self, other: &Self) -> bool + where + Ty: PartialEq, + { // Ideally we'd just compare the `mode`, but that is not enough -- for some modes LLVM will look // at the type. - self.layout.eq_abi(&other.layout) && self.mode.eq_abi(&other.mode) + self.layout.eq_abi(&other.layout) && self.mode.eq_abi(&other.mode) && { + // `fn_arg_sanity_check` accepts `PassMode::Direct` for some aggregates. + // That elevates any type difference to an ABI difference since we just use the + // full Rust type as the LLVM argument/return type. + if matches!(self.mode, PassMode::Direct(..)) + && matches!(self.layout.abi, Abi::Aggregate { .. }) + { + // For aggregates in `Direct` mode to be compatible, the types need to be equal. + self.layout.ty == other.layout.ty + } else { + true + } + } } } @@ -871,10 +901,10 @@ impl<'a, Ty> FnAbi<'a, Ty> { } "x86_64" => match abi { spec::abi::Abi::SysV64 { .. } => x86_64::compute_abi_info(cx, self), - spec::abi::Abi::Win64 { .. } => x86_win64::compute_abi_info(self), + spec::abi::Abi::Win64 { .. } => x86_win64::compute_abi_info(cx, self), _ => { if cx.target_spec().is_like_windows { - x86_win64::compute_abi_info(self) + x86_win64::compute_abi_info(cx, self) } else { x86_64::compute_abi_info(cx, self) } @@ -898,7 +928,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { "csky" => csky::compute_abi_info(self), "mips" | "mips32r6" => mips::compute_abi_info(cx, self), "mips64" | "mips64r6" => mips64::compute_abi_info(cx, self), - "powerpc" => powerpc::compute_abi_info(self), + "powerpc" => powerpc::compute_abi_info(cx, self), "powerpc64" => powerpc64::compute_abi_info(cx, self), "s390x" => s390x::compute_abi_info(cx, self), "msp430" => msp430::compute_abi_info(self), diff --git a/compiler/rustc_target/src/abi/call/powerpc.rs b/compiler/rustc_target/src/abi/call/powerpc.rs index 70c32db0a87..8f67f57cd2b 100644 --- a/compiler/rustc_target/src/abi/call/powerpc.rs +++ b/compiler/rustc_target/src/abi/call/powerpc.rs @@ -1,4 +1,5 @@ use crate::abi::call::{ArgAbi, FnAbi}; +use crate::spec::HasTargetSpec; fn classify_ret(ret: &mut ArgAbi<'_, Ty>) { if ret.layout.is_aggregate() { @@ -8,7 +9,17 @@ fn classify_ret(ret: &mut ArgAbi<'_, Ty>) { } } -fn classify_arg(arg: &mut ArgAbi<'_, Ty>) { +fn classify_arg(cx: &impl HasTargetSpec, arg: &mut ArgAbi<'_, Ty>) { + if arg.is_ignore() { + // powerpc-unknown-linux-{gnu,musl,uclibc} doesn't ignore ZSTs. + if cx.target_spec().os == "linux" + && matches!(&*cx.target_spec().env, "gnu" | "musl" | "uclibc") + && arg.layout.is_zst() + { + arg.make_indirect_from_ignore(); + } + return; + } if arg.layout.is_aggregate() { arg.make_indirect(); } else { @@ -16,15 +27,12 @@ fn classify_arg(arg: &mut ArgAbi<'_, Ty>) { } } -pub fn compute_abi_info(fn_abi: &mut FnAbi<'_, Ty>) { +pub fn compute_abi_info(cx: &impl HasTargetSpec, fn_abi: &mut FnAbi<'_, Ty>) { if !fn_abi.ret.is_ignore() { classify_ret(&mut fn_abi.ret); } for arg in fn_abi.args.iter_mut() { - if arg.is_ignore() { - continue; - } - classify_arg(arg); + classify_arg(cx, arg); } } diff --git a/compiler/rustc_target/src/abi/call/s390x.rs b/compiler/rustc_target/src/abi/call/s390x.rs index 1a2191082d5..901ce139c7b 100644 --- a/compiler/rustc_target/src/abi/call/s390x.rs +++ b/compiler/rustc_target/src/abi/call/s390x.rs @@ -3,6 +3,7 @@ use crate::abi::call::{ArgAbi, FnAbi, Reg}; use crate::abi::{HasDataLayout, TyAbiInterface}; +use crate::spec::HasTargetSpec; fn classify_ret(ret: &mut ArgAbi<'_, Ty>) { if !ret.layout.is_aggregate() && ret.layout.size.bits() <= 64 { @@ -15,12 +16,22 @@ fn classify_ret(ret: &mut ArgAbi<'_, Ty>) { fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) where Ty: TyAbiInterface<'a, C> + Copy, - C: HasDataLayout, + C: HasDataLayout + HasTargetSpec, { if !arg.layout.is_sized() { // Not touching this... return; } + if arg.is_ignore() { + // s390x-unknown-linux-{gnu,musl,uclibc} doesn't ignore ZSTs. + if cx.target_spec().os == "linux" + && matches!(&*cx.target_spec().env, "gnu" | "musl" | "uclibc") + && arg.layout.is_zst() + { + arg.make_indirect_from_ignore(); + } + return; + } if !arg.layout.is_aggregate() && arg.layout.size.bits() <= 64 { arg.extend_integer_width_to(64); return; @@ -46,16 +57,13 @@ where pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where Ty: TyAbiInterface<'a, C> + Copy, - C: HasDataLayout, + C: HasDataLayout + HasTargetSpec, { if !fn_abi.ret.is_ignore() { classify_ret(&mut fn_abi.ret); } for arg in fn_abi.args.iter_mut() { - if arg.is_ignore() { - continue; - } classify_arg(cx, arg); } } diff --git a/compiler/rustc_target/src/abi/call/sparc64.rs b/compiler/rustc_target/src/abi/call/sparc64.rs index c0952130e04..311691d8efb 100644 --- a/compiler/rustc_target/src/abi/call/sparc64.rs +++ b/compiler/rustc_target/src/abi/call/sparc64.rs @@ -4,6 +4,7 @@ use crate::abi::call::{ ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, FnAbi, Reg, Uniform, }; use crate::abi::{self, HasDataLayout, Scalar, Size, TyAbiInterface, TyAndLayout}; +use crate::spec::HasTargetSpec; #[derive(Clone, Debug)] pub struct Sdata { @@ -211,7 +212,7 @@ where pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where Ty: TyAbiInterface<'a, C> + Copy, - C: HasDataLayout, + C: HasDataLayout + HasTargetSpec, { if !fn_abi.ret.is_ignore() { classify_arg(cx, &mut fn_abi.ret, Size::from_bytes(32)); @@ -219,7 +220,14 @@ where for arg in fn_abi.args.iter_mut() { if arg.is_ignore() { - continue; + // sparc64-unknown-linux-{gnu,musl,uclibc} doesn't ignore ZSTs. + if cx.target_spec().os == "linux" + && matches!(&*cx.target_spec().env, "gnu" | "musl" | "uclibc") + && arg.layout.is_zst() + { + arg.make_indirect_from_ignore(); + } + return; } classify_arg(cx, arg, Size::from_bytes(16)); } diff --git a/compiler/rustc_target/src/abi/call/x86_win64.rs b/compiler/rustc_target/src/abi/call/x86_win64.rs index 4e19460bd28..720707ef53f 100644 --- a/compiler/rustc_target/src/abi/call/x86_win64.rs +++ b/compiler/rustc_target/src/abi/call/x86_win64.rs @@ -1,9 +1,10 @@ use crate::abi::call::{ArgAbi, FnAbi, Reg}; use crate::abi::{Abi, Float, Primitive}; +use crate::spec::HasTargetSpec; // Win64 ABI: https://docs.microsoft.com/en-us/cpp/build/parameter-passing -pub fn compute_abi_info(fn_abi: &mut FnAbi<'_, Ty>) { +pub fn compute_abi_info(cx: &impl HasTargetSpec, fn_abi: &mut FnAbi<'_, Ty>) { let fixup = |a: &mut ArgAbi<'_, Ty>| { match a.layout.abi { Abi::Uninhabited | Abi::Aggregate { sized: false } => {} @@ -37,6 +38,13 @@ pub fn compute_abi_info(fn_abi: &mut FnAbi<'_, Ty>) { } for arg in fn_abi.args.iter_mut() { if arg.is_ignore() { + // x86_64-pc-windows-gnu doesn't ignore ZSTs. + if cx.target_spec().os == "windows" + && cx.target_spec().env == "gnu" + && arg.layout.is_zst() + { + arg.make_indirect_from_ignore(); + } continue; } fixup(arg); diff --git a/compiler/rustc_target/src/asm/aarch64.rs b/compiler/rustc_target/src/asm/aarch64.rs index 358efb4174d..daf5162e8ac 100644 --- a/compiler/rustc_target/src/asm/aarch64.rs +++ b/compiler/rustc_target/src/asm/aarch64.rs @@ -59,11 +59,11 @@ impl AArch64InlineAsmRegClass { _arch: InlineAsmArch, ) -> &'static [(InlineAsmType, Option)] { match self { - Self::reg => types! { _: I8, I16, I32, I64, F32, F64; }, + Self::reg => types! { _: I8, I16, I32, I64, F16, F32, F64; }, Self::vreg | Self::vreg_low16 => types! { - neon: I8, I16, I32, I64, F32, F64, - VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF32(2), VecF64(1), - VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2); + neon: I8, I16, I32, I64, F16, F32, F64, F128, + VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF16(4), VecF32(2), VecF64(1), + VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF16(8), VecF32(4), VecF64(2); }, Self::preg => &[], } diff --git a/compiler/rustc_target/src/spec/abi/mod.rs b/compiler/rustc_target/src/spec/abi/mod.rs index 0d61345a70e..cc383f88fbc 100644 --- a/compiler/rustc_target/src/spec/abi/mod.rs +++ b/compiler/rustc_target/src/spec/abi/mod.rs @@ -53,6 +53,8 @@ pub enum Abi { }, RustIntrinsic, RustCall, + /// *Not* a stable ABI, just directly use the Rust types to describe the ABI for LLVM. Even + /// normally ABI-compatible Rust types can become ABI-incompatible with this ABI! Unadjusted, /// For things unlikely to be called, where reducing register pressure in /// `extern "Rust"` callers is worth paying extra cost in the callee. diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 8ce51ba2463..d5f227a84a4 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1561,6 +1561,7 @@ supported_targets! { ("powerpc-unknown-linux-gnu", powerpc_unknown_linux_gnu), ("powerpc-unknown-linux-gnuspe", powerpc_unknown_linux_gnuspe), ("powerpc-unknown-linux-musl", powerpc_unknown_linux_musl), + ("powerpc-unknown-linux-muslspe", powerpc_unknown_linux_muslspe), ("powerpc64-ibm-aix", powerpc64_ibm_aix), ("powerpc64-unknown-linux-gnu", powerpc64_unknown_linux_gnu), ("powerpc64-unknown-linux-musl", powerpc64_unknown_linux_musl), @@ -1749,6 +1750,9 @@ supported_targets! { ("x86_64-unikraft-linux-musl", x86_64_unikraft_linux_musl), + ("armv7-unknown-trusty", armv7_unknown_trusty), + ("aarch64-unknown-trusty", aarch64_unknown_trusty), + ("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf), ("riscv32im-risc0-zkvm-elf", riscv32im_risc0_zkvm_elf), ("riscv32im-unknown-none-elf", riscv32im_unknown_none_elf), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs index 85c40ec60c4..32c2367d5bf 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs @@ -10,7 +10,7 @@ pub fn target() -> Target { llvm_target: mac_catalyst_llvm_target(arch).into(), metadata: crate::spec::TargetMetadata { description: Some("Apple Catalyst on ARM64".into()), - tier: Some(3), + tier: Some(2), host_tools: Some(false), std: Some(true), }, diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_trusty.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_trusty.rs new file mode 100644 index 00000000000..9fd7c246498 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_trusty.rs @@ -0,0 +1,34 @@ +// Trusty OS target for AArch64. + +use crate::spec::{LinkSelfContainedDefault, PanicStrategy, RelroLevel, Target, TargetOptions}; + +pub fn target() -> Target { + Target { + llvm_target: "aarch64-unknown-unknown-musl".into(), + metadata: crate::spec::TargetMetadata { + description: Some("ARM64 Trusty".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(false), + }, + pointer_width: 64, + data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + arch: "aarch64".into(), + options: TargetOptions { + features: "+neon,+fp-armv8,+reserve-x18".into(), + executables: true, + max_atomic_width: Some(128), + panic_strategy: PanicStrategy::Abort, + os: "trusty".into(), + position_independent_executables: true, + static_position_independent_executables: true, + crt_static_default: true, + crt_static_respected: true, + dynamic_linking: false, + link_self_contained: LinkSelfContainedDefault::InferredForMusl, + relro_level: RelroLevel::Full, + mcount: "\u{1}_mcount".into(), + ..Default::default() + }, + } +} diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_trusty.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_trusty.rs new file mode 100644 index 00000000000..889cc201569 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_trusty.rs @@ -0,0 +1,37 @@ +use crate::spec::{LinkSelfContainedDefault, PanicStrategy, RelroLevel, Target, TargetOptions}; + +pub fn target() -> Target { + Target { + // It's important we use "gnueabi" and not "musleabi" here. LLVM uses it + // to determine the calling convention and float ABI, and it doesn't + // support the "musleabi" value. + llvm_target: "armv7-unknown-unknown-gnueabi".into(), + metadata: crate::spec::TargetMetadata { + description: Some("Armv7-A Trusty".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(false), + }, + pointer_width: 32, + data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), + arch: "arm".into(), + options: TargetOptions { + abi: "eabi".into(), + features: "+v7,+thumb2,+soft-float,-neon".into(), + max_atomic_width: Some(64), + mcount: "\u{1}mcount".into(), + os: "trusty".into(), + link_self_contained: LinkSelfContainedDefault::InferredForMusl, + dynamic_linking: false, + executables: true, + crt_static_default: true, + crt_static_respected: true, + relro_level: RelroLevel::Full, + panic_strategy: PanicStrategy::Abort, + position_independent_executables: true, + static_position_independent_executables: true, + + ..Default::default() + }, + } +} diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs new file mode 100644 index 00000000000..d19015729ec --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs @@ -0,0 +1,28 @@ +use crate::abi::Endian; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; + +pub fn target() -> Target { + let mut base = base::linux_musl::opts(); + base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-mspe"]); + base.max_atomic_width = Some(32); + base.stack_probes = StackProbeType::Inline; + + Target { + llvm_target: "powerpc-unknown-linux-muslspe".into(), + metadata: crate::spec::TargetMetadata { + description: Some("PowerPC SPE Linux with musl".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(true), + }, + pointer_width: 32, + data_layout: "E-m:e-p:32:32-Fn32-i64:64-n32".into(), + arch: "powerpc".into(), + options: TargetOptions { + abi: "spe".into(), + endian: Endian::Big, + mcount: "_mcount".into(), + ..base + }, + } +} diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs index d3ba17cf027..c23a20ff084 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs @@ -10,7 +10,7 @@ pub fn target() -> Target { llvm_target: mac_catalyst_llvm_target(arch).into(), metadata: crate::spec::TargetMetadata { description: Some("Apple Catalyst on x86_64".into()), - tier: Some(3), + tier: Some(2), host_tools: Some(false), std: Some(true), }, diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index da66ba270b3..8319cb880cc 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -99,6 +99,8 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("bti", Stable, &[]), // FEAT_CRC ("crc", Stable, &[]), + // FEAT_CSSC + ("cssc", Unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_DIT ("dit", Stable, &[]), // FEAT_DotProd @@ -107,21 +109,37 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("dpb", Stable, &[]), // FEAT_DPB2 ("dpb2", Stable, &["dpb"]), + // FEAT_ECV + ("ecv", Unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_F32MM ("f32mm", Stable, &["sve"]), // FEAT_F64MM ("f64mm", Stable, &["sve"]), + // FEAT_FAMINMAX + ("faminmax", Unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_FCMA ("fcma", Stable, &["neon"]), // FEAT_FHM ("fhm", Stable, &["fp16"]), // FEAT_FLAGM ("flagm", Stable, &[]), + // FEAT_FLAGM2 + ("flagm2", Unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_FP16 // Rust ties FP and Neon: https://github.com/rust-lang/rust/pull/91608 ("fp16", Stable, &["neon"]), + // FEAT_FP8 + ("fp8", Unstable(sym::aarch64_unstable_target_feature), &["faminmax", "lut", "bf16"]), + // FEAT_FP8DOT2 + ("fp8dot2", Unstable(sym::aarch64_unstable_target_feature), &["fp8dot4"]), + // FEAT_FP8DOT4 + ("fp8dot4", Unstable(sym::aarch64_unstable_target_feature), &["fp8fma"]), + // FEAT_FP8FMA + ("fp8fma", Unstable(sym::aarch64_unstable_target_feature), &["fp8"]), // FEAT_FRINTTS ("frintts", Stable, &[]), + // FEAT_HBC + ("hbc", Unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_I8MM ("i8mm", Stable, &[]), // FEAT_JSCVT @@ -131,6 +149,14 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("lor", Stable, &[]), // FEAT_LSE ("lse", Stable, &[]), + // FEAT_LSE128 + ("lse128", Unstable(sym::aarch64_unstable_target_feature), &["lse"]), + // FEAT_LSE2 + ("lse2", Unstable(sym::aarch64_unstable_target_feature), &[]), + // FEAT_LUT + ("lut", Unstable(sym::aarch64_unstable_target_feature), &[]), + // FEAT_MOPS + ("mops", Unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_MTE & FEAT_MTE2 ("mte", Stable, &[]), // FEAT_AdvSimd & FEAT_FP @@ -143,14 +169,16 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("pan", Stable, &[]), // FEAT_PMUv3 ("pmuv3", Stable, &[]), - // FEAT_RAND + // FEAT_RNG ("rand", Stable, &[]), // FEAT_RAS & FEAT_RASv1p1 ("ras", Stable, &[]), - // FEAT_RCPC + // FEAT_LRCPC ("rcpc", Stable, &[]), - // FEAT_RCPC2 + // FEAT_LRCPC2 ("rcpc2", Stable, &["rcpc"]), + // FEAT_LRCPC3 + ("rcpc3", Unstable(sym::aarch64_unstable_target_feature), &["rcpc2"]), // FEAT_RDM ("rdm", Stable, &["neon"]), // FEAT_SB @@ -161,10 +189,36 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("sha3", Stable, &["sha2"]), // FEAT_SM3 & FEAT_SM4 ("sm4", Stable, &["neon"]), + // FEAT_SME + ("sme", Unstable(sym::aarch64_unstable_target_feature), &["bf16"]), + // FEAT_SME_F16F16 + ("sme-f16f16", Unstable(sym::aarch64_unstable_target_feature), &["sme2"]), + // FEAT_SME_F64F64 + ("sme-f64f64", Unstable(sym::aarch64_unstable_target_feature), &["sme"]), + // FEAT_SME_F8F16 + ("sme-f8f16", Unstable(sym::aarch64_unstable_target_feature), &["sme-f8f32"]), + // FEAT_SME_F8F32 + ("sme-f8f32", Unstable(sym::aarch64_unstable_target_feature), &["sme2", "fp8"]), + // FEAT_SME_FA64 + ("sme-fa64", Unstable(sym::aarch64_unstable_target_feature), &["sme", "sve2"]), + // FEAT_SME_I16I64 + ("sme-i16i64", Unstable(sym::aarch64_unstable_target_feature), &["sme"]), + // FEAT_SME_LUTv2 + ("sme-lutv2", Unstable(sym::aarch64_unstable_target_feature), &[]), + // FEAT_SME2 + ("sme2", Unstable(sym::aarch64_unstable_target_feature), &["sme"]), + // FEAT_SME2p1 + ("sme2p1", Unstable(sym::aarch64_unstable_target_feature), &["sme2"]), // FEAT_SPE ("spe", Stable, &[]), // FEAT_SSBS & FEAT_SSBS2 ("ssbs", Stable, &[]), + // FEAT_SSVE_FP8FDOT2 + ("ssve-fp8dot2", Unstable(sym::aarch64_unstable_target_feature), &["ssve-fp8dot4"]), + // FEAT_SSVE_FP8FDOT4 + ("ssve-fp8dot4", Unstable(sym::aarch64_unstable_target_feature), &["ssve-fp8fma"]), + // FEAT_SSVE_FP8FMA + ("ssve-fp8fma", Unstable(sym::aarch64_unstable_target_feature), &["sme2", "fp8"]), // FEAT_SVE // It was decided that SVE requires Neon: https://github.com/rust-lang/rust/pull/91608 // @@ -173,9 +227,11 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // // "For backwards compatibility, Neon and VFP are required in the latest architectures." ("sve", Stable, &["neon"]), + // FEAT_SVE_B16B16 (SVE or SME Instructions) + ("sve-b16b16", Unstable(sym::aarch64_unstable_target_feature), &["bf16"]), // FEAT_SVE2 ("sve2", Stable, &["sve"]), - // FEAT_SVE2_AES + // FEAT_SVE_AES & FEAT_SVE_PMULL128 ("sve2-aes", Stable, &["sve2", "aes"]), // FEAT_SVE2_BitPerm ("sve2-bitperm", Stable, &["sve2"]), @@ -183,6 +239,8 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("sve2-sha3", Stable, &["sve2", "sha3"]), // FEAT_SVE2_SM4 ("sve2-sm4", Stable, &["sve2", "sm4"]), + // FEAT_SVE2p1 + ("sve2p1", Unstable(sym::aarch64_unstable_target_feature), &["sve2"]), // FEAT_TME ("tme", Stable, &[]), ( @@ -199,9 +257,19 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("v8.4a", Unstable(sym::aarch64_ver_target_feature), &["v8.3a", "dotprod", "dit", "flagm"]), ("v8.5a", Unstable(sym::aarch64_ver_target_feature), &["v8.4a", "ssbs", "sb", "dpb2", "bti"]), ("v8.6a", Unstable(sym::aarch64_ver_target_feature), &["v8.5a", "bf16", "i8mm"]), - ("v8.7a", Unstable(sym::aarch64_ver_target_feature), &[]), + ("v8.7a", Unstable(sym::aarch64_ver_target_feature), &["v8.6a", "wfxt"]), + ("v8.8a", Unstable(sym::aarch64_ver_target_feature), &["v8.7a", "hbc", "mops"]), + ("v8.9a", Unstable(sym::aarch64_ver_target_feature), &["v8.8a", "cssc"]), + ("v9.1a", Unstable(sym::aarch64_ver_target_feature), &["v9a", "v8.6a"]), + ("v9.2a", Unstable(sym::aarch64_ver_target_feature), &["v9.1a", "v8.7a"]), + ("v9.3a", Unstable(sym::aarch64_ver_target_feature), &["v9.2a", "v8.8a"]), + ("v9.4a", Unstable(sym::aarch64_ver_target_feature), &["v9.3a", "v8.9a"]), + ("v9.5a", Unstable(sym::aarch64_ver_target_feature), &["v9.4a"]), + ("v9a", Unstable(sym::aarch64_ver_target_feature), &["v8.5a", "sve2"]), // FEAT_VHE ("vh", Stable, &[]), + // FEAT_WFxT + ("wfxt", Unstable(sym::aarch64_unstable_target_feature), &[]), // tidy-alphabetical-end ]; diff --git a/compiler/rustc_trait_selection/messages.ftl b/compiler/rustc_trait_selection/messages.ftl index 137850f31d3..3ddd23924b5 100644 --- a/compiler/rustc_trait_selection/messages.ftl +++ b/compiler/rustc_trait_selection/messages.ftl @@ -446,6 +446,8 @@ trait_selection_type_annotations_needed = {$source_kind -> } .label = type must be known at this point +trait_selection_type_annotations_needed_error_time = this is an inference error on crate `time` caused by an API change in Rust 1.80.0; update `time` to version `>=0.3.35` by calling `cargo update` + trait_selection_types_declared_different = these two types are declared with different lifetimes... trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated} diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index 8ccb2a8483a..5193333be8e 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -1087,9 +1087,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { values } - (ty::FnDef(did1, args1), ty::FnPtr(sig2)) => { + (ty::FnDef(did1, args1), ty::FnPtr(sig_tys2, hdr2)) => { let sig1 = self.tcx.fn_sig(*did1).instantiate(self.tcx, args1); - let mut values = self.cmp_fn_sig(&sig1, sig2); + let mut values = self.cmp_fn_sig(&sig1, &sig_tys2.with(*hdr2)); values.0.push_highlighted(format!( " {{{}}}", self.tcx.def_path_str_with_args(*did1, args1) @@ -1097,16 +1097,18 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { values } - (ty::FnPtr(sig1), ty::FnDef(did2, args2)) => { + (ty::FnPtr(sig_tys1, hdr1), ty::FnDef(did2, args2)) => { let sig2 = self.tcx.fn_sig(*did2).instantiate(self.tcx, args2); - let mut values = self.cmp_fn_sig(sig1, &sig2); + let mut values = self.cmp_fn_sig(&sig_tys1.with(*hdr1), &sig2); values .1 .push_normal(format!(" {{{}}}", self.tcx.def_path_str_with_args(*did2, args2))); values } - (ty::FnPtr(sig1), ty::FnPtr(sig2)) => self.cmp_fn_sig(sig1, sig2), + (ty::FnPtr(sig_tys1, hdr1), ty::FnPtr(sig_tys2, hdr2)) => { + self.cmp_fn_sig(&sig_tys1.with(*hdr1), &sig_tys2.with(*hdr2)) + } _ => { let mut strs = (DiagStyledString::new(), DiagStyledString::new()); diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs index f6dd7898fb2..53f013ac153 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs @@ -6,7 +6,7 @@ use rustc_errors::codes::*; use rustc_errors::{Diag, IntoDiagArg}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Namespace, Res}; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{Body, Closure, Expr, ExprKind, FnRetTy, HirId, LetStmt, LocalSource}; use rustc_middle::bug; @@ -18,7 +18,7 @@ use rustc_middle::ty::{ TypeFoldable, TypeFolder, TypeSuperFoldable, TypeckResults, }; use rustc_span::symbol::{sym, Ident}; -use rustc_span::{BytePos, Span, DUMMY_SP}; +use rustc_span::{BytePos, FileName, Span, DUMMY_SP}; use crate::error_reporting::TypeErrCtxt; use crate::errors::{ @@ -382,8 +382,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { infer_subdiags, multi_suggestions, bad_label, - was_written: None, + was_written: false, path: Default::default(), + time_version: false, }), TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl { span, @@ -393,7 +394,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { infer_subdiags, multi_suggestions, bad_label, - was_written: None, + was_written: false, path: Default::default(), }), TypeAnnotationNeeded::E0284 => self.dcx().create_err(AmbiguousReturn { @@ -404,7 +405,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { infer_subdiags, multi_suggestions, bad_label, - was_written: None, + was_written: false, path: Default::default(), }), } @@ -577,6 +578,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } } + + let time_version = + self.detect_old_time_crate_version(failure_span, &kind, &mut infer_subdiags); + match error_code { TypeAnnotationNeeded::E0282 => self.dcx().create_err(AnnotationRequired { span, @@ -586,8 +591,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { infer_subdiags, multi_suggestions, bad_label: None, - was_written: path.as_ref().map(|_| ()), + was_written: path.is_some(), path: path.unwrap_or_default(), + time_version, }), TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl { span, @@ -597,7 +603,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { infer_subdiags, multi_suggestions, bad_label: None, - was_written: path.as_ref().map(|_| ()), + was_written: path.is_some(), path: path.unwrap_or_default(), }), TypeAnnotationNeeded::E0284 => self.dcx().create_err(AmbiguousReturn { @@ -608,11 +614,47 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { infer_subdiags, multi_suggestions, bad_label: None, - was_written: path.as_ref().map(|_| ()), + was_written: path.is_some(), path: path.unwrap_or_default(), }), } } + + /// Detect the inference regression on crate `time` <= 0.3.35 and emit a more targeted error. + /// + // FIXME: we should figure out a more generic version of doing this, ideally in cargo itself. + fn detect_old_time_crate_version( + &self, + span: Option, + kind: &InferSourceKind<'_>, + // We will clear the non-actionable suggestion from the error to reduce noise. + infer_subdiags: &mut Vec>, + ) -> bool { + // FIXME(#129461): We are time-boxing this code in the compiler. It'll start failing + // compilation once we promote 1.89 to beta, which will happen in 9 months from now. + #[cfg(not(version("1.89")))] + const fn version_check() {} + #[cfg(version("1.89"))] + const fn version_check() { + panic!("remove this check as presumably the ecosystem has moved from needing it"); + } + const { version_check() }; + // Only relevant when building the `time` crate. + if self.infcx.tcx.crate_name(LOCAL_CRATE) == sym::time + && let Some(span) = span + && let InferSourceKind::LetBinding { pattern_name, .. } = kind + && let Some(name) = pattern_name + && name.as_str() == "items" + && let FileName::Real(file) = self.infcx.tcx.sess.source_map().span_to_filename(span) + { + let path = file.local_path_if_available().to_string_lossy(); + if path.contains("format_description") && path.contains("parse") { + infer_subdiags.clear(); + return true; + } + } + false + } } #[derive(Debug)] diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs index 3f35391be13..cd61747917a 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs @@ -101,7 +101,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { // region at the right depth with the same index (Some(rbv::ResolvedArg::EarlyBound(id)), ty::BrNamed(def_id, _)) => { debug!("EarlyBound id={:?} def_id={:?}", id, def_id); - if id == def_id { + if id.to_def_id() == def_id { return ControlFlow::Break(arg); } } @@ -118,7 +118,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { debruijn_index ); debug!("LateBound id={:?} def_id={:?}", id, def_id); - if debruijn_index == self.current_index && id == def_id { + if debruijn_index == self.current_index && id.to_def_id() == def_id { return ControlFlow::Break(arg); } } @@ -192,7 +192,7 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> { // the lifetime of the TyPath! (Some(rbv::ResolvedArg::EarlyBound(id)), ty::BrNamed(def_id, _)) => { debug!("EarlyBound id={:?} def_id={:?}", id, def_id); - if id == def_id { + if id.to_def_id() == def_id { return ControlFlow::Break(()); } } @@ -201,7 +201,7 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> { debug!("FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}", debruijn_index,); debug!("id={:?}", id); debug!("def_id={:?}", def_id); - if debruijn_index == self.current_index && id == def_id { + if debruijn_index == self.current_index && id.to_def_id() == def_id { return ControlFlow::Break(()); } } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs index 9c772f42cca..f2a7da707b8 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs @@ -11,7 +11,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { pub(super) fn try_report_placeholder_relation(&self) -> Option> { match &self.error { Some(RegionResolutionError::ConcreteFailure( - SubregionOrigin::RelateRegionParamBound(span), + SubregionOrigin::RelateRegionParamBound(span, _), Region(Interned( RePlaceholder(ty::Placeholder { bound: ty::BoundRegion { kind: sub_name, .. }, diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note.rs index 04e1be22a4d..600da730845 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/note.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note.rs @@ -52,7 +52,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .add_to_diag(err); } } - infer::RelateRegionParamBound(span) => { + infer::RelateRegionParamBound(span, _) => { RegionOriginNote::Plain { span, msg: fluent::infer_relate_region_param_bound } .add_to_diag(err); } @@ -199,7 +199,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { note, }) } - infer::RelateRegionParamBound(span) => { + infer::RelateRegionParamBound(span, _) => { let param_instantiated = note_and_explain::RegionExplanation::new( self.tcx, generic_param_scope, diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs index 864510bb650..05c79170902 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs @@ -4,6 +4,7 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::error::{ExpectedFound, TypeError}; +use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; use rustc_middle::ty::print::{FmtPrinter, Printer}; use rustc_middle::ty::{self, suggest_constraining_type_param, Ty}; use rustc_span::def_id::DefId; @@ -313,11 +314,15 @@ impl Trait for X { (ty::Dynamic(t, _, ty::DynKind::Dyn), _) if let Some(def_id) = t.principal_def_id() => { - let mut impl_def_ids = vec![]; + let mut has_matching_impl = false; tcx.for_each_relevant_impl(def_id, values.found, |did| { - impl_def_ids.push(did) + if DeepRejectCtxt::new(tcx, TreatParams::ForLookup) + .types_may_unify(values.found, tcx.type_of(did).skip_binder()) + { + has_matching_impl = true; + } }); - if let [_] = &impl_def_ids[..] { + if has_matching_impl { let trait_name = tcx.item_name(def_id); diag.help(format!( "`{}` implements `{trait_name}` so you could box the found value \ @@ -330,11 +335,15 @@ impl Trait for X { (_, ty::Dynamic(t, _, ty::DynKind::Dyn)) if let Some(def_id) = t.principal_def_id() => { - let mut impl_def_ids = vec![]; + let mut has_matching_impl = false; tcx.for_each_relevant_impl(def_id, values.expected, |did| { - impl_def_ids.push(did) + if DeepRejectCtxt::new(tcx, TreatParams::ForLookup) + .types_may_unify(values.expected, tcx.type_of(did).skip_binder()) + { + has_matching_impl = true; + } }); - if let [_] = &impl_def_ids[..] { + if has_matching_impl { let trait_name = tcx.item_name(def_id); diag.help(format!( "`{}` implements `{trait_name}` so you could change the expected \ @@ -346,11 +355,15 @@ impl Trait for X { (ty::Dynamic(t, _, ty::DynKind::DynStar), _) if let Some(def_id) = t.principal_def_id() => { - let mut impl_def_ids = vec![]; + let mut has_matching_impl = false; tcx.for_each_relevant_impl(def_id, values.found, |did| { - impl_def_ids.push(did) + if DeepRejectCtxt::new(tcx, TreatParams::ForLookup) + .types_may_unify(values.found, tcx.type_of(did).skip_binder()) + { + has_matching_impl = true; + } }); - if let [_] = &impl_def_ids[..] { + if has_matching_impl { let trait_name = tcx.item_name(def_id); diag.help(format!( "`{}` implements `{trait_name}`, `#[feature(dyn_star)]` is likely \ @@ -441,9 +454,9 @@ impl Trait for X { } } } - (ty::FnPtr(sig), ty::FnDef(def_id, _)) - | (ty::FnDef(def_id, _), ty::FnPtr(sig)) => { - if tcx.fn_sig(def_id).skip_binder().safety() < sig.safety() { + (ty::FnPtr(_, hdr), ty::FnDef(def_id, _)) + | (ty::FnDef(def_id, _), ty::FnPtr(_, hdr)) => { + if tcx.fn_sig(def_id).skip_binder().safety() < hdr.safety { diag.note( "unsafe functions cannot be coerced into safe function pointers", ); diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index 3cee8ff5f4c..ada44b632d4 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -17,8 +17,8 @@ use rustc_span::{BytePos, ErrorGuaranteed, Span, Symbol}; use rustc_type_ir::Upcast as _; use super::nice_region_error::find_anon_type; -use super::{nice_region_error, ObligationCauseAsDiagArg}; -use crate::error_reporting::infer::ObligationCauseExt as _; +use super::ObligationCauseAsDiagArg; +use crate::error_reporting::infer::ObligationCauseExt; use crate::error_reporting::TypeErrCtxt; use crate::errors::{ self, note_and_explain, FulfillReqLifetime, LfBoundNotSatisfied, OutlivesBound, @@ -257,7 +257,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .add_to_diag(err); } } - infer::RelateRegionParamBound(span) => { + infer::RelateRegionParamBound(span, _) => { RegionOriginNote::Plain { span, msg: fluent::trait_selection_relate_region_param_bound, @@ -410,7 +410,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { note, }) } - infer::RelateRegionParamBound(span) => { + infer::RelateRegionParamBound(span, ty) => { let param_instantiated = note_and_explain::RegionExplanation::new( self.tcx, generic_param_scope, @@ -419,11 +419,31 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { note_and_explain::PrefixKind::LfParamInstantiatedWith, note_and_explain::SuffixKind::Empty, ); + let mut alt_span = None; + if let Some(ty) = ty + && sub.is_static() + && let ty::Dynamic(preds, _, ty::DynKind::Dyn) = ty.kind() + && let Some(def_id) = preds.principal_def_id() + { + for (clause, span) in + self.tcx.predicates_of(def_id).instantiate_identity(self.tcx) + { + if let ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(a, b)) = + clause.kind().skip_binder() + && let ty::Param(param) = a.kind() + && param.name == kw::SelfUpper + && b.is_static() + { + // Point at explicit `'static` bound on the trait (`trait T: 'static`). + alt_span = Some(span); + } + } + } let param_must_outlive = note_and_explain::RegionExplanation::new( self.tcx, generic_param_scope, sub, - None, + alt_span, note_and_explain::PrefixKind::LfParamMustOutlive, note_and_explain::SuffixKind::Empty, ); @@ -1079,16 +1099,8 @@ fn msg_span_from_named_region<'tcx>( ) -> (String, Option) { match *region { ty::ReEarlyParam(br) => { - let scope = tcx - .parent(tcx.generics_of(generic_param_scope).region_param(br, tcx).def_id) - .expect_local(); - let span = if let Some(param) = - tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(br.name)) - { - param.span - } else { - tcx.def_span(scope) - }; + let param_def_id = tcx.generics_of(generic_param_scope).region_param(br, tcx).def_id; + let span = tcx.def_span(param_def_id); let text = if br.has_name() { format!("the lifetime `{}` as defined here", br.name) } else { @@ -1104,16 +1116,8 @@ fn msg_span_from_named_region<'tcx>( ("the anonymous lifetime defined here".to_string(), Some(ty.span)) } else { match fr.bound_region { - ty::BoundRegionKind::BrNamed(_, name) => { - let span = if let Some(param) = tcx - .hir() - .get_generics(generic_param_scope) - .and_then(|generics| generics.get_named(name)) - { - param.span - } else { - tcx.def_span(generic_param_scope) - }; + ty::BoundRegionKind::BrNamed(param_def_id, name) => { + let span = tcx.def_span(param_def_id); let text = if name == kw::UnderscoreLifetime { "the anonymous lifetime as defined here".to_string() } else { @@ -1212,22 +1216,8 @@ pub fn unexpected_hidden_region_diagnostic<'a, 'tcx>( hidden_region, "", ); - if let Some(reg_info) = tcx.is_suitable_region(generic_param_scope, hidden_region) { - if infcx.tcx.features().precise_capturing { - suggest_precise_capturing(tcx, opaque_ty_key.def_id, hidden_region, &mut err); - } else { - let fn_returns = tcx.return_type_impl_or_dyn_traits(reg_info.def_id); - nice_region_error::suggest_new_region_bound( - tcx, - &mut err, - fn_returns, - hidden_region.to_string(), - None, - format!("captures `{hidden_region}`"), - None, - Some(reg_info.def_id), - ) - } + if let Some(_) = tcx.is_suitable_region(generic_param_scope, hidden_region) { + suggest_precise_capturing(tcx, opaque_ty_key.def_id, hidden_region, &mut err); } } ty::RePlaceholder(_) => { diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs index ee159aa0b77..ba656493d46 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs @@ -382,9 +382,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { if !expected_inner.is_fn() || !found_inner.is_fn() { return; } - match (&expected_inner.kind(), &found_inner.kind()) { - (ty::FnPtr(sig), ty::FnDef(did, args)) => { - let expected_sig = &(self.normalize_fn_sig)(*sig); + match (expected_inner.kind(), found_inner.kind()) { + (ty::FnPtr(sig_tys, hdr), ty::FnDef(did, args)) => { + let sig = sig_tys.with(*hdr); + let expected_sig = &(self.normalize_fn_sig)(sig); let found_sig = &(self.normalize_fn_sig)(self.tcx.fn_sig(*did).instantiate(self.tcx, args)); @@ -402,11 +403,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { (false, true) => FunctionPointerSuggestion::RemoveRef { span, fn_name }, (true, true) => { diag.subdiagnostic(FnItemsAreDistinct); - FunctionPointerSuggestion::CastRef { span, fn_name, sig: *sig } + FunctionPointerSuggestion::CastRef { span, fn_name, sig } } (false, false) => { diag.subdiagnostic(FnItemsAreDistinct); - FunctionPointerSuggestion::Cast { span, fn_name, sig: *sig } + FunctionPointerSuggestion::Cast { span, fn_name, sig } } }; diag.subdiagnostic(sugg); @@ -449,10 +450,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { diag.subdiagnostic(sug); } - (ty::FnDef(did, args), ty::FnPtr(sig)) => { + (ty::FnDef(did, args), ty::FnPtr(sig_tys, hdr)) => { let expected_sig = &(self.normalize_fn_sig)(self.tcx.fn_sig(*did).instantiate(self.tcx, args)); - let found_sig = &(self.normalize_fn_sig)(*sig); + let found_sig = &(self.normalize_fn_sig)(sig_tys.with(*hdr)); if !self.same_type_modulo_infer(*found_sig, *expected_sig) { return; diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index f908d8a6870..def9d6e9a31 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -230,8 +230,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { post_message, ); - let (err_msg, safe_transmute_explanation) = if Some(main_trait_ref.def_id()) - == self.tcx.lang_items().transmute_trait() + let (err_msg, safe_transmute_explanation) = if self.tcx.is_lang_item(main_trait_ref.def_id(), LangItem::TransmuteTrait) { // Recompute the safe transmute reason and use that for the error reporting match self.get_safe_transmute_error_and_reason( @@ -375,7 +374,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let impl_candidates = self.find_similar_impl_candidates(leaf_trait_predicate); suggested = if let &[cand] = &impl_candidates[..] { let cand = cand.trait_ref; - if let (ty::FnPtr(_), ty::FnDef(..)) = + if let (ty::FnPtr(..), ty::FnDef(..)) = (cand.self_ty().kind(), main_trait_ref.self_ty().skip_binder().kind()) { err.span_suggestion( @@ -439,6 +438,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let is_target_feature_fn = if let ty::FnDef(def_id, _) = *leaf_trait_ref.skip_binder().self_ty().kind() { + // FIXME(struct_target_features): should a function that inherits + // target_features through arguments implement Fn traits? !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty() } else { false @@ -790,8 +791,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // is unimplemented is because async closures don't implement `Fn`/`FnMut` // if they have captures. if let Some(by_ref_captures) = by_ref_captures - && let ty::FnPtr(sig) = by_ref_captures.kind() - && !sig.skip_binder().output().is_unit() + && let ty::FnPtr(sig_tys, _) = by_ref_captures.kind() + && !sig_tys.skip_binder().output().is_unit() { let mut err = self.dcx().create_err(AsyncClosureNotFn { span: self.tcx.def_span(closure_def_id), @@ -1057,7 +1058,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { "`{ty}` is forbidden as the type of a const generic parameter", ) } - ty::FnPtr(_) => { + ty::FnPtr(..) => { struct_span_code_err!( self.dcx(), span, @@ -1669,7 +1670,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let name = self.tcx.crate_name(trait_def_id.krate); let spans: Vec<_> = [trait_def_id, found_type] .into_iter() - .filter_map(|def_id| self.tcx.extern_crate(def_id)) + .filter_map(|def_id| self.tcx.extern_crate(def_id.krate)) .map(|data| { let dependency = if data.dependency_of == LOCAL_CRATE { "direct dependency of the current crate".to_string() @@ -1690,11 +1691,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { err.highlighted_span_help( span, vec![ - StringPart::normal("you have ".to_string()), + StringPart::normal("there are ".to_string()), StringPart::highlighted("multiple different versions".to_string()), StringPart::normal(" of crate `".to_string()), StringPart::highlighted(format!("{name}")), - StringPart::normal("` in your dependency graph".to_string()), + StringPart::normal("` in the dependency graph".to_string()), ], ); let candidates = if impl_candidates.is_empty() { @@ -1836,10 +1837,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let &[cand] = &candidates[..] { let (desc, mention_castable) = match (cand.self_ty().kind(), trait_ref.self_ty().skip_binder().kind()) { - (ty::FnPtr(_), ty::FnDef(..)) => { + (ty::FnPtr(..), ty::FnDef(..)) => { (" implemented for fn pointer `", ", cast using `as`") } - (ty::FnPtr(_), _) => (" implemented for fn pointer `", ""), + (ty::FnPtr(..), _) => (" implemented for fn pointer `", ""), _ => (" implemented for `", ""), }; err.highlighted_help(vec![ @@ -2730,6 +2731,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(ref sig, _), .. }) | Node::TraitItem(&hir::TraitItem { kind: hir::TraitItemKind::Fn(ref sig, _), .. + }) + | Node::ForeignItem(&hir::ForeignItem { + kind: hir::ForeignItemKind::Fn(ref sig, _, _), + .. }) => ( sig.span, None, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 9269177eb50..3cb95294fb6 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -1077,10 +1077,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let Some((def_id_or_name, output, inputs)) = (self.autoderef_steps)(found).into_iter().find_map(|(found, _)| { match *found.kind() { - ty::FnPtr(fn_sig) => Some(( + ty::FnPtr(sig_tys, _) => Some(( DefIdOrName::Name("function pointer"), - fn_sig.output(), - fn_sig.inputs(), + sig_tys.output(), + sig_tys.inputs(), )), ty::FnDef(def_id, _) => { let fn_sig = found.fn_sig(self.tcx); @@ -1977,20 +1977,22 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let ObligationCauseCode::FunctionArg { arg_hir_id, .. } = cause else { return; }; - let ty::FnPtr(expected) = expected.kind() else { + let ty::FnPtr(sig_tys, hdr) = expected.kind() else { return; }; - let ty::FnPtr(found) = found.kind() else { + let expected = sig_tys.with(*hdr); + let ty::FnPtr(sig_tys, hdr) = found.kind() else { return; }; + let found = sig_tys.with(*hdr); let Node::Expr(arg) = self.tcx.hir_node(*arg_hir_id) else { return; }; let hir::ExprKind::Path(path) = arg.kind else { return; }; - let expected_inputs = self.tcx.instantiate_bound_regions_with_erased(*expected).inputs(); - let found_inputs = self.tcx.instantiate_bound_regions_with_erased(*found).inputs(); + let expected_inputs = self.tcx.instantiate_bound_regions_with_erased(expected).inputs(); + let found_inputs = self.tcx.instantiate_bound_regions_with_erased(found).inputs(); let both_tys = expected_inputs.iter().copied().zip(found_inputs.iter().copied()); let arg_expr = |infcx: &InferCtxt<'tcx>, name, expected: Ty<'tcx>, found: Ty<'tcx>| { @@ -2725,6 +2727,20 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let tcx = self.tcx; let predicate = predicate.upcast(tcx); + let suggest_remove_deref = |err: &mut Diag<'_, G>, expr: &hir::Expr<'_>| { + if let Some(pred) = predicate.as_trait_clause() + && tcx.is_lang_item(pred.def_id(), LangItem::Sized) + && let hir::ExprKind::Unary(hir::UnOp::Deref, inner) = expr.kind + { + err.span_suggestion_verbose( + expr.span.until(inner.span), + "references are always `Sized`, even if they point to unsized data; consider \ + not dereferencing the expression", + String::new(), + Applicability::MaybeIncorrect, + ); + } + }; match *cause_code { ObligationCauseCode::ExprAssignable | ObligationCauseCode::MatchExpressionArm { .. } @@ -2771,6 +2787,19 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { | ObligationCauseCode::WhereClauseInExpr(item_def_id, span, ..) if !span.is_dummy() => { + if let ObligationCauseCode::WhereClauseInExpr(_, _, hir_id, pos) = &cause_code { + if let Node::Expr(expr) = tcx.parent_hir_node(*hir_id) + && let hir::ExprKind::Call(_, args) = expr.kind + && let Some(expr) = args.get(*pos) + { + suggest_remove_deref(err, &expr); + } else if let Node::Expr(expr) = self.tcx.hir_node(*hir_id) + && let hir::ExprKind::MethodCall(_, _, args, _) = expr.kind + && let Some(expr) = args.get(*pos) + { + suggest_remove_deref(err, &expr); + } + } let item_name = tcx.def_path_str(item_def_id); let short_item_name = with_forced_trimmed_paths!(tcx.def_path_str(item_def_id)); let mut multispan = MultiSpan::from(span); @@ -2829,7 +2858,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // Do not suggest relaxing if there is an explicit `Sized` obligation. && !bounds.iter() .filter_map(|bound| bound.trait_ref()) - .any(|tr| tr.trait_def_id() == tcx.lang_items().sized_trait()) + .any(|tr| tr.trait_def_id().is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::Sized))) { let (span, separator) = if let [.., last] = bounds { (last.span().shrink_to_hi(), " +") @@ -2968,6 +2997,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { )); err.downgrade_to_delayed_bug(); } + let mut local = true; match tcx.parent_hir_node(hir_id) { Node::LetStmt(hir::LetStmt { ty: Some(ty), .. }) => { err.span_suggestion_verbose( @@ -2976,7 +3006,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { "&", Applicability::MachineApplicable, ); - err.note("all local variables must have a statically known size"); } Node::LetStmt(hir::LetStmt { init: Some(hir::Expr { kind: hir::ExprKind::Index(..), span, .. }), @@ -2991,7 +3020,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { "&", Applicability::MachineApplicable, ); - err.note("all local variables must have a statically known size"); + } + Node::LetStmt(hir::LetStmt { init: Some(expr), .. }) => { + // When encountering an assignment of an unsized trait, like `let x = *"";`, + // we check if the RHS is a deref operation, to suggest removing it. + suggest_remove_deref(err, &expr); } Node::Param(param) => { err.span_suggestion_verbose( @@ -3001,10 +3034,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { "&", Applicability::MachineApplicable, ); + local = false; } - _ => { - err.note("all local variables must have a statically known size"); - } + _ => {} + } + if local { + err.note("all local variables must have a statically known size"); } if !tcx.features().unsized_locals { err.help("unsized locals are gated as an unstable feature"); @@ -3527,14 +3562,16 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ); } ObligationCauseCode::OpaqueReturnType(expr_info) => { - if let Some((expr_ty, expr_span)) = expr_info { + if let Some((expr_ty, hir_id)) = expr_info { let expr_ty = self.tcx.short_ty_string(expr_ty, &mut long_ty_file); + let expr = self.infcx.tcx.hir().expect_expr(hir_id); err.span_label( - expr_span, + expr.span, with_forced_trimmed_paths!(format!( "return type was inferred to be `{expr_ty}` here", )), ); + suggest_remove_deref(err, &expr); } } } @@ -4608,6 +4645,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }) } + // For E0277 when use `?` operator, suggest adding + // a suitable return type in `FnSig`, and a default + // return value at the end of the function's body. pub(super) fn suggest_add_result_as_return_type( &self, obligation: &PredicateObligation<'tcx>, @@ -4618,26 +4658,59 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { return; } + // Only suggest for local function and associated method, + // because this suggest adding both return type in + // the `FnSig` and a default return value in the body, so it + // is not suitable for foreign function without a local body, + // and neighter for trait method which may be also implemented + // in other place, so shouldn't change it's FnSig. + fn choose_suggest_items<'tcx, 'hir>( + tcx: TyCtxt<'tcx>, + node: hir::Node<'hir>, + ) -> Option<(&'hir hir::FnDecl<'hir>, hir::BodyId)> { + match node { + hir::Node::Item(item) if let hir::ItemKind::Fn(sig, _, body_id) = item.kind => { + Some((sig.decl, body_id)) + } + hir::Node::ImplItem(item) + if let hir::ImplItemKind::Fn(sig, body_id) = item.kind => + { + let parent = tcx.parent_hir_node(item.hir_id()); + if let hir::Node::Item(item) = parent + && let hir::ItemKind::Impl(imp) = item.kind + && imp.of_trait.is_none() + { + return Some((sig.decl, body_id)); + } + None + } + _ => None, + } + } + let node = self.tcx.hir_node_by_def_id(obligation.cause.body_id); - if let hir::Node::Item(item) = node - && let hir::ItemKind::Fn(sig, _, body_id) = item.kind - && let hir::FnRetTy::DefaultReturn(ret_span) = sig.decl.output + if let Some((fn_decl, body_id)) = choose_suggest_items(self.tcx, node) + && let hir::FnRetTy::DefaultReturn(ret_span) = fn_decl.output && self.tcx.is_diagnostic_item(sym::FromResidual, trait_pred.def_id()) && trait_pred.skip_binder().trait_ref.args.type_at(0).is_unit() && let ty::Adt(def, _) = trait_pred.skip_binder().trait_ref.args.type_at(1).kind() && self.tcx.is_diagnostic_item(sym::Result, def.did()) { - let body = self.tcx.hir().body(body_id); let mut sugg_spans = vec![(ret_span, " -> Result<(), Box>".to_string())]; - + let body = self.tcx.hir().body(body_id); if let hir::ExprKind::Block(b, _) = body.value.kind && b.expr.is_none() { + // The span of '}' in the end of block. + let span = self.tcx.sess.source_map().end_point(b.span); sugg_spans.push(( - // The span will point to the closing curly brace `}` of the block. - b.span.shrink_to_hi().with_lo(b.span.hi() - BytePos(1)), - "\n Ok(())\n}".to_string(), + span.shrink_to_lo(), + format!( + "{}{}", + " Ok(())\n", + self.tcx.sess.source_map().indentation_before(span).unwrap_or_default(), + ), )); } err.multipart_suggestion_verbose( @@ -4790,13 +4863,13 @@ fn hint_missing_borrow<'tcx>( } let found_args = match found.kind() { - ty::FnPtr(f) => infcx.enter_forall(*f, |f| f.inputs().iter()), + ty::FnPtr(sig_tys, _) => infcx.enter_forall(*sig_tys, |sig_tys| sig_tys.inputs().iter()), kind => { span_bug!(span, "found was converted to a FnPtr above but is now {:?}", kind) } }; let expected_args = match expected.kind() { - ty::FnPtr(f) => infcx.enter_forall(*f, |f| f.inputs().iter()), + ty::FnPtr(sig_tys, _) => infcx.enter_forall(*sig_tys, |sig_tys| sig_tys.inputs().iter()), kind => { span_bug!(span, "expected was converted to a FnPtr above but is now {:?}", kind) } diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 78f1f7d9b9b..ebaec0b9059 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -203,8 +203,10 @@ pub struct AnnotationRequired<'a> { #[subdiagnostic] pub multi_suggestions: Vec>, #[note(trait_selection_full_type_written)] - pub was_written: Option<()>, + pub was_written: bool, pub path: PathBuf, + #[note(trait_selection_type_annotations_needed_error_time)] + pub time_version: bool, } // Copy of `AnnotationRequired` for E0283 @@ -224,7 +226,7 @@ pub struct AmbiguousImpl<'a> { #[subdiagnostic] pub multi_suggestions: Vec>, #[note(trait_selection_full_type_written)] - pub was_written: Option<()>, + pub was_written: bool, pub path: PathBuf, } @@ -245,7 +247,7 @@ pub struct AmbiguousReturn<'a> { #[subdiagnostic] pub multi_suggestions: Vec>, #[note(trait_selection_full_type_written)] - pub was_written: Option<()>, + pub was_written: bool, pub path: PathBuf, } diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 1bd66266936..c98d6c5f1df 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -19,6 +19,7 @@ #![feature(assert_matches)] #![feature(associated_type_defaults)] #![feature(box_patterns)] +#![feature(cfg_version)] #![feature(control_flow_enum)] #![feature(extract_if)] #![feature(if_let_guard)] diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index 1a459aa484f..51dda25d8ad 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -334,13 +334,9 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { pub fn candidates(&'a self) -> Vec> { let mut candidates = vec![]; - let last_eval_step = match self.evaluation_kind { - inspect::CanonicalGoalEvaluationKind::Overflow - | inspect::CanonicalGoalEvaluationKind::CycleInStack - | inspect::CanonicalGoalEvaluationKind::ProvisionalCacheHit => { - warn!("unexpected root evaluation: {:?}", self.evaluation_kind); - return vec![]; - } + let last_eval_step = match &self.evaluation_kind { + // An annoying edge case in case the recursion limit is 0. + inspect::CanonicalGoalEvaluationKind::Overflow => return vec![], inspect::CanonicalGoalEvaluationKind::Evaluation { final_revision } => final_revision, }; diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 29f78f9d5f0..38d338598a1 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -770,7 +770,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { let reported = tcx.dcx().emit_err(UnableToConstructConstantValue { span: tcx.def_span(unevaluated.def), - unevaluated: unevaluated, + unevaluated, }); Err(ErrorHandled::Reported(reported.into(), tcx.def_span(unevaluated.def))) } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 8a17d7ed641..568214fe022 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1636,7 +1636,7 @@ fn confirm_fn_pointer_candidate<'cx, 'tcx>( .generics_of(def_id) .host_effect_index .map_or(tcx.consts.true_, |idx| args.const_at(idx)), - ty::FnPtr(_) => tcx.consts.true_, + ty::FnPtr(..) => tcx.consts.true_, _ => unreachable!("only expected FnPtr or FnDef in `confirm_fn_pointer_candidate`"), }; diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs index d3a1ed52d2e..7d30e652449 100644 --- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs @@ -33,7 +33,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { | ty::Float(_) | ty::Never | ty::FnDef(..) - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::Char | ty::CoroutineWitness(..) | ty::RawPtr(_, _) @@ -224,7 +224,7 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>( | ty::RawPtr(..) | ty::Ref(..) | ty::FnDef(..) - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::CoroutineWitness(..) => { // these types never have a destructor } diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 247b6e4823c..cb96db5f7a2 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -333,14 +333,14 @@ impl<'cx, 'tcx> FallibleTypeFolder> for QueryNormalizer<'cx, 'tcx> return Ok(constant); } - let constant = constant.try_super_fold_with(self)?; - debug!(?constant, ?self.param_env); - Ok(crate::traits::with_replaced_escaping_bound_vars( + let constant = crate::traits::with_replaced_escaping_bound_vars( self.infcx, &mut self.universes, constant, |constant| constant.normalize(self.infcx.tcx, self.param_env), - )) + ); + debug!(?constant, ?self.param_env); + constant.try_super_fold_with(self) } #[inline] diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/eq.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/eq.rs deleted file mode 100644 index 656130cda19..00000000000 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/eq.rs +++ /dev/null @@ -1,33 +0,0 @@ -pub use rustc_middle::traits::query::type_op::Eq; -use rustc_middle::traits::query::NoSolution; -use rustc_middle::traits::ObligationCause; -use rustc_middle::ty::{ParamEnvAnd, TyCtxt}; - -use crate::infer::canonical::{Canonical, CanonicalQueryResponse}; -use crate::traits::ObligationCtxt; - -impl<'tcx> super::QueryTypeOp<'tcx> for Eq<'tcx> { - type QueryResponse = (); - - fn try_fast_path( - _tcx: TyCtxt<'tcx>, - key: &ParamEnvAnd<'tcx, Eq<'tcx>>, - ) -> Option { - if key.value.a == key.value.b { Some(()) } else { None } - } - - fn perform_query( - tcx: TyCtxt<'tcx>, - canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>, - ) -> Result, NoSolution> { - tcx.type_op_eq(canonicalized) - } - - fn perform_locally_with_next_solver( - ocx: &ObligationCtxt<'_, 'tcx>, - key: ParamEnvAnd<'tcx, Self>, - ) -> Result { - ocx.eq(&ObligationCause::dummy(), key.param_env, key.value.a, key.value.b)?; - Ok(()) - } -} diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs index 2f64ed963f9..a765de92afd 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs @@ -16,12 +16,10 @@ use crate::traits::{ObligationCause, ObligationCtxt}; pub mod ascribe_user_type; pub mod custom; -pub mod eq; pub mod implied_outlives_bounds; pub mod normalize; pub mod outlives; pub mod prove_predicate; -pub mod subtype; pub use rustc_middle::traits::query::type_op::*; @@ -170,44 +168,12 @@ where // collecting region constraints via `region_constraints`. let (mut output, _) = scrape_region_constraints( infcx, - |_ocx| { - let (output, ei, mut obligations, _) = + |ocx| { + let (output, ei, obligations, _) = Q::fully_perform_into(self, infcx, &mut region_constraints, span)?; error_info = ei; - // Typically, instantiating NLL query results does not - // create obligations. However, in some cases there - // are unresolved type variables, and unify them *can* - // create obligations. In that case, we have to go - // fulfill them. We do this via a (recursive) query. - while !obligations.is_empty() { - trace!("{:#?}", obligations); - let mut progress = false; - for obligation in std::mem::take(&mut obligations) { - let obligation = infcx.resolve_vars_if_possible(obligation); - match ProvePredicate::fully_perform_into( - obligation.param_env.and(ProvePredicate::new(obligation.predicate)), - infcx, - &mut region_constraints, - span, - ) { - Ok(((), _, new, certainty)) => { - obligations.extend(new); - progress = true; - if let Certainty::Ambiguous = certainty { - obligations.push(obligation); - } - } - Err(_) => obligations.push(obligation), - } - } - if !progress { - infcx.dcx().span_bug( - span, - format!("ambiguity processing {obligations:?} from {self:?}"), - ); - } - } + ocx.register_obligations(obligations); Ok(output) }, "fully_perform", diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs index 294c6bfc124..d6687c762c3 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs @@ -1,3 +1,4 @@ +use rustc_hir::LangItem; use rustc_infer::traits::Obligation; pub use rustc_middle::traits::query::type_op::ProvePredicate; use rustc_middle::traits::query::NoSolution; @@ -20,8 +21,7 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> { // such cases. if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_ref)) = key.value.predicate.kind().skip_binder() - && let Some(sized_def_id) = tcx.lang_items().sized_trait() - && trait_ref.def_id() == sized_def_id + && tcx.is_lang_item(trait_ref.def_id(), LangItem::Sized) && trait_ref.self_ty().is_trivially_sized(tcx) { return Some(()); diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/subtype.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/subtype.rs deleted file mode 100644 index 892c2a1f113..00000000000 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/subtype.rs +++ /dev/null @@ -1,30 +0,0 @@ -pub use rustc_middle::traits::query::type_op::Subtype; -use rustc_middle::traits::query::NoSolution; -use rustc_middle::traits::ObligationCause; -use rustc_middle::ty::{ParamEnvAnd, TyCtxt}; - -use crate::infer::canonical::{Canonical, CanonicalQueryResponse}; -use crate::traits::ObligationCtxt; - -impl<'tcx> super::QueryTypeOp<'tcx> for Subtype<'tcx> { - type QueryResponse = (); - - fn try_fast_path(_tcx: TyCtxt<'tcx>, key: &ParamEnvAnd<'tcx, Self>) -> Option<()> { - if key.value.sub == key.value.sup { Some(()) } else { None } - } - - fn perform_query( - tcx: TyCtxt<'tcx>, - canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>, - ) -> Result, NoSolution> { - tcx.type_op_subtype(canonicalized) - } - - fn perform_locally_with_next_solver( - ocx: &ObligationCtxt<'_, 'tcx>, - key: ParamEnvAnd<'tcx, Self>, - ) -> Result { - ocx.sub(&ObligationCause::dummy(), key.param_env, key.value.sub, key.value.sup)?; - Ok(()) - } -} diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 9de62031311..a21feec4b1a 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -468,8 +468,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidates.vec.push(AsyncClosureCandidate); } // Provide an impl, but only for suitable `fn` pointers. - ty::FnPtr(sig) => { - if sig.is_fn_trait_compatible() { + ty::FnPtr(sig_tys, hdr) => { + if sig_tys.with(hdr).is_fn_trait_compatible() { candidates.vec.push(AsyncClosureCandidate); } } @@ -535,8 +535,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidates.ambiguous = true; // Could wind up being a fn() type. } // Provide an impl, but only for suitable `fn` pointers. - ty::FnPtr(sig) => { - if sig.is_fn_trait_compatible() { + ty::FnPtr(sig_tys, hdr) => { + if sig_tys.with(hdr).is_fn_trait_compatible() { candidates .vec .push(FnPointerCandidate { fn_host_effect: self.tcx().consts.true_ }); @@ -545,6 +545,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Provide an impl for suitable functions, rejecting `#[target_feature]` functions (RFC 2396). ty::FnDef(def_id, args) => { let tcx = self.tcx(); + // FIXME(struct_target_features): should a function that inherits target_features + // through an argument implement Fn traits? if tcx.fn_sig(def_id).skip_binder().is_fn_trait_compatible() && tcx.codegen_fn_attrs(def_id).target_features.is_empty() { @@ -819,7 +821,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::RawPtr(_, _) | ty::Ref(..) | ty::FnDef(..) - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::Closure(..) | ty::CoroutineClosure(..) | ty::Coroutine(..) @@ -1207,7 +1209,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::RawPtr(_, _) | ty::Ref(..) | ty::FnDef(..) - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::Never | ty::Foreign(_) | ty::Array(..) @@ -1290,7 +1292,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Ref(_, _, _) | ty::FnDef(_, _) | ty::Pat(_, _) - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::Dynamic(_, _, _) | ty::Closure(..) | ty::CoroutineClosure(..) @@ -1339,7 +1341,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let self_ty = self.infcx.resolve_vars_if_possible(obligation.self_ty()); match self_ty.skip_binder().kind() { - ty::FnPtr(_) => candidates.vec.push(BuiltinCandidate { has_nested: false }), + ty::FnPtr(..) => candidates.vec.push(BuiltinCandidate { has_nested: false }), ty::Bool | ty::Char | ty::Int(_) diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index ddd8b970cc8..f19cd19c99a 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -17,8 +17,7 @@ use rustc_infer::infer::{DefineOpaqueTypes, HigherRankedType, InferOk}; use rustc_infer::traits::ObligationCauseCode; use rustc_middle::traits::{BuiltinImplSource, SignatureMismatchData}; use rustc_middle::ty::{ - self, GenericArgs, GenericArgsRef, GenericParamDefKind, ToPolyTraitRef, TraitPredicate, Ty, - TyCtxt, Upcast, + self, GenericArgs, GenericArgsRef, GenericParamDefKind, ToPolyTraitRef, Ty, TyCtxt, Upcast, }; use rustc_middle::{bug, span_bug}; use rustc_span::def_id::DefId; @@ -292,90 +291,120 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &PolyTraitObligation<'tcx>, ) -> Result>, SelectionError<'tcx>> { - use rustc_transmute::{Answer, Condition}; - #[instrument(level = "debug", skip(tcx, obligation, predicate))] + use rustc_transmute::{Answer, Assume, Condition}; + + /// Generate sub-obligations for reference-to-reference transmutations. + fn reference_obligations<'tcx>( + tcx: TyCtxt<'tcx>, + obligation: &PolyTraitObligation<'tcx>, + (src_lifetime, src_ty, src_mut): (ty::Region<'tcx>, Ty<'tcx>, Mutability), + (dst_lifetime, dst_ty, dst_mut): (ty::Region<'tcx>, Ty<'tcx>, Mutability), + assume: Assume, + ) -> Vec> { + let make_transmute_obl = |src, dst| { + let transmute_trait = obligation.predicate.def_id(); + let assume = obligation.predicate.skip_binder().trait_ref.args.const_at(2); + let trait_ref = ty::TraitRef::new( + tcx, + transmute_trait, + [ + ty::GenericArg::from(dst), + ty::GenericArg::from(src), + ty::GenericArg::from(assume), + ], + ); + Obligation::with_depth( + tcx, + obligation.cause.clone(), + obligation.recursion_depth + 1, + obligation.param_env, + obligation.predicate.rebind(trait_ref), + ) + }; + + let make_freeze_obl = |ty| { + let trait_ref = ty::TraitRef::new( + tcx, + tcx.require_lang_item(LangItem::Freeze, None), + [ty::GenericArg::from(ty)], + ); + Obligation::with_depth( + tcx, + obligation.cause.clone(), + obligation.recursion_depth + 1, + obligation.param_env, + trait_ref, + ) + }; + + let make_outlives_obl = |target, region| { + let outlives = ty::OutlivesPredicate(target, region); + Obligation::with_depth( + tcx, + obligation.cause.clone(), + obligation.recursion_depth + 1, + obligation.param_env, + obligation.predicate.rebind(outlives), + ) + }; + + // Given a transmutation from `&'a (mut) Src` and `&'dst (mut) Dst`, + // it is always the case that `Src` must be transmutable into `Dst`, + // and that that `'src` must outlive `'dst`. + let mut obls = vec![make_transmute_obl(src_ty, dst_ty)]; + if !assume.lifetimes { + obls.push(make_outlives_obl(src_lifetime, dst_lifetime)); + } + + // Given a transmutation from `&Src`, both `Src` and `Dst` must be + // `Freeze`, otherwise, using the transmuted value could lead to + // data races. + if src_mut == Mutability::Not { + obls.extend([make_freeze_obl(src_ty), make_freeze_obl(dst_ty)]) + } + + // Given a transmutation into `&'dst mut Dst`, it also must be the + // case that `Dst` is transmutable into `Src`. For example, + // transmuting bool -> u8 is OK as long as you can't update that u8 + // to be > 1, because you could later transmute the u8 back to a + // bool and get undefined behavior. It also must be the case that + // `'dst` lives exactly as long as `'src`. + if dst_mut == Mutability::Mut { + obls.push(make_transmute_obl(dst_ty, src_ty)); + if !assume.lifetimes { + obls.push(make_outlives_obl(dst_lifetime, src_lifetime)); + } + } + + obls + } + + /// Flatten the `Condition` tree into a conjunction of obligations. + #[instrument(level = "debug", skip(tcx, obligation))] fn flatten_answer_tree<'tcx>( tcx: TyCtxt<'tcx>, obligation: &PolyTraitObligation<'tcx>, - predicate: TraitPredicate<'tcx>, cond: Condition>, + assume: Assume, ) -> Vec> { match cond { // FIXME(bryangarza): Add separate `IfAny` case, instead of treating as `IfAll` // Not possible until the trait solver supports disjunctions of obligations Condition::IfAll(conds) | Condition::IfAny(conds) => conds .into_iter() - .flat_map(|cond| flatten_answer_tree(tcx, obligation, predicate, cond)) + .flat_map(|cond| flatten_answer_tree(tcx, obligation, cond, assume)) .collect(), - Condition::IfTransmutable { src, dst } => { - let transmute_trait = obligation.predicate.def_id(); - let assume_const = predicate.trait_ref.args.const_at(2); - let make_transmute_obl = |from_ty, to_ty| { - let trait_ref = ty::TraitRef::new( - tcx, - transmute_trait, - [ - ty::GenericArg::from(to_ty), - ty::GenericArg::from(from_ty), - ty::GenericArg::from(assume_const), - ], - ); - Obligation::with_depth( - tcx, - obligation.cause.clone(), - obligation.recursion_depth + 1, - obligation.param_env, - trait_ref, - ) - }; - - let make_freeze_obl = |ty| { - let trait_ref = ty::TraitRef::new( - tcx, - tcx.require_lang_item(LangItem::Freeze, None), - [ty::GenericArg::from(ty)], - ); - Obligation::with_depth( - tcx, - obligation.cause.clone(), - obligation.recursion_depth + 1, - obligation.param_env, - trait_ref, - ) - }; - - let mut obls = vec![]; - - // If the source is a shared reference, it must be `Freeze`; - // otherwise, transmuting could lead to data races. - if src.mutability == Mutability::Not { - obls.extend([make_freeze_obl(src.ty), make_freeze_obl(dst.ty)]) - } - - // If Dst is mutable, check bidirectionally. - // For example, transmuting bool -> u8 is OK as long as you can't update that u8 - // to be > 1, because you could later transmute the u8 back to a bool and get UB. - match dst.mutability { - Mutability::Not => obls.push(make_transmute_obl(src.ty, dst.ty)), - Mutability::Mut => obls.extend([ - make_transmute_obl(src.ty, dst.ty), - make_transmute_obl(dst.ty, src.ty), - ]), - } - - obls - } + Condition::IfTransmutable { src, dst } => reference_obligations( + tcx, + obligation, + (src.lifetime, src.ty, src.mutability), + (dst.lifetime, dst.ty, dst.mutability), + assume, + ), } } - // We erase regions here because transmutability calls layout queries, - // which does not handle inference regions and doesn't particularly - // care about other regions. Erasing late-bound regions is equivalent - // to instantiating the binder with placeholders then erasing those - // placeholder regions. - let predicate = self - .tcx() - .erase_regions(self.tcx().instantiate_bound_regions_with_erased(obligation.predicate)); + let predicate = obligation.predicate.skip_binder(); let Some(assume) = rustc_transmute::Assume::from_const( self.infcx.tcx, @@ -387,6 +416,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let dst = predicate.trait_ref.args.type_at(0); let src = predicate.trait_ref.args.type_at(1); + debug!(?src, ?dst); let mut transmute_env = rustc_transmute::TransmuteTypeEnv::new(self.infcx); let maybe_transmutable = transmute_env.is_transmutable( @@ -397,7 +427,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let fully_flattened = match maybe_transmutable { Answer::No(_) => Err(Unimplemented)?, - Answer::If(cond) => flatten_answer_tree(self.tcx(), obligation, predicate, cond), + Answer::If(cond) => flatten_answer_tree(self.tcx(), obligation, cond, assume), Answer::Yes => vec![], }; @@ -1398,7 +1428,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::RawPtr(_, _) | ty::Ref(..) | ty::FnDef(..) - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::Never | ty::Foreign(_) => {} diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 1b2767a6a62..f002fa27db2 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2113,7 +2113,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { | ty::Bool | ty::Float(_) | ty::FnDef(..) - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::RawPtr(..) | ty::Char | ty::Ref(..) @@ -2170,7 +2170,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { use self::BuiltinImplConditions::{Ambiguous, None, Where}; match *self_ty.kind() { - ty::FnDef(..) | ty::FnPtr(_) | ty::Error(_) => Where(ty::Binder::dummy(Vec::new())), + ty::FnDef(..) | ty::FnPtr(..) | ty::Error(_) => Where(ty::Binder::dummy(Vec::new())), ty::Uint(_) | ty::Int(_) @@ -2332,7 +2332,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { | ty::Bool | ty::Float(_) | ty::FnDef(..) - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::Error(_) | ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) | ty::Never diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 7e5fe7e3c94..a3982c3d987 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -812,7 +812,7 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { return upvars.visit_with(self); } - ty::FnPtr(_) => { + ty::FnPtr(..) => { // Let the visitor iterate into the argument/return // types appearing in the fn signature. } diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs index 5affadaac38..f34adf85755 100644 --- a/compiler/rustc_traits/src/type_op.rs +++ b/compiler/rustc_traits/src/type_op.rs @@ -10,18 +10,14 @@ use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt; use rustc_trait_selection::traits::query::type_op::ascribe_user_type::{ type_op_ascribe_user_type_with_span, AscribeUserType, }; -use rustc_trait_selection::traits::query::type_op::eq::Eq; use rustc_trait_selection::traits::query::type_op::normalize::Normalize; use rustc_trait_selection::traits::query::type_op::prove_predicate::ProvePredicate; -use rustc_trait_selection::traits::query::type_op::subtype::Subtype; use rustc_trait_selection::traits::{Normalized, Obligation, ObligationCause, ObligationCtxt}; pub(crate) fn provide(p: &mut Providers) { *p = Providers { type_op_ascribe_user_type, - type_op_eq, type_op_prove_predicate, - type_op_subtype, type_op_normalize_ty, type_op_normalize_clause, type_op_normalize_fn_sig, @@ -39,16 +35,6 @@ fn type_op_ascribe_user_type<'tcx>( }) } -fn type_op_eq<'tcx>( - tcx: TyCtxt<'tcx>, - canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Eq<'tcx>>>, -) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> { - tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |ocx, key| { - let (param_env, Eq { a, b }) = key.into_parts(); - Ok(ocx.eq(&ObligationCause::dummy(), param_env, a, b)?) - }) -} - fn type_op_normalize<'tcx, T>( ocx: &ObligationCtxt<'_, 'tcx>, key: ParamEnvAnd<'tcx, Normalize>, @@ -91,16 +77,6 @@ fn type_op_normalize_poly_fn_sig<'tcx>( tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, type_op_normalize) } -fn type_op_subtype<'tcx>( - tcx: TyCtxt<'tcx>, - canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Subtype<'tcx>>>, -) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> { - tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |ocx, key| { - let (param_env, Subtype { sub, sup }) = key.into_parts(); - Ok(ocx.sup(&ObligationCause::dummy(), param_env, sup, sub)?) - }) -} - fn type_op_prove_predicate<'tcx>( tcx: TyCtxt<'tcx>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, ProvePredicate<'tcx>>>, diff --git a/compiler/rustc_transmute/src/layout/mod.rs b/compiler/rustc_transmute/src/layout/mod.rs index bbf155581f9..1cf9e0b9b70 100644 --- a/compiler/rustc_transmute/src/layout/mod.rs +++ b/compiler/rustc_transmute/src/layout/mod.rs @@ -63,7 +63,9 @@ pub mod rustc { use std::fmt::{self, Write}; use rustc_middle::mir::Mutability; - use rustc_middle::ty::{self, Ty}; + use rustc_middle::ty::layout::{LayoutCx, LayoutError}; + use rustc_middle::ty::{self, Ty, TyCtxt}; + use rustc_target::abi::Layout; /// A reference in the layout. #[derive(Debug, Hash, Eq, PartialEq, Clone, Copy)] @@ -120,4 +122,13 @@ pub mod rustc { self != &Self::Primitive } } + + pub(crate) fn layout_of<'tcx>( + cx: LayoutCx<'tcx, TyCtxt<'tcx>>, + ty: Ty<'tcx>, + ) -> Result, &'tcx LayoutError<'tcx>> { + use rustc_middle::ty::layout::LayoutOf; + let ty = cx.tcx.erase_regions(ty); + cx.layout_of(ty).map(|tl| tl.layout) + } } diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs index 5c25f913ffe..2c67e7d4847 100644 --- a/compiler/rustc_transmute/src/layout/tree.rs +++ b/compiler/rustc_transmute/src/layout/tree.rs @@ -171,13 +171,15 @@ where #[cfg(feature = "rustc")] pub(crate) mod rustc { - use rustc_middle::ty::layout::{HasTyCtxt, LayoutCx, LayoutError, LayoutOf}; + use rustc_middle::ty::layout::{HasTyCtxt, LayoutCx, LayoutError}; use rustc_middle::ty::{self, AdtDef, AdtKind, List, ScalarInt, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::ErrorGuaranteed; - use rustc_target::abi::{FieldsShape, Size, TyAndLayout, Variants}; + use rustc_target::abi::{ + FieldIdx, FieldsShape, Layout, Size, TyAndLayout, VariantIdx, Variants, + }; use super::Tree; - use crate::layout::rustc::{Def, Ref}; + use crate::layout::rustc::{layout_of, Def, Ref}; #[derive(Debug, Copy, Clone)] pub(crate) enum Err { @@ -202,20 +204,18 @@ pub(crate) mod rustc { } impl<'tcx> Tree, Ref<'tcx>> { - pub fn from_ty( - ty_and_layout: TyAndLayout<'tcx, Ty<'tcx>>, - cx: LayoutCx<'tcx, TyCtxt<'tcx>>, - ) -> Result { + pub fn from_ty(ty: Ty<'tcx>, cx: LayoutCx<'tcx, TyCtxt<'tcx>>) -> Result { use rustc_target::abi::HasDataLayout; + let layout = layout_of(cx, ty)?; - if let Err(e) = ty_and_layout.ty.error_reported() { + if let Err(e) = ty.error_reported() { return Err(Err::TypeError(e)); } let target = cx.tcx.data_layout(); let pointer_size = target.pointer_size; - match ty_and_layout.ty.kind() { + match ty.kind() { ty::Bool => Ok(Self::bool()), ty::Float(nty) => { @@ -233,32 +233,30 @@ pub(crate) mod rustc { Ok(Self::number(width as _)) } - ty::Tuple(members) => Self::from_tuple(ty_and_layout, members, cx), + ty::Tuple(members) => Self::from_tuple((ty, layout), members, cx), ty::Array(inner_ty, len) => { - let FieldsShape::Array { stride, count } = &ty_and_layout.fields else { + let FieldsShape::Array { stride, count } = &layout.fields else { return Err(Err::NotYetSupported); }; - let inner_ty_and_layout = cx.layout_of(*inner_ty)?; - assert_eq!(*stride, inner_ty_and_layout.size); - let elt = Tree::from_ty(inner_ty_and_layout, cx)?; + let inner_layout = layout_of(cx, *inner_ty)?; + assert_eq!(*stride, inner_layout.size); + let elt = Tree::from_ty(*inner_ty, cx)?; Ok(std::iter::repeat(elt) .take(*count as usize) .fold(Tree::unit(), |tree, elt| tree.then(elt))) } - ty::Adt(adt_def, _args_ref) if !ty_and_layout.ty.is_box() => { - match adt_def.adt_kind() { - AdtKind::Struct => Self::from_struct(ty_and_layout, *adt_def, cx), - AdtKind::Enum => Self::from_enum(ty_and_layout, *adt_def, cx), - AdtKind::Union => Self::from_union(ty_and_layout, *adt_def, cx), - } - } + ty::Adt(adt_def, _args_ref) if !ty.is_box() => match adt_def.adt_kind() { + AdtKind::Struct => Self::from_struct((ty, layout), *adt_def, cx), + AdtKind::Enum => Self::from_enum((ty, layout), *adt_def, cx), + AdtKind::Union => Self::from_union((ty, layout), *adt_def, cx), + }, ty::Ref(lifetime, ty, mutability) => { - let ty_and_layout = cx.layout_of(*ty)?; - let align = ty_and_layout.align.abi.bytes_usize(); - let size = ty_and_layout.size.bytes_usize(); + let layout = layout_of(cx, *ty)?; + let align = layout.align.abi.bytes_usize(); + let size = layout.size.bytes_usize(); Ok(Tree::Ref(Ref { lifetime: *lifetime, ty: *ty, @@ -274,21 +272,20 @@ pub(crate) mod rustc { /// Constructs a `Tree` from a tuple. fn from_tuple( - ty_and_layout: TyAndLayout<'tcx, Ty<'tcx>>, + (ty, layout): (Ty<'tcx>, Layout<'tcx>), members: &'tcx List>, cx: LayoutCx<'tcx, TyCtxt<'tcx>>, ) -> Result { - match &ty_and_layout.fields { + match &layout.fields { FieldsShape::Primitive => { assert_eq!(members.len(), 1); let inner_ty = members[0]; - let inner_ty_and_layout = cx.layout_of(inner_ty)?; - assert_eq!(ty_and_layout.layout, inner_ty_and_layout.layout); - Self::from_ty(inner_ty_and_layout, cx) + let inner_layout = layout_of(cx, inner_ty)?; + Self::from_ty(inner_ty, cx) } FieldsShape::Arbitrary { offsets, .. } => { assert_eq!(offsets.len(), members.len()); - Self::from_variant(Def::Primitive, None, ty_and_layout, ty_and_layout.size, cx) + Self::from_variant(Def::Primitive, None, (ty, layout), layout.size, cx) } FieldsShape::Array { .. } | FieldsShape::Union(_) => Err(Err::NotYetSupported), } @@ -300,13 +297,13 @@ pub(crate) mod rustc { /// /// Panics if `def` is not a struct definition. fn from_struct( - ty_and_layout: TyAndLayout<'tcx, Ty<'tcx>>, + (ty, layout): (Ty<'tcx>, Layout<'tcx>), def: AdtDef<'tcx>, cx: LayoutCx<'tcx, TyCtxt<'tcx>>, ) -> Result { assert!(def.is_struct()); let def = Def::Adt(def); - Self::from_variant(def, None, ty_and_layout, ty_and_layout.size, cx) + Self::from_variant(def, None, (ty, layout), layout.size, cx) } /// Constructs a `Tree` from an enum. @@ -315,19 +312,18 @@ pub(crate) mod rustc { /// /// Panics if `def` is not an enum definition. fn from_enum( - ty_and_layout: TyAndLayout<'tcx, Ty<'tcx>>, + (ty, layout): (Ty<'tcx>, Layout<'tcx>), def: AdtDef<'tcx>, cx: LayoutCx<'tcx, TyCtxt<'tcx>>, ) -> Result { assert!(def.is_enum()); - let layout = ty_and_layout.layout; // Computes the variant of a given index. let layout_of_variant = |index| { - let tag = cx.tcx.tag_for_variant((ty_and_layout.ty, index)); + let tag = cx.tcx.tag_for_variant((cx.tcx.erase_regions(ty), index)); let variant_def = Def::Variant(def.variant(index)); - let variant_ty_and_layout = ty_and_layout.for_variant(&cx, index); - Self::from_variant(variant_def, tag, variant_ty_and_layout, layout.size, cx) + let variant_layout = ty_variant(cx, (ty, layout), index); + Self::from_variant(variant_def, tag, (ty, variant_layout), layout.size, cx) }; // We consider three kinds of enums, each demanding a different @@ -385,21 +381,20 @@ pub(crate) mod rustc { fn from_variant( def: Def<'tcx>, tag: Option, - ty_and_layout: TyAndLayout<'tcx, Ty<'tcx>>, + (ty, layout): (Ty<'tcx>, Layout<'tcx>), total_size: Size, cx: LayoutCx<'tcx, TyCtxt<'tcx>>, ) -> Result { // This constructor does not support non-`FieldsShape::Arbitrary` // layouts. - let FieldsShape::Arbitrary { offsets, memory_index } = ty_and_layout.layout.fields() - else { + let FieldsShape::Arbitrary { offsets, memory_index } = layout.fields() else { return Err(Err::NotYetSupported); }; // When this function is invoked with enum variants, // `ty_and_layout.size` does not encompass the entire size of the // enum. We rely on `total_size` for this. - assert!(ty_and_layout.size <= total_size); + assert!(layout.size <= total_size); let mut size = Size::ZERO; let mut struct_tree = Self::def(def); @@ -412,17 +407,18 @@ pub(crate) mod rustc { // Append the fields, in memory order, to the layout. let inverse_memory_index = memory_index.invert_bijective_mapping(); - for (memory_idx, field_idx) in inverse_memory_index.iter_enumerated() { + for (memory_idx, &field_idx) in inverse_memory_index.iter_enumerated() { // Add interfield padding. - let padding_needed = offsets[*field_idx] - size; + let padding_needed = offsets[field_idx] - size; let padding = Self::padding(padding_needed.bytes_usize()); - let field_ty_and_layout = ty_and_layout.field(&cx, field_idx.as_usize()); - let field_tree = Self::from_ty(field_ty_and_layout, cx)?; + let field_ty = ty_field(cx, (ty, layout), field_idx); + let field_layout = layout_of(cx, field_ty)?; + let field_tree = Self::from_ty(field_ty, cx)?; struct_tree = struct_tree.then(padding).then(field_tree); - size += padding_needed + field_ty_and_layout.size; + size += padding_needed + field_layout.size; } // Add trailing padding. @@ -457,28 +453,27 @@ pub(crate) mod rustc { /// /// Panics if `def` is not a union definition. fn from_union( - ty_and_layout: TyAndLayout<'tcx, Ty<'tcx>>, + (ty, layout): (Ty<'tcx>, Layout<'tcx>), def: AdtDef<'tcx>, cx: LayoutCx<'tcx, TyCtxt<'tcx>>, ) -> Result { assert!(def.is_union()); - let union_layout = ty_and_layout.layout; - // This constructor does not support non-`FieldsShape::Union` // layouts. Fields of this shape are all placed at offset 0. - let FieldsShape::Union(fields) = union_layout.fields() else { + let FieldsShape::Union(fields) = layout.fields() else { return Err(Err::NotYetSupported); }; let fields = &def.non_enum_variant().fields; let fields = fields.iter_enumerated().try_fold( Self::uninhabited(), - |fields, (idx, ref field_def)| { + |fields, (idx, field_def)| { let field_def = Def::Field(field_def); - let field_ty_and_layout = ty_and_layout.field(&cx, idx.as_usize()); - let field = Self::from_ty(field_ty_and_layout, cx)?; - let trailing_padding_needed = union_layout.size - field_ty_and_layout.size; + let field_ty = ty_field(cx, (ty, layout), idx); + let field_layout = layout_of(cx, field_ty)?; + let field = Self::from_ty(field_ty, cx)?; + let trailing_padding_needed = layout.size - field_layout.size; let trailing_padding = Self::padding(trailing_padding_needed.bytes_usize()); let field_and_padding = field.then(trailing_padding); Result::::Ok(fields.or(field_and_padding)) @@ -488,4 +483,40 @@ pub(crate) mod rustc { Ok(Self::def(Def::Adt(def)).then(fields)) } } + + fn ty_field<'tcx>( + cx: LayoutCx<'tcx, TyCtxt<'tcx>>, + (ty, layout): (Ty<'tcx>, Layout<'tcx>), + i: FieldIdx, + ) -> Ty<'tcx> { + match ty.kind() { + ty::Adt(def, args) => { + match layout.variants { + Variants::Single { index } => { + let field = &def.variant(index).fields[i]; + field.ty(cx.tcx, args) + } + // Discriminant field for enums (where applicable). + Variants::Multiple { tag, .. } => { + assert_eq!(i.as_usize(), 0); + ty::layout::PrimitiveExt::to_ty(&tag.primitive(), cx.tcx) + } + } + } + ty::Tuple(fields) => fields[i.as_usize()], + kind @ _ => unimplemented!( + "only a subset of `Ty::ty_and_layout_field`'s functionality is implemented. implementation needed for {:?}", + kind + ), + } + } + + fn ty_variant<'tcx>( + cx: LayoutCx<'tcx, TyCtxt<'tcx>>, + (ty, layout): (Ty<'tcx>, Layout<'tcx>), + i: VariantIdx, + ) -> Layout<'tcx> { + let ty = cx.tcx.erase_regions(ty); + TyAndLayout { ty, layout }.for_variant(&cx, i).layout + } } diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs index 31664ee6c4f..bdc98bcea5e 100644 --- a/compiler/rustc_transmute/src/lib.rs +++ b/compiler/rustc_transmute/src/lib.rs @@ -9,7 +9,7 @@ pub(crate) use rustc_data_structures::fx::{FxIndexMap as Map, FxIndexSet as Set} pub mod layout; mod maybe_transmutable; -#[derive(Default)] +#[derive(Copy, Clone, Debug, Default)] pub struct Assume { pub alignment: bool, pub lifetimes: bool, diff --git a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs index 7c66a827db9..2762b4e6384 100644 --- a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs +++ b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs @@ -30,7 +30,7 @@ where // FIXME: Nix this cfg, so we can write unit tests independently of rustc #[cfg(feature = "rustc")] mod rustc { - use rustc_middle::ty::layout::{LayoutCx, LayoutOf}; + use rustc_middle::ty::layout::LayoutCx; use rustc_middle::ty::{ParamEnv, Ty, TyCtxt}; use super::*; @@ -44,19 +44,11 @@ mod rustc { let Self { src, dst, assume, context } = self; let layout_cx = LayoutCx { tcx: context, param_env: ParamEnv::reveal_all() }; - let layout_of = |ty| { - layout_cx - .layout_of(ty) - .map_err(|_| Err::NotYetSupported) - .and_then(|tl| Tree::from_ty(tl, layout_cx)) - }; // Convert `src` and `dst` from their rustc representations, to `Tree`-based - // representations. If these conversions fail, conclude that the transmutation is - // unacceptable; the layouts of both the source and destination types must be - // well-defined. - let src = layout_of(src); - let dst = layout_of(dst); + // representations. + let src = Tree::from_ty(src, layout_cx); + let dst = Tree::from_ty(dst, layout_cx); match (src, dst) { (Err(Err::TypeError(_)), _) | (_, Err(Err::TypeError(_))) => { diff --git a/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs b/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs index 95373916a71..f8b59bdf326 100644 --- a/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs +++ b/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs @@ -4,7 +4,6 @@ use crate::layout; pub(crate) trait QueryContext { type Def: layout::Def; type Ref: layout::Ref; - type Scope: Copy; } #[cfg(test)] @@ -28,20 +27,17 @@ pub(crate) mod test { impl QueryContext for UltraMinimal { type Def = Def; type Ref = !; - type Scope = (); } } #[cfg(feature = "rustc")] mod rustc { - use rustc_middle::ty::{Ty, TyCtxt}; + use rustc_middle::ty::TyCtxt; use super::*; impl<'tcx> super::QueryContext for TyCtxt<'tcx> { type Def = layout::rustc::Def<'tcx>; type Ref = layout::rustc::Ref<'tcx>; - - type Scope = Ty<'tcx>; } } diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index d90c3bedc70..16cd147b7d4 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -169,39 +169,6 @@ fn fn_sig_for_fn_abi<'tcx>( kind: ty::BoundRegionKind::BrEnv, }; - let mut ty = ty; - // When this `Closure` comes from a `CoroutineKindShim`, - // make sure we respect the `target_kind` in that shim. - // FIXME(async_closures): This shouldn't be needed, and we should be populating - // a separate def-id for these bodies. - if let InstanceKind::CoroutineKindShim { .. } = instance.def { - // Grab the parent coroutine-closure. It has the same args for the purposes - // of instantiation, so this will be okay to do. - let ty::CoroutineClosure(_, coroutine_closure_args) = *tcx - .instantiate_and_normalize_erasing_regions( - args, - param_env, - tcx.type_of(tcx.parent(did)), - ) - .kind() - else { - bug!("CoroutineKindShim comes from calling a coroutine-closure"); - }; - let coroutine_closure_args = coroutine_closure_args.as_coroutine_closure(); - ty = tcx.instantiate_bound_regions_with_erased( - coroutine_closure_args.coroutine_closure_sig().map_bound(|sig| { - sig.to_coroutine_given_kind_and_upvars( - tcx, - coroutine_closure_args.parent_args(), - did, - ty::ClosureKind::FnOnce, - tcx.lifetimes.re_erased, - coroutine_closure_args.tupled_upvars_ty(), - coroutine_closure_args.coroutine_captures_by_ref_ty(), - ) - }), - ); - } let env_ty = Ty::new_mut_ref(tcx, ty::Region::new_bound(tcx, ty::INNERMOST, br), ty); let pin_did = tcx.require_lang_item(LangItem::Pin, None); @@ -584,7 +551,7 @@ fn fn_abi_new_uncached<'tcx>( let conv = conv_from_spec_abi(cx.tcx(), sig.abi, sig.c_variadic); let mut inputs = sig.inputs(); - let extra_args = if sig.abi == RustCall { + let extra_args = if sig.abi == SpecAbi::RustCall { assert!(!sig.c_variadic && extra_args.is_empty()); if let Some(input) = sig.inputs().last() { @@ -608,20 +575,8 @@ fn fn_abi_new_uncached<'tcx>( extra_args }; - let target = &cx.tcx.sess.target; - let target_env_gnu_like = matches!(&target.env[..], "gnu" | "musl" | "uclibc"); - let win_x64_gnu = target.os == "windows" && target.arch == "x86_64" && target.env == "gnu"; - let linux_s390x_gnu_like = - target.os == "linux" && target.arch == "s390x" && target_env_gnu_like; - let linux_sparc64_gnu_like = - target.os == "linux" && target.arch == "sparc64" && target_env_gnu_like; - let linux_powerpc_gnu_like = - target.os == "linux" && target.arch == "powerpc" && target_env_gnu_like; - use SpecAbi::*; - let rust_abi = matches!(sig.abi, RustIntrinsic | Rust | RustCall); - let is_drop_in_place = - fn_def_id.is_some() && fn_def_id == cx.tcx.lang_items().drop_in_place_fn(); + fn_def_id.is_some_and(|def_id| cx.tcx.is_lang_item(def_id, LangItem::DropInPlace)); let arg_of = |ty: Ty<'tcx>, arg_idx: Option| -> Result<_, &'tcx FnAbiError<'tcx>> { let span = tracing::debug_span!("arg_of"); @@ -659,18 +614,7 @@ fn fn_abi_new_uncached<'tcx>( }); if arg.layout.is_zst() { - // For some forsaken reason, x86_64-pc-windows-gnu - // doesn't ignore zero-sized struct arguments. - // The same is true for {s390x,sparc64,powerpc}-unknown-linux-{gnu,musl,uclibc}. - if is_return - || rust_abi - || (!win_x64_gnu - && !linux_s390x_gnu_like - && !linux_sparc64_gnu_like - && !linux_powerpc_gnu_like) - { - arg.mode = PassMode::Ignore; - } + arg.mode = PassMode::Ignore; } Ok(arg) diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index 24926883523..ae5341ddec1 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -192,7 +192,7 @@ fn recurse_build<'tcx>( ExprKind::Borrow { arg, .. } => { let arg_node = &body.exprs[*arg]; - // Skip reborrows for now until we allow Deref/Borrow/AddressOf + // Skip reborrows for now until we allow Deref/Borrow/RawBorrow // expressions. // FIXME(generic_const_exprs): Verify/explain why this is sound if let ExprKind::Deref { arg } = arg_node.kind { @@ -202,7 +202,7 @@ fn recurse_build<'tcx>( } } // FIXME(generic_const_exprs): We may want to support these. - ExprKind::AddressOf { .. } | ExprKind::Deref { .. } => maybe_supported_error( + ExprKind::RawBorrow { .. } | ExprKind::Deref { .. } => maybe_supported_error( GenericConstantTooComplexSub::AddressAndDerefNotSupported(node.span), )?, ExprKind::Repeat { .. } | ExprKind::Array { .. } => { @@ -284,7 +284,7 @@ fn error( ) -> Result { let reported = tcx.dcx().emit_err(GenericConstantTooComplex { span: root_span, - maybe_supported: None, + maybe_supported: false, sub, }); @@ -298,7 +298,7 @@ fn maybe_supported_error( ) -> Result { let reported = tcx.dcx().emit_err(GenericConstantTooComplex { span: root_span, - maybe_supported: Some(()), + maybe_supported: true, sub, }); @@ -343,7 +343,7 @@ impl<'a, 'tcx> IsThirPolymorphic<'a, 'tcx> { | thir::ExprKind::VarRef { .. } | thir::ExprKind::UpvarRef { .. } | thir::ExprKind::Borrow { .. } - | thir::ExprKind::AddressOf { .. } + | thir::ExprKind::RawBorrow { .. } | thir::ExprKind::Break { .. } | thir::ExprKind::Continue { .. } | thir::ExprKind::Return { .. } diff --git a/compiler/rustc_ty_utils/src/errors.rs b/compiler/rustc_ty_utils/src/errors.rs index bfbb45f0cb5..42ecaaeafa9 100644 --- a/compiler/rustc_ty_utils/src/errors.rs +++ b/compiler/rustc_ty_utils/src/errors.rs @@ -18,7 +18,7 @@ pub struct GenericConstantTooComplex { #[primary_span] pub span: Span, #[note(ty_utils_maybe_supported)] - pub maybe_supported: Option<()>, + pub maybe_supported: bool, #[subdiagnostic] pub sub: GenericConstantTooComplexSub, } diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index 8812260b3af..70321a071a2 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -144,7 +144,8 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' | DefKind::Field | DefKind::LifetimeParam | DefKind::GlobalAsm - | DefKind::Closure => ty::List::empty(), + | DefKind::Closure + | DefKind::SyntheticCoroutineBody => ty::List::empty(), } } diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 43e49138709..d77c3a277bf 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -248,7 +248,7 @@ fn resolve_associated_item<'tcx>( if name == sym::clone { let self_ty = trait_ref.self_ty(); match self_ty.kind() { - ty::FnDef(..) | ty::FnPtr(_) => (), + ty::FnDef(..) | ty::FnPtr(..) => (), ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Closure(..) @@ -363,6 +363,11 @@ fn resolve_associated_item<'tcx>( tcx.item_name(trait_item_id) ), } + } else if tcx.is_lang_item(trait_ref.def_id, LangItem::TransmuteTrait) { + let name = tcx.item_name(trait_item_id); + assert_eq!(name, sym::transmute); + let args = tcx.erase_regions(rcvr_args); + Some(ty::Instance::new(trait_item_id, args)) } else { Instance::try_resolve_item_for_coroutine(tcx, trait_item_id, trait_id, rcvr_args) } diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 244a6afcf97..234e1a6d55e 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -184,7 +184,7 @@ fn layout_of_uncached<'tcx>( ty::Int(ity) => scalar(Int(Integer::from_int_ty(dl, ity), true)), ty::Uint(ity) => scalar(Int(Integer::from_uint_ty(dl, ity), false)), ty::Float(fty) => scalar(Float(Float::from_float_ty(fty))), - ty::FnPtr(_) => { + ty::FnPtr(..) => { let mut ptr = scalar_unit(Pointer(dl.instruction_address_space)); ptr.valid_range_mut().start = 1; tcx.mk_layout(LayoutS::scalar(cx, ptr)) diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index d274a934d52..9a3956596d2 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -366,7 +366,7 @@ fn adt_consider_insignificant_dtor<'tcx>( fn adt_drop_tys<'tcx>( tcx: TyCtxt<'tcx>, def_id: DefId, -) -> Result<&ty::List>, AlwaysRequiresDrop> { +) -> Result<&'tcx ty::List>, AlwaysRequiresDrop> { // This is for the "adt_drop_tys" query, that considers all `Drop` impls, therefore all dtors are // significant. let adt_has_dtor = diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index 6680b451b7c..e899284674c 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -348,7 +348,8 @@ fn opaque_types_defined_by<'tcx>( | DefKind::Field | DefKind::LifetimeParam | DefKind::GlobalAsm - | DefKind::Impl { .. } => {} + | DefKind::Impl { .. } + | DefKind::SyntheticCoroutineBody => {} // Closures and coroutines are type checked with their parent, so we need to allow all // opaques from the closure signature *and* from the parent body. DefKind::Closure | DefKind::InlineConst => { diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs index 568b9383ffb..6f1cbb0fee7 100644 --- a/compiler/rustc_ty_utils/src/sig_types.rs +++ b/compiler/rustc_ty_utils/src/sig_types.rs @@ -87,7 +87,7 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( // These are not part of a public API, they can only appear as hidden types, and there // the interesting parts are solely in the signature of the containing item's opaque type // or dyn type. - DefKind::InlineConst | DefKind::Closure => {} + DefKind::InlineConst | DefKind::Closure | DefKind::SyntheticCoroutineBody => {} DefKind::Impl { of_trait } => { if of_trait { let span = tcx.hir_node_by_def_id(item).expect_item().expect_impl().of_trait.unwrap().path.span; diff --git a/compiler/rustc_type_ir/Cargo.toml b/compiler/rustc_type_ir/Cargo.toml index 2750838bbe9..98cc116bd00 100644 --- a/compiler/rustc_type_ir/Cargo.toml +++ b/compiler/rustc_type_ir/Cargo.toml @@ -8,6 +8,7 @@ edition = "2021" bitflags = "2.4.1" derive-where = "1.2.7" indexmap = "2.0.0" +rustc-hash = "1.1.0" rustc_ast_ir = { path = "../rustc_ast_ir", default-features = false } rustc_data_structures = { path = "../rustc_data_structures", optional = true } rustc_index = { path = "../rustc_index", default-features = false } @@ -31,3 +32,6 @@ nightly = [ "rustc_index/nightly", "rustc_ast_ir/nightly" ] + +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(bootstrap)'] } diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index c1f6fb36324..d42efbc91e1 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -8,7 +8,7 @@ use derive_where::derive_where; use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; #[cfg(feature = "nightly")] use rustc_serialize::Decodable; -use tracing::debug; +use tracing::instrument; use crate::data_structures::SsoHashSet; use crate::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable}; @@ -86,6 +86,7 @@ macro_rules! impl_binder_encode_decode { #[cfg(feature = "nightly")] impl_binder_encode_decode! { ty::FnSig, + ty::FnSigTys, ty::TraitPredicate, ty::ExistentialPredicate, ty::TraitRef, @@ -247,21 +248,6 @@ impl Binder { // `self.value` is equivalent to `self.skip_binder()` if self.value.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) } } - - /// Splits the contents into two things that share the same binder - /// level as the original, returning two distinct binders. - /// - /// `f` should consider bound regions at depth 1 to be free, and - /// anything it produces with bound regions at depth 1 will be - /// bound in the resulting return values. - pub fn split(self, f: F) -> (Binder, Binder) - where - F: FnOnce(T) -> (U, V), - { - let Binder { value, bound_vars } = self; - let (u, v) = f(value); - (Binder { value: u, bound_vars }, Binder { value: v, bound_vars }) - } } impl Binder> { @@ -831,28 +817,20 @@ impl<'a, I: Interner> ArgFolder<'a, I> { /// As indicated in the diagram, here the same type `&'a i32` is instantiated once, but in the /// first case we do not increase the De Bruijn index and in the second case we do. The reason /// is that only in the second case have we passed through a fn binder. + #[instrument(level = "trace", skip(self), fields(binders_passed = self.binders_passed), ret)] fn shift_vars_through_binders>(&self, val: T) -> T { - debug!( - "shift_vars(val={:?}, binders_passed={:?}, has_escaping_bound_vars={:?})", - val, - self.binders_passed, - val.has_escaping_bound_vars() - ); - if self.binders_passed == 0 || !val.has_escaping_bound_vars() { - return val; + val + } else { + ty::fold::shift_vars(self.cx, val, self.binders_passed) } - - let result = ty::fold::shift_vars(TypeFolder::cx(self), val, self.binders_passed); - debug!("shift_vars: shifted result = {:?}", result); - - result } fn shift_region_through_binders(&self, region: I::Region) -> I::Region { if self.binders_passed == 0 || !region.has_escaping_bound_vars() { - return region; + region + } else { + ty::fold::shift_region(self.cx, region, self.binders_passed) } - ty::fold::shift_region(self.cx, region, self.binders_passed) } } diff --git a/compiler/rustc_type_ir/src/data_structures.rs b/compiler/rustc_type_ir/src/data_structures.rs index 4ca97c0c86c..96036e53b0a 100644 --- a/compiler/rustc_type_ir/src/data_structures.rs +++ b/compiler/rustc_type_ir/src/data_structures.rs @@ -1,8 +1,13 @@ +use std::hash::BuildHasherDefault; + +use rustc_hash::FxHasher; +pub use rustc_hash::{FxHashMap as HashMap, FxHashSet as HashSet}; + +pub type IndexMap = indexmap::IndexMap>; +pub type IndexSet = indexmap::IndexSet>; + #[cfg(feature = "nightly")] mod impl_ { - pub use rustc_data_structures::fx::{ - FxHashMap as HashMap, FxHashSet as HashSet, FxIndexMap as IndexMap, FxIndexSet as IndexSet, - }; pub use rustc_data_structures::sso::{SsoHashMap, SsoHashSet}; pub use rustc_data_structures::stack::ensure_sufficient_stack; pub use rustc_data_structures::sync::Lrc; @@ -10,11 +15,9 @@ mod impl_ { #[cfg(not(feature = "nightly"))] mod impl_ { - pub use std::collections::{HashMap, HashMap as SsoHashMap, HashSet, HashSet as SsoHashSet}; + pub use std::collections::{HashMap as SsoHashMap, HashSet as SsoHashSet}; pub use std::sync::Arc as Lrc; - pub use indexmap::{IndexMap, IndexSet}; - #[inline] pub fn ensure_sufficient_stack(f: impl FnOnce() -> R) -> R { f() diff --git a/compiler/rustc_type_ir/src/elaborate.rs b/compiler/rustc_type_ir/src/elaborate.rs index f30419c801f..433c444e701 100644 --- a/compiler/rustc_type_ir/src/elaborate.rs +++ b/compiler/rustc_type_ir/src/elaborate.rs @@ -237,7 +237,7 @@ pub fn supertrait_def_ids( cx: I, trait_def_id: I::DefId, ) -> impl Iterator { - let mut set = HashSet::default(); + let mut set: HashSet = HashSet::default(); let mut stack = vec![trait_def_id]; set.insert(trait_def_id); diff --git a/compiler/rustc_type_ir/src/fast_reject.rs b/compiler/rustc_type_ir/src/fast_reject.rs index 456accd1a1b..fab4a099117 100644 --- a/compiler/rustc_type_ir/src/fast_reject.rs +++ b/compiler/rustc_type_ir/src/fast_reject.rs @@ -135,7 +135,9 @@ pub fn simplify_type( ty::CoroutineWitness(def_id, _) => Some(SimplifiedType::CoroutineWitness(def_id)), ty::Never => Some(SimplifiedType::Never), ty::Tuple(tys) => Some(SimplifiedType::Tuple(tys.len())), - ty::FnPtr(f) => Some(SimplifiedType::Function(f.skip_binder().inputs().len())), + ty::FnPtr(sig_tys, _hdr) => { + Some(SimplifiedType::Function(sig_tys.skip_binder().inputs().len())) + } ty::Placeholder(..) => Some(SimplifiedType::Placeholder), ty::Param(_) => match treat_params { TreatParams::ForLookup => Some(SimplifiedType::Placeholder), @@ -307,17 +309,14 @@ impl DeepRejectCtxt { obl_preds.principal_def_id() == impl_preds.principal_def_id() ) } - ty::FnPtr(obl_sig) => match k { - ty::FnPtr(impl_sig) => { - let ty::FnSig { inputs_and_output, c_variadic, safety, abi } = - obl_sig.skip_binder(); - let impl_sig = impl_sig.skip_binder(); + ty::FnPtr(obl_sig_tys, obl_hdr) => match k { + ty::FnPtr(impl_sig_tys, impl_hdr) => { + let obl_sig_tys = obl_sig_tys.skip_binder().inputs_and_output; + let impl_sig_tys = impl_sig_tys.skip_binder().inputs_and_output; - abi == impl_sig.abi - && c_variadic == impl_sig.c_variadic - && safety == impl_sig.safety - && inputs_and_output.len() == impl_sig.inputs_and_output.len() - && iter::zip(inputs_and_output.iter(), impl_sig.inputs_and_output.iter()) + obl_hdr == impl_hdr + && obl_sig_tys.len() == impl_sig_tys.len() + && iter::zip(obl_sig_tys.iter(), impl_sig_tys.iter()) .all(|(obl, imp)| self.types_may_unify(obl, imp)) } _ => false, diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs index d37bacc7d35..8e3534b0e9e 100644 --- a/compiler/rustc_type_ir/src/fold.rs +++ b/compiler/rustc_type_ir/src/fold.rs @@ -48,7 +48,7 @@ use std::mem; use rustc_index::{Idx, IndexVec}; -use tracing::debug; +use tracing::instrument; use crate::data_structures::Lrc; use crate::inherent::*; @@ -417,15 +417,14 @@ pub fn shift_region(cx: I, region: I::Region, amount: u32) -> I::Re } } +#[instrument(level = "trace", skip(cx), ret)] pub fn shift_vars(cx: I, value: T, amount: u32) -> T where T: TypeFoldable, { - debug!("shift_vars(value={:?}, amount={})", value, amount); - if amount == 0 || !value.has_escaping_bound_vars() { - return value; + value + } else { + value.fold_with(&mut Shifter::new(cx, amount)) } - - value.fold_with(&mut Shifter::new(cx, amount)) } diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 263ba676427..958360faede 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -133,12 +133,12 @@ pub trait Ty>: } fn is_fn_ptr(self) -> bool { - matches!(self.kind(), ty::FnPtr(_)) + matches!(self.kind(), ty::FnPtr(..)) } fn fn_sig(self, interner: I) -> ty::Binder> { match self.kind() { - ty::FnPtr(sig) => sig, + ty::FnPtr(sig_tys, hdr) => sig_tys.with(hdr), ty::FnDef(def_id, args) => interner.fn_sig(def_id).instantiate(interner, args), ty::Error(_) => { // ignore errors (#54954) @@ -181,7 +181,7 @@ pub trait Ty>: | ty::RawPtr(_, _) | ty::Ref(_, _, _) | ty::FnDef(_, _) - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::Dynamic(_, _, _) | ty::Closure(_, _) | ty::CoroutineClosure(_, _) @@ -203,7 +203,9 @@ pub trait Ty>: pub trait Tys>: Copy + Debug + Hash + Eq + SliceLike + TypeFoldable + Default { - fn split_inputs_and_output(self) -> (I::FnInputTys, I::Ty); + fn inputs(self) -> I::FnInputTys; + + fn output(self) -> I::Ty; } pub trait Abi>: Copy + Debug + Hash + Eq + Relate { diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index c251540c0fc..f2492ede4f5 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -11,7 +11,6 @@ use crate::inherent::*; use crate::ir_print::IrPrint; use crate::lang_items::TraitSolverLangItem; use crate::relate::Relate; -use crate::solve::inspect::CanonicalGoalEvaluationStep; use crate::solve::{ CanonicalInput, ExternalConstraintsData, PredefinedOpaquesData, QueryResult, SolverMode, }; @@ -65,11 +64,6 @@ pub trait Interner: + Eq + TypeVisitable + SliceLike; - type CanonicalGoalEvaluationStepRef: Copy - + Debug - + Hash - + Eq - + Deref>; type CanonicalVars: Copy + Debug @@ -177,11 +171,6 @@ pub trait Interner: fn debug_assert_args_compatible(self, def_id: Self::DefId, args: Self::GenericArgs); - fn intern_canonical_goal_evaluation_step( - self, - step: CanonicalGoalEvaluationStep, - ) -> Self::CanonicalGoalEvaluationStepRef; - fn mk_type_list_from_iter(self, args: I) -> T::Output where I: Iterator, @@ -390,7 +379,6 @@ impl CollectAndApply for Result { } impl search_graph::Cx for I { - type ProofTree = Option; type Input = CanonicalInput; type Result = QueryResult; diff --git a/compiler/rustc_type_ir/src/outlives.rs b/compiler/rustc_type_ir/src/outlives.rs index 2f26a439183..e8afaf1a480 100644 --- a/compiler/rustc_type_ir/src/outlives.rs +++ b/compiler/rustc_type_ir/src/outlives.rs @@ -68,6 +68,9 @@ struct OutlivesCollector<'a, I: Interner> { } impl TypeVisitor for OutlivesCollector<'_, I> { + #[cfg(not(feature = "nightly"))] + type Result = (); + fn visit_ty(&mut self, ty: I::Ty) -> Self::Result { if !self.visited.insert(ty) { return; @@ -186,7 +189,7 @@ impl TypeVisitor for OutlivesCollector<'_, I> { | ty::Slice(_) | ty::RawPtr(_, _) | ty::Ref(_, _, _) - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::Dynamic(_, _, _) | ty::Tuple(_) => { ty.super_visit_with(self); diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs index 9fd3534d1fa..578436b622a 100644 --- a/compiler/rustc_type_ir/src/relate.rs +++ b/compiler/rustc_type_ir/src/relate.rs @@ -524,8 +524,8 @@ pub fn structurally_relate_tys>( Ok(Ty::new_fn_def(cx, a_def_id, args)) } - (ty::FnPtr(a_fty), ty::FnPtr(b_fty)) => { - let fty = relation.relate(a_fty, b_fty)?; + (ty::FnPtr(a_sig_tys, a_hdr), ty::FnPtr(b_sig_tys, b_hdr)) => { + let fty = relation.relate(a_sig_tys.with(a_hdr), b_sig_tys.with(b_hdr))?; Ok(Ty::new_fn_ptr(cx, fty)) } diff --git a/compiler/rustc_type_ir/src/search_graph/global_cache.rs b/compiler/rustc_type_ir/src/search_graph/global_cache.rs index be4f1069cd1..47f7cefac6a 100644 --- a/compiler/rustc_type_ir/src/search_graph/global_cache.rs +++ b/compiler/rustc_type_ir/src/search_graph/global_cache.rs @@ -1,18 +1,17 @@ use derive_where::derive_where; -use rustc_index::IndexVec; -use super::{AvailableDepth, Cx, StackDepth, StackEntry}; -use crate::data_structures::{HashMap, HashSet}; - -#[derive_where(Debug, Clone, Copy; X: Cx)] -struct QueryData { - result: X::Result, - proof_tree: X::ProofTree, -} +use super::{AvailableDepth, Cx, NestedGoals}; +use crate::data_structures::HashMap; struct Success { - data: X::Tracked>, additional_depth: usize, + nested_goals: NestedGoals, + result: X::Tracked, +} + +struct WithOverflow { + nested_goals: NestedGoals, + result: X::Tracked, } /// The cache entry for a given input. @@ -23,24 +22,15 @@ struct Success { #[derive_where(Default; X: Cx)] struct CacheEntry { success: Option>, - /// We have to be careful when caching roots of cycles. - /// - /// See the doc comment of `StackEntry::cycle_participants` for more - /// details. - nested_goals: HashSet, - with_overflow: HashMap>>, + with_overflow: HashMap>, } #[derive_where(Debug; X: Cx)] pub(super) struct CacheData<'a, X: Cx> { pub(super) result: X::Result, - pub(super) proof_tree: X::ProofTree, pub(super) additional_depth: usize, pub(super) encountered_overflow: bool, - // FIXME: This is currently unused, but impacts the design - // by requiring a closure for `Cx::with_global_cache`. - #[allow(dead_code)] - pub(super) nested_goals: &'a HashSet, + pub(super) nested_goals: &'a NestedGoals, } #[derive_where(Default; X: Cx)] pub struct GlobalCache { @@ -55,20 +45,21 @@ impl GlobalCache { input: X::Input, result: X::Result, - proof_tree: X::ProofTree, dep_node: X::DepNodeIndex, additional_depth: usize, encountered_overflow: bool, - nested_goals: &HashSet, + nested_goals: NestedGoals, ) { - let data = cx.mk_tracked(QueryData { result, proof_tree }, dep_node); + let result = cx.mk_tracked(result, dep_node); let entry = self.map.entry(input).or_default(); - entry.nested_goals.extend(nested_goals); if encountered_overflow { - entry.with_overflow.insert(additional_depth, data); + let with_overflow = WithOverflow { nested_goals, result }; + let prev = entry.with_overflow.insert(additional_depth, with_overflow); + assert!(prev.is_none()); } else { - entry.success = Some(Success { data, additional_depth }); + let prev = entry.success.replace(Success { additional_depth, nested_goals, result }); + assert!(prev.is_none()); } } @@ -80,36 +71,37 @@ impl GlobalCache { &'a self, cx: X, input: X::Input, - stack: &IndexVec>, available_depth: AvailableDepth, + mut candidate_is_applicable: impl FnMut(&NestedGoals) -> bool, ) -> Option> { let entry = self.map.get(&input)?; - if stack.iter().any(|e| entry.nested_goals.contains(&e.input)) { - return None; - } - - if let Some(ref success) = entry.success { - if available_depth.cache_entry_is_applicable(success.additional_depth) { - let QueryData { result, proof_tree } = cx.get_tracked(&success.data); + if let Some(Success { additional_depth, ref nested_goals, ref result }) = entry.success { + if available_depth.cache_entry_is_applicable(additional_depth) + && candidate_is_applicable(nested_goals) + { return Some(CacheData { - result, - proof_tree, - additional_depth: success.additional_depth, + result: cx.get_tracked(&result), + additional_depth, encountered_overflow: false, - nested_goals: &entry.nested_goals, + nested_goals, }); } } - entry.with_overflow.get(&available_depth.0).map(|e| { - let QueryData { result, proof_tree } = cx.get_tracked(e); - CacheData { - result, - proof_tree, - additional_depth: available_depth.0, - encountered_overflow: true, - nested_goals: &entry.nested_goals, + let additional_depth = available_depth.0; + if let Some(WithOverflow { nested_goals, result }) = + entry.with_overflow.get(&additional_depth) + { + if candidate_is_applicable(nested_goals) { + return Some(CacheData { + result: cx.get_tracked(result), + additional_depth, + encountered_overflow: true, + nested_goals, + }); } - }) + } + + None } } diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs index 4abf99b1ded..418139c3aad 100644 --- a/compiler/rustc_type_ir/src/search_graph/mod.rs +++ b/compiler/rustc_type_ir/src/search_graph/mod.rs @@ -1,19 +1,32 @@ +/// The search graph is responsible for caching and cycle detection in the trait +/// solver. Making sure that caching doesn't result in soundness bugs or unstable +/// query results is very challenging and makes this one of the most-involved +/// self-contained components of the compiler. +/// +/// We added fuzzing support to test its correctness. The fuzzers used to verify +/// the current implementation can be found in https://github.com/lcnr/search_graph_fuzz. +/// +/// This is just a quick overview of the general design, please check out the relevant +/// [rustc-dev-guide chapter](https://rustc-dev-guide.rust-lang.org/solve/caching.html) for +/// more details. Caching is split between a global cache and the per-cycle `provisional_cache`. +/// The global cache has to be completely unobservable, while the per-cycle cache may impact +/// behavior as long as the resulting behavior is still correct. +use std::cmp::Ordering; +use std::collections::BTreeSet; use std::fmt::Debug; use std::hash::Hash; use std::marker::PhantomData; -use std::mem; use derive_where::derive_where; use rustc_index::{Idx, IndexVec}; use tracing::debug; -use crate::data_structures::{HashMap, HashSet}; +use crate::data_structures::HashMap; use crate::solve::SolverMode; mod global_cache; use global_cache::CacheData; pub use global_cache::GlobalCache; -mod validate; /// The search graph does not simply use `Interner` directly /// to enable its fuzzing without having to stub the rest of @@ -22,7 +35,6 @@ mod validate; /// about `Input` and `Result` as they are implementation details /// of the search graph. pub trait Cx: Copy { - type ProofTree: Debug + Copy; type Input: Debug + Eq + Hash + Copy; type Result: Debug + Eq + Hash + Copy; @@ -43,30 +55,41 @@ pub trait Cx: Copy { ) -> R; } -pub trait ProofTreeBuilder { - fn try_apply_proof_tree(&mut self, proof_tree: X::ProofTree) -> bool; - fn on_provisional_cache_hit(&mut self); - fn on_cycle_in_stack(&mut self); - fn finalize_canonical_goal_evaluation(&mut self, cx: X) -> X::ProofTree; -} - pub trait Delegate { type Cx: Cx; - const FIXPOINT_STEP_LIMIT: usize; - type ProofTreeBuilder: ProofTreeBuilder; + /// Whether to use the provisional cache. Set to `false` by a fuzzer when + /// validating the search graph. + const ENABLE_PROVISIONAL_CACHE: bool; + type ValidationScope; + /// Returning `Some` disables the global cache for the current goal. + /// + /// The `ValidationScope` is used when fuzzing the search graph to track + /// for which goals the global cache has been disabled. This is necessary + /// as we may otherwise ignore the global cache entry for some goal `G` + /// only to later use it, failing to detect a cycle goal and potentially + /// changing the result. + fn enter_validation_scope( + cx: Self::Cx, + input: ::Input, + ) -> Option; + const FIXPOINT_STEP_LIMIT: usize; + + type ProofTreeBuilder; + fn inspect_is_noop(inspect: &mut Self::ProofTreeBuilder) -> bool; + + const DIVIDE_AVAILABLE_DEPTH_ON_OVERFLOW: usize; fn recursion_limit(cx: Self::Cx) -> usize; fn initial_provisional_result( cx: Self::Cx, - kind: CycleKind, + kind: PathKind, input: ::Input, ) -> ::Result; - fn reached_fixpoint( + fn is_initial_provisional_result( cx: Self::Cx, - kind: UsageKind, + kind: PathKind, input: ::Input, - provisional_result: Option<::Result>, result: ::Result, ) -> bool; fn on_stack_overflow( @@ -79,6 +102,13 @@ pub trait Delegate { input: ::Input, ) -> ::Result; + fn is_ambiguous_result(result: ::Result) -> bool; + fn propagate_ambiguity( + cx: Self::Cx, + for_input: ::Input, + from_result: ::Result, + ) -> ::Result; + fn step_is_coinductive(cx: Self::Cx, input: ::Input) -> bool; } @@ -86,19 +116,20 @@ pub trait Delegate { /// result. In the case we return an initial provisional result depending /// on the kind of cycle. #[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum CycleKind { +pub enum PathKind { Coinductive, Inductive, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum UsageKind { - Single(CycleKind), + Single(PathKind), Mixed, } impl UsageKind { fn merge(self, other: Self) -> Self { match (self, other) { + (UsageKind::Mixed, _) | (_, UsageKind::Mixed) => UsageKind::Mixed, (UsageKind::Single(lhs), UsageKind::Single(rhs)) => { if lhs == rhs { UsageKind::Single(lhs) @@ -106,11 +137,11 @@ impl UsageKind { UsageKind::Mixed } } - (UsageKind::Mixed, UsageKind::Mixed) - | (UsageKind::Mixed, UsageKind::Single(_)) - | (UsageKind::Single(_), UsageKind::Mixed) => UsageKind::Mixed, } } + fn and_merge(&mut self, other: Self) { + *self = self.merge(other); + } } #[derive(Debug, Clone, Copy)] @@ -132,7 +163,7 @@ impl AvailableDepth { } Some(if last.encountered_overflow { - AvailableDepth(last.available_depth.0 / 2) + AvailableDepth(last.available_depth.0 / D::DIVIDE_AVAILABLE_DEPTH_ON_OVERFLOW) } else { AvailableDepth(last.available_depth.0 - 1) }) @@ -148,97 +179,181 @@ impl AvailableDepth { } } +/// All cycle heads a given goal depends on, ordered by their stack depth. +/// +/// We therefore pop the cycle heads from highest to lowest. +#[derive(Clone, Debug, PartialEq, Eq, Default)] +struct CycleHeads { + heads: BTreeSet, +} + +impl CycleHeads { + fn is_empty(&self) -> bool { + self.heads.is_empty() + } + + fn highest_cycle_head(&self) -> StackDepth { + *self.heads.last().unwrap() + } + + fn opt_highest_cycle_head(&self) -> Option { + self.heads.last().copied() + } + + fn opt_lowest_cycle_head(&self) -> Option { + self.heads.first().copied() + } + + fn remove_highest_cycle_head(&mut self) { + let last = self.heads.pop_last(); + debug_assert_ne!(last, None); + } + + fn insert(&mut self, head: StackDepth) { + self.heads.insert(head); + } + + fn merge(&mut self, heads: &CycleHeads) { + for &head in heads.heads.iter() { + self.insert(head); + } + } + + /// Update the cycle heads of a goal at depth `this` given the cycle heads + /// of a nested goal. This merges the heads after filtering the parent goal + /// itself. + fn extend_from_child(&mut self, this: StackDepth, child: &CycleHeads) { + for &head in child.heads.iter() { + match head.cmp(&this) { + Ordering::Less => {} + Ordering::Equal => continue, + Ordering::Greater => unreachable!(), + } + + self.insert(head); + } + } +} + +/// The nested goals of each stack entry and the path from the +/// stack entry to that nested goal. +/// +/// We only start tracking nested goals once we've either encountered +/// overflow or a solver cycle. This is a performance optimization to +/// avoid tracking nested goals on the happy path. +/// +/// We use nested goals for two reasons: +/// - when rebasing provisional cache entries +/// - when checking whether we have to ignore a global cache entry as reevaluating +/// it would encounter a cycle or use a provisional cache entry. +/// +/// We need to disable the global cache if using it would hide a cycle, as +/// cycles can impact behavior. The cycle ABA may have different final +/// results from a the cycle BAB depending on the cycle root. +#[derive_where(Debug, Default; X: Cx)] +struct NestedGoals { + nested_goals: HashMap, +} +impl NestedGoals { + fn is_empty(&self) -> bool { + self.nested_goals.is_empty() + } + + fn insert(&mut self, input: X::Input, path_from_entry: UsageKind) { + self.nested_goals.entry(input).or_insert(path_from_entry).and_merge(path_from_entry); + } + + fn merge(&mut self, nested_goals: &NestedGoals) { + #[allow(rustc::potential_query_instability)] + for (input, path_from_entry) in nested_goals.iter() { + self.insert(input, path_from_entry); + } + } + + /// Adds the nested goals of a nested goal, given that the path `step_kind` from this goal + /// to the parent goal. + /// + /// If the path from this goal to the nested goal is inductive, the paths from this goal + /// to all nested goals of that nested goal are also inductive. Otherwise the paths are + /// the same as for the child. + fn extend_from_child(&mut self, step_kind: PathKind, nested_goals: &NestedGoals) { + #[allow(rustc::potential_query_instability)] + for (input, path_from_entry) in nested_goals.iter() { + let path_from_entry = match step_kind { + PathKind::Coinductive => path_from_entry, + PathKind::Inductive => UsageKind::Single(PathKind::Inductive), + }; + self.insert(input, path_from_entry); + } + } + + #[cfg_attr(feature = "nightly", rustc_lint_query_instability)] + #[allow(rustc::potential_query_instability)] + fn iter(&self) -> impl Iterator + '_ { + self.nested_goals.iter().map(|(i, p)| (*i, *p)) + } + + fn get(&self, input: X::Input) -> Option { + self.nested_goals.get(&input).copied() + } + + fn contains(&self, input: X::Input) -> bool { + self.nested_goals.contains_key(&input) + } +} + rustc_index::newtype_index! { #[orderable] #[gate_rustc_only] pub struct StackDepth {} } +/// Stack entries of the evaluation stack. Its fields tend to be lazily +/// when popping a child goal or completely immutable. #[derive_where(Debug; X: Cx)] struct StackEntry { input: X::Input, + /// The available depth of a given goal, immutable. available_depth: AvailableDepth, /// The maximum depth reached by this stack entry, only up-to date /// for the top of the stack and lazily updated for the rest. reached_depth: StackDepth, - /// Whether this entry is a non-root cycle participant. - /// - /// We must not move the result of non-root cycle participants to the - /// global cache. We store the highest stack depth of a head of a cycle - /// this goal is involved in. This necessary to soundly cache its - /// provisional result. - non_root_cycle_participant: Option, + /// All cycle heads this goal depends on. Lazily updated and only + /// up-to date for the top of the stack. + heads: CycleHeads, + /// Whether evaluating this goal encountered overflow. Lazily updated. encountered_overflow: bool, + /// Whether this goal has been used as the root of a cycle. This gets + /// eagerly updated when encountering a cycle. has_been_used: Option, - /// We put only the root goal of a coinductive cycle into the global cache. - /// - /// If we were to use that result when later trying to prove another cycle - /// participant, we can end up with unstable query results. - /// - /// See tests/ui/next-solver/coinduction/incompleteness-unstable-result.rs for - /// an example of where this is needed. - /// - /// There can be multiple roots on the same stack, so we need to track - /// cycle participants per root: - /// ```plain - /// A :- B - /// B :- A, C - /// C :- D - /// D :- C - /// ``` - nested_goals: HashSet, + /// The nested goals of this goal, see the doc comment of the type. + nested_goals: NestedGoals, + /// Starts out as `None` and gets set when rerunning this /// goal in case we encounter a cycle. provisional_result: Option, } -/// The provisional result for a goal which is not on the stack. -#[derive(Debug)] -struct DetachedEntry { - /// The head of the smallest non-trivial cycle involving this entry. - /// - /// Given the following rules, when proving `A` the head for - /// the provisional entry of `C` would be `B`. - /// ```plain - /// A :- B - /// B :- C - /// C :- A + B + C - /// ``` - head: StackDepth, - result: X::Result, -} - -/// Stores the stack depth of a currently evaluated goal *and* already -/// computed results for goals which depend on other goals still on the stack. -/// -/// The provisional result may depend on whether the stack above it is inductive -/// or coinductive. Because of this, we store separate provisional results for -/// each case. If an provisional entry is not applicable, it may be the case -/// that we already have provisional result while computing a goal. In this case -/// we prefer the provisional result to potentially avoid fixpoint iterations. -/// See tests/ui/traits/next-solver/cycles/mixed-cycles-2.rs for an example. -/// -/// The provisional cache can theoretically result in changes to the observable behavior, -/// see tests/ui/traits/next-solver/cycles/provisional-cache-impacts-behavior.rs. -#[derive_where(Default; X: Cx)] +/// A provisional result of an already computed goals which depends on other +/// goals still on the stack. +#[derive_where(Debug; X: Cx)] struct ProvisionalCacheEntry { - stack_depth: Option, - with_inductive_stack: Option>, - with_coinductive_stack: Option>, -} - -impl ProvisionalCacheEntry { - fn is_empty(&self) -> bool { - self.stack_depth.is_none() - && self.with_inductive_stack.is_none() - && self.with_coinductive_stack.is_none() - } + /// Whether evaluating the goal encountered overflow. This is used to + /// disable the cache entry except if the last goal on the stack is + /// already involved in this cycle. + encountered_overflow: bool, + /// All cycle heads this cache entry depends on. + heads: CycleHeads, + /// The path from the highest cycle head to this goal. + path_from_head: PathKind, + nested_goals: NestedGoals, + result: X::Result, } pub struct SearchGraph, X: Cx = ::Cx> { @@ -247,7 +362,11 @@ pub struct SearchGraph, X: Cx = ::Cx> { /// /// An element is *deeper* in the stack if its index is *lower*. stack: IndexVec>, - provisional_cache: HashMap>, + /// The provisional cache contains entries for already computed goals which + /// still depend on goals higher-up in the stack. We don't move them to the + /// global cache and track them locally instead. A provisional cache entry + /// is only valid until the result of one of its cycle heads changes. + provisional_cache: HashMap>>, _marker: PhantomData, } @@ -266,77 +385,66 @@ impl, X: Cx> SearchGraph { self.mode } - fn update_parent_goal(&mut self, reached_depth: StackDepth, encountered_overflow: bool) { - if let Some(parent) = self.stack.raw.last_mut() { + /// Lazily update the stack entry for the parent goal. + /// This behavior is shared between actually evaluating goals + /// and using existing global cache entries to make sure they + /// have the same impact on the remaining evaluation. + fn update_parent_goal( + cx: X, + stack: &mut IndexVec>, + reached_depth: StackDepth, + heads: &CycleHeads, + encountered_overflow: bool, + nested_goals: &NestedGoals, + ) { + if let Some(parent_index) = stack.last_index() { + let parent = &mut stack[parent_index]; parent.reached_depth = parent.reached_depth.max(reached_depth); parent.encountered_overflow |= encountered_overflow; + + parent.heads.extend_from_child(parent_index, heads); + let step_kind = Self::step_kind(cx, parent.input); + parent.nested_goals.extend_from_child(step_kind, nested_goals); + // Once we've got goals which encountered overflow or a cycle, + // we track all goals whose behavior may depend depend on these + // goals as this change may cause them to now depend on additional + // goals, resulting in new cycles. See the dev-guide for examples. + if !nested_goals.is_empty() { + parent.nested_goals.insert(parent.input, UsageKind::Single(PathKind::Coinductive)) + } } } pub fn is_empty(&self) -> bool { - self.stack.is_empty() + if self.stack.is_empty() { + debug_assert!(self.provisional_cache.is_empty()); + true + } else { + false + } } - fn stack_coinductive_from( + /// The number of goals currently in the search graph. This should only be + /// used for debugging purposes. + pub fn debug_current_depth(&self) -> usize { + self.stack.len() + } + + fn step_kind(cx: X, input: X::Input) -> PathKind { + if D::step_is_coinductive(cx, input) { PathKind::Coinductive } else { PathKind::Inductive } + } + + /// Whether the path from `head` to the current stack entry is inductive or coinductive. + fn stack_path_kind( cx: X, stack: &IndexVec>, head: StackDepth, - ) -> bool { - stack.raw[head.index()..].iter().all(|entry| D::step_is_coinductive(cx, entry.input)) - } - - // When encountering a solver cycle, the result of the current goal - // depends on goals lower on the stack. - // - // We have to therefore be careful when caching goals. Only the final result - // of the cycle root, i.e. the lowest goal on the stack involved in this cycle, - // is moved to the global cache while all others are stored in a provisional cache. - // - // We update both the head of this cycle to rerun its evaluation until - // we reach a fixpoint and all other cycle participants to make sure that - // their result does not get moved to the global cache. - fn tag_cycle_participants( - stack: &mut IndexVec>, - usage_kind: Option, - head: StackDepth, - ) { - if let Some(usage_kind) = usage_kind { - stack[head].has_been_used = - Some(stack[head].has_been_used.map_or(usage_kind, |prev| prev.merge(usage_kind))); + ) -> PathKind { + if stack.raw[head.index()..].iter().all(|entry| D::step_is_coinductive(cx, entry.input)) { + PathKind::Coinductive + } else { + PathKind::Inductive } - debug_assert!(stack[head].has_been_used.is_some()); - - // The current root of these cycles. Note that this may not be the final - // root in case a later goal depends on a goal higher up the stack. - let mut current_root = head; - while let Some(parent) = stack[current_root].non_root_cycle_participant { - current_root = parent; - debug_assert!(stack[current_root].has_been_used.is_some()); - } - - let (stack, cycle_participants) = stack.raw.split_at_mut(head.index() + 1); - let current_cycle_root = &mut stack[current_root.as_usize()]; - for entry in cycle_participants { - entry.non_root_cycle_participant = entry.non_root_cycle_participant.max(Some(head)); - current_cycle_root.nested_goals.insert(entry.input); - current_cycle_root.nested_goals.extend(mem::take(&mut entry.nested_goals)); - } - } - - fn clear_dependent_provisional_results( - provisional_cache: &mut HashMap>, - head: StackDepth, - ) { - #[allow(rustc::potential_query_instability)] - provisional_cache.retain(|_, entry| { - if entry.with_coinductive_stack.as_ref().is_some_and(|p| p.head == head) { - entry.with_coinductive_stack.take(); - } - if entry.with_inductive_stack.as_ref().is_some_and(|p| p.head == head) { - entry.with_inductive_stack.take(); - } - !entry.is_empty() - }); } /// Probably the most involved method of the whole solver. @@ -348,90 +456,66 @@ impl, X: Cx> SearchGraph { cx: X, input: X::Input, inspect: &mut D::ProofTreeBuilder, - mut prove_goal: impl FnMut(&mut Self, &mut D::ProofTreeBuilder) -> X::Result, + mut evaluate_goal: impl FnMut(&mut Self, &mut D::ProofTreeBuilder) -> X::Result, ) -> X::Result { - self.check_invariants(); - // Check for overflow. let Some(available_depth) = AvailableDepth::allowed_depth_for_nested::(cx, &self.stack) else { - if let Some(last) = self.stack.raw.last_mut() { - last.encountered_overflow = true; - } - - debug!("encountered stack overflow"); - return D::on_stack_overflow(cx, inspect, input); + return self.handle_overflow(cx, input, inspect); }; - if let Some(result) = self.lookup_global_cache(cx, input, available_depth, inspect) { + // We check the provisional cache before checking the global cache. This simplifies + // the implementation as we can avoid worrying about cases where both the global and + // provisional cache may apply, e.g. consider the following example + // + // - xxBA overflow + // - A + // - BA cycle + // - CB :x: + if let Some(result) = self.lookup_provisional_cache(cx, input) { return result; } - // Check whether the goal is in the provisional cache. - // The provisional result may rely on the path to its cycle roots, - // so we have to check the path of the current goal matches that of - // the cache entry. - let cache_entry = self.provisional_cache.entry(input).or_default(); - if let Some(entry) = cache_entry - .with_coinductive_stack - .as_ref() - .filter(|p| Self::stack_coinductive_from(cx, &self.stack, p.head)) - .or_else(|| { - cache_entry - .with_inductive_stack - .as_ref() - .filter(|p| !Self::stack_coinductive_from(cx, &self.stack, p.head)) - }) - { - debug!("provisional cache hit"); - // We have a nested goal which is already in the provisional cache, use - // its result. We do not provide any usage kind as that should have been - // already set correctly while computing the cache entry. - inspect.on_provisional_cache_hit(); - Self::tag_cycle_participants(&mut self.stack, None, entry.head); - return entry.result; - } else if let Some(stack_depth) = cache_entry.stack_depth { - debug!("encountered cycle with depth {stack_depth:?}"); - // We have a nested goal which directly relies on a goal deeper in the stack. - // - // We start by tagging all cycle participants, as that's necessary for caching. - // - // Finally we can return either the provisional response or the initial response - // in case we're in the first fixpoint iteration for this goal. - inspect.on_cycle_in_stack(); - - let is_coinductive_cycle = Self::stack_coinductive_from(cx, &self.stack, stack_depth); - let cycle_kind = - if is_coinductive_cycle { CycleKind::Coinductive } else { CycleKind::Inductive }; - Self::tag_cycle_participants( - &mut self.stack, - Some(UsageKind::Single(cycle_kind)), - stack_depth, - ); - - // Return the provisional result or, if we're in the first iteration, - // start with no constraints. - return if let Some(result) = self.stack[stack_depth].provisional_result { - result - } else { - D::initial_provisional_result(cx, cycle_kind, input) - }; + // Lookup the global cache unless we're building proof trees or are currently + // fuzzing. + let validate_cache = if !D::inspect_is_noop(inspect) { + None + } else if let Some(scope) = D::enter_validation_scope(cx, input) { + // When validating the global cache we need to track the goals for which the + // global cache has been disabled as it may otherwise change the result for + // cyclic goals. We don't care about goals which are not on the current stack + // so it's fine to drop their scope eagerly. + self.lookup_global_cache_untracked(cx, input, available_depth) + .inspect(|expected| debug!(?expected, "validate cache entry")) + .map(|r| (scope, r)) + } else if let Some(result) = self.lookup_global_cache(cx, input, available_depth) { + return result; } else { - // No entry, we push this goal on the stack and try to prove it. - let depth = self.stack.next_index(); - let entry = StackEntry { - input, - available_depth, - reached_depth: depth, - non_root_cycle_participant: None, - encountered_overflow: false, - has_been_used: None, - nested_goals: Default::default(), - provisional_result: None, - }; - assert_eq!(self.stack.push(entry), depth); - cache_entry.stack_depth = Some(depth); + None }; + // Detect cycles on the stack. We do this after the global cache lookup to + // avoid iterating over the stack in case a goal has already been computed. + // This may not have an actual performance impact and we could reorder them + // as it may reduce the number of `nested_goals` we need to track. + if let Some(result) = self.check_cycle_on_stack(cx, input) { + debug_assert!(validate_cache.is_none(), "global cache and cycle on stack"); + return result; + } + + // Unfortunate, it looks like we actually have to compute this goalrar. + let depth = self.stack.next_index(); + let entry = StackEntry { + input, + available_depth, + reached_depth: depth, + heads: Default::default(), + encountered_overflow: false, + has_been_used: None, + nested_goals: Default::default(), + provisional_result: None, + }; + assert_eq!(self.stack.push(entry), depth); + // This is for global caching, so we properly track query dependencies. // Everything that affects the `result` should be performed within this // `with_anon_task` closure. If computing this goal depends on something @@ -439,65 +523,320 @@ impl, X: Cx> SearchGraph { // must not be added to the global cache. Notably, this is the case for // trait solver cycles participants. let ((final_entry, result), dep_node) = cx.with_cached_task(|| { - for _ in 0..D::FIXPOINT_STEP_LIMIT { - match self.fixpoint_step_in_task(cx, input, inspect, &mut prove_goal) { - StepResult::Done(final_entry, result) => return (final_entry, result), - StepResult::HasChanged => debug!("fixpoint changed provisional results"), + self.evaluate_goal_in_task(cx, input, inspect, &mut evaluate_goal) + }); + + // We've finished computing the goal and have popped it from the stack, + // lazily update its parent goal. + Self::update_parent_goal( + cx, + &mut self.stack, + final_entry.reached_depth, + &final_entry.heads, + final_entry.encountered_overflow, + &final_entry.nested_goals, + ); + + // We're now done with this goal. We only add the root of cycles to the global cache. + // In case this goal is involved in a larger cycle add it to the provisional cache. + if final_entry.heads.is_empty() { + if let Some((_scope, expected)) = validate_cache { + // Do not try to move a goal into the cache again if we're testing + // the global cache. + assert_eq!(result, expected, "input={input:?}"); + } else if D::inspect_is_noop(inspect) { + self.insert_global_cache(cx, input, final_entry, result, dep_node) + } + } else if D::ENABLE_PROVISIONAL_CACHE { + debug_assert!(validate_cache.is_none()); + let entry = self.provisional_cache.entry(input).or_default(); + let StackEntry { heads, nested_goals, encountered_overflow, .. } = final_entry; + let path_from_head = Self::stack_path_kind(cx, &self.stack, heads.highest_cycle_head()); + entry.push(ProvisionalCacheEntry { + encountered_overflow, + heads, + path_from_head, + nested_goals, + result, + }); + } else { + debug_assert!(validate_cache.is_none()); + } + + result + } + + fn handle_overflow( + &mut self, + cx: X, + input: X::Input, + inspect: &mut D::ProofTreeBuilder, + ) -> X::Result { + if let Some(last) = self.stack.raw.last_mut() { + last.encountered_overflow = true; + // If computing a goal `B` depends on another goal `A` and + // `A` has a nested goal which overflows, then computing `B` + // at the same depth, but with `A` already on the stack, + // would encounter a solver cycle instead, potentially + // changing the result. + // + // We must therefore not use the global cache entry for `B` in that case. + // See tests/ui/traits/next-solver/cycles/hidden-by-overflow.rs + last.nested_goals.insert(last.input, UsageKind::Single(PathKind::Coinductive)); + } + + debug!("encountered stack overflow"); + D::on_stack_overflow(cx, inspect, input) + } + + /// When reevaluating a goal with a changed provisional result, all provisional cache entry + /// which depend on this goal get invalidated. + fn clear_dependent_provisional_results(&mut self) { + let head = self.stack.next_index(); + #[allow(rustc::potential_query_instability)] + self.provisional_cache.retain(|_, entries| { + entries.retain(|entry| entry.heads.highest_cycle_head() != head); + !entries.is_empty() + }); + } + + /// A necessary optimization to handle complex solver cycles. A provisional cache entry + /// relies on a set of cycle heads and the path towards these heads. When popping a cycle + /// head from the stack after we've finished computing it, we can't be sure that the + /// provisional cache entry is still applicable. We need to keep the cache entries to + /// prevent hangs. + /// + /// What we therefore do is check whether the cycle kind of all cycles the goal of a + /// provisional cache entry is involved in would stay the same when computing the + /// goal without its cycle head on the stack. For more details, see the relevant + /// [rustc-dev-guide chapter](https://rustc-dev-guide.rust-lang.org/solve/caching.html). + /// + /// This can be thought of rotating the sub-tree of this provisional result and changing + /// its entry point while making sure that all paths through this sub-tree stay the same. + /// + /// + /// In case the popped cycle head failed to reach a fixpoint anything which depends on + /// its provisional result is invalid. Actually discarding provisional cache entries in + /// this case would cause hangs, so we instead change the result of dependant provisional + /// cache entries to also be ambiguous. This causes some undesirable ambiguity for nested + /// goals whose result doesn't actually depend on this cycle head, but that's acceptable + /// to me. + fn rebase_provisional_cache_entries( + &mut self, + cx: X, + stack_entry: &StackEntry, + mut mutate_result: impl FnMut(X::Input, X::Result) -> X::Result, + ) { + let head = self.stack.next_index(); + #[allow(rustc::potential_query_instability)] + self.provisional_cache.retain(|&input, entries| { + entries.retain_mut(|entry| { + let ProvisionalCacheEntry { + encountered_overflow: _, + heads, + path_from_head, + nested_goals, + result, + } = entry; + if heads.highest_cycle_head() != head { + return true; + } + + // We don't try rebasing if the path from the current head + // to the cache entry is not coinductive or if the path from + // the cache entry to the current head is not coinductive. + // + // Both of these constraints could be weakened, but by only + // accepting coinductive paths we don't have to worry about + // changing the cycle kind of the remaining cycles. We can + // extend this in the future once there's a known issue + // caused by it. + if *path_from_head != PathKind::Coinductive + || nested_goals.get(stack_entry.input).unwrap() + != UsageKind::Single(PathKind::Coinductive) + { + return false; + } + + // Merge the cycle heads of the provisional cache entry and the + // popped head. If the popped cycle head was a root, discard all + // provisional cache entries which depend on it. + heads.remove_highest_cycle_head(); + heads.merge(&stack_entry.heads); + let Some(head) = heads.opt_highest_cycle_head() else { + return false; + }; + + // As we've made sure that the path from the new highest cycle + // head to the uses of the popped cycle head are fully coinductive, + // we can be sure that the paths to all nested goals of the popped + // cycle head remain the same. We can simply merge them. + nested_goals.merge(&stack_entry.nested_goals); + // We now care about the path from the next highest cycle head to the + // provisional cache entry. + *path_from_head = Self::stack_path_kind(cx, &self.stack, head); + // Mutate the result of the provisional cache entry in case we did + // not reach a fixpoint. + *result = mutate_result(input, *result); + true + }); + !entries.is_empty() + }); + } + + fn lookup_provisional_cache(&mut self, cx: X, input: X::Input) -> Option { + if !D::ENABLE_PROVISIONAL_CACHE { + return None; + } + + let entries = self.provisional_cache.get(&input)?; + for &ProvisionalCacheEntry { + encountered_overflow, + ref heads, + path_from_head, + ref nested_goals, + result, + } in entries + { + let head = heads.highest_cycle_head(); + if encountered_overflow { + // This check is overly strict and very subtle. We need to make sure that if + // a global cache entry depends on some goal without adding it to its + // `nested_goals`, that goal must never have an applicable provisional + // cache entry to avoid incorrectly applying the cache entry. + // + // As we'd have to otherwise track literally all nested goals, we only + // apply provisional cache entries which encountered overflow once the + // current goal is already part of the same cycle. This check could be + // improved but seems to be good enough for now. + let last = self.stack.raw.last().unwrap(); + if !last.heads.opt_lowest_cycle_head().is_some_and(|lowest| lowest <= head) { + continue; } } - debug!("canonical cycle overflow"); - let current_entry = self.stack.pop().unwrap(); - debug_assert!(current_entry.has_been_used.is_none()); - let result = D::on_fixpoint_overflow(cx, input); - (current_entry, result) - }); + // A provisional cache entry is only valid if the current path from its + // highest cycle head to the goal is the same. + if path_from_head == Self::stack_path_kind(cx, &self.stack, head) { + // While we don't have to track the full depth of the provisional cache entry, + // we do have to increment the required depth by one as we'd have already failed + // with overflow otherwise + let next_index = self.stack.next_index(); + let last = &mut self.stack.raw.last_mut().unwrap(); + let path_from_entry = Self::step_kind(cx, last.input); + last.nested_goals.insert(input, UsageKind::Single(path_from_entry)); - let proof_tree = inspect.finalize_canonical_goal_evaluation(cx); - - self.update_parent_goal(final_entry.reached_depth, final_entry.encountered_overflow); - - // We're now done with this goal. In case this goal is involved in a larger cycle - // do not remove it from the provisional cache and update its provisional result. - // We only add the root of cycles to the global cache. - if let Some(head) = final_entry.non_root_cycle_participant { - let coinductive_stack = Self::stack_coinductive_from(cx, &self.stack, head); - - let entry = self.provisional_cache.get_mut(&input).unwrap(); - entry.stack_depth = None; - if coinductive_stack { - entry.with_coinductive_stack = Some(DetachedEntry { head, result }); - } else { - entry.with_inductive_stack = Some(DetachedEntry { head, result }); - } - } else { - // When encountering a cycle, both inductive and coinductive, we only - // move the root into the global cache. We also store all other cycle - // participants involved. - // - // We must not use the global cache entry of a root goal if a cycle - // participant is on the stack. This is necessary to prevent unstable - // results. See the comment of `StackEntry::nested_goals` for - // more details. - self.provisional_cache.remove(&input); - let additional_depth = final_entry.reached_depth.as_usize() - self.stack.len(); - cx.with_global_cache(self.mode, |cache| { - cache.insert( + Self::update_parent_goal( cx, - input, - result, - proof_tree, - dep_node, - additional_depth, - final_entry.encountered_overflow, - &final_entry.nested_goals, - ) - }) + &mut self.stack, + next_index, + heads, + false, + nested_goals, + ); + debug_assert!(self.stack[head].has_been_used.is_some()); + debug!(?head, ?path_from_head, "provisional cache hit"); + return Some(result); + } } - self.check_invariants(); + None + } - result + /// Even if there is a global cache entry for a given goal, we need to make sure + /// evaluating this entry would not have ended up depending on either a goal + /// already on the stack or a provisional cache entry. + fn candidate_is_applicable( + cx: X, + stack: &IndexVec>, + provisional_cache: &HashMap>>, + nested_goals: &NestedGoals, + ) -> bool { + // If the global cache entry didn't depend on any nested goals, it always + // applies. + if nested_goals.is_empty() { + return true; + } + + // If a nested goal of the global cache entry is on the stack, we would + // definitely encounter a cycle. + if stack.iter().any(|e| nested_goals.contains(e.input)) { + debug!("cache entry not applicable due to stack"); + return false; + } + + // The global cache entry is also invalid if there's a provisional cache entry + // would apply for any of its nested goals. + #[allow(rustc::potential_query_instability)] + for (input, path_from_global_entry) in nested_goals.iter() { + let Some(entries) = provisional_cache.get(&input) else { + continue; + }; + + debug!(?input, ?path_from_global_entry, ?entries, "candidate_is_applicable"); + // A provisional cache entry is applicable if the path to + // its highest cycle head is equal to the expected path. + for &ProvisionalCacheEntry { + encountered_overflow, + ref heads, + path_from_head, + nested_goals: _, + result: _, + } in entries.iter() + { + // We don't have to worry about provisional cache entries which encountered + // overflow, see the relevant comment in `lookup_provisional_cache`. + if encountered_overflow { + continue; + } + + // A provisional cache entry only applies if the path from its highest head + // matches the path when encountering the goal. + let head = heads.highest_cycle_head(); + let full_path = match Self::stack_path_kind(cx, stack, head) { + PathKind::Coinductive => path_from_global_entry, + PathKind::Inductive => UsageKind::Single(PathKind::Inductive), + }; + + match (full_path, path_from_head) { + (UsageKind::Mixed, _) + | (UsageKind::Single(PathKind::Coinductive), PathKind::Coinductive) + | (UsageKind::Single(PathKind::Inductive), PathKind::Inductive) => { + debug!( + ?full_path, + ?path_from_head, + "cache entry not applicable due to matching paths" + ); + return false; + } + _ => debug!(?full_path, ?path_from_head, "paths don't match"), + } + } + } + + true + } + + /// Used when fuzzing the global cache. Accesses the global cache without + /// updating the state of the search graph. + fn lookup_global_cache_untracked( + &self, + cx: X, + input: X::Input, + available_depth: AvailableDepth, + ) -> Option { + cx.with_global_cache(self.mode, |cache| { + cache + .get(cx, input, available_depth, |nested_goals| { + Self::candidate_is_applicable( + cx, + &self.stack, + &self.provisional_cache, + nested_goals, + ) + }) + .map(|c| c.result) + }) } /// Try to fetch a previously computed result from the global cache, @@ -508,97 +847,206 @@ impl, X: Cx> SearchGraph { cx: X, input: X::Input, available_depth: AvailableDepth, - inspect: &mut D::ProofTreeBuilder, ) -> Option { cx.with_global_cache(self.mode, |cache| { - let CacheData { - result, - proof_tree, - additional_depth, - encountered_overflow, - nested_goals: _, // FIXME: consider nested goals here. - } = cache.get(cx, input, &self.stack, available_depth)?; - - // If we're building a proof tree and the current cache entry does not - // contain a proof tree, we do not use the entry but instead recompute - // the goal. We simply overwrite the existing entry once we're done, - // caching the proof tree. - if !inspect.try_apply_proof_tree(proof_tree) { - return None; - } + let CacheData { result, additional_depth, encountered_overflow, nested_goals } = cache + .get(cx, input, available_depth, |nested_goals| { + Self::candidate_is_applicable( + cx, + &self.stack, + &self.provisional_cache, + nested_goals, + ) + })?; // Update the reached depth of the current goal to make sure // its state is the same regardless of whether we've used the // global cache or not. let reached_depth = self.stack.next_index().plus(additional_depth); - self.update_parent_goal(reached_depth, encountered_overflow); + // We don't move cycle participants to the global cache, so the + // cycle heads are always empty. + let heads = Default::default(); + Self::update_parent_goal( + cx, + &mut self.stack, + reached_depth, + &heads, + encountered_overflow, + nested_goals, + ); - debug!("global cache hit"); + debug!(?additional_depth, "global cache hit"); Some(result) }) } -} -enum StepResult { - Done(StackEntry, X::Result), - HasChanged, -} + fn check_cycle_on_stack(&mut self, cx: X, input: X::Input) -> Option { + let (head, _stack_entry) = self.stack.iter_enumerated().find(|(_, e)| e.input == input)?; + debug!("encountered cycle with depth {head:?}"); + // We have a nested goal which directly relies on a goal deeper in the stack. + // + // We start by tagging all cycle participants, as that's necessary for caching. + // + // Finally we can return either the provisional response or the initial response + // in case we're in the first fixpoint iteration for this goal. + let path_kind = Self::stack_path_kind(cx, &self.stack, head); + let usage_kind = UsageKind::Single(path_kind); + self.stack[head].has_been_used = + Some(self.stack[head].has_been_used.map_or(usage_kind, |prev| prev.merge(usage_kind))); + + // Subtle: when encountering a cyclic goal, we still first checked for overflow, + // so we have to update the reached depth. + let next_index = self.stack.next_index(); + let last_index = self.stack.last_index().unwrap(); + let last = &mut self.stack[last_index]; + last.reached_depth = last.reached_depth.max(next_index); + + let path_from_entry = Self::step_kind(cx, last.input); + last.nested_goals.insert(input, UsageKind::Single(path_from_entry)); + last.nested_goals.insert(last.input, UsageKind::Single(PathKind::Coinductive)); + if last_index != head { + last.heads.insert(head); + } + + // Return the provisional result or, if we're in the first iteration, + // start with no constraints. + if let Some(result) = self.stack[head].provisional_result { + Some(result) + } else { + Some(D::initial_provisional_result(cx, path_kind, input)) + } + } + + /// Whether we've reached a fixpoint when evaluating a cycle head. + fn reached_fixpoint( + &mut self, + cx: X, + stack_entry: &StackEntry, + usage_kind: UsageKind, + result: X::Result, + ) -> bool { + if let Some(prev) = stack_entry.provisional_result { + prev == result + } else if let UsageKind::Single(kind) = usage_kind { + D::is_initial_provisional_result(cx, kind, stack_entry.input, result) + } else { + false + } + } -impl, X: Cx> SearchGraph { /// When we encounter a coinductive cycle, we have to fetch the /// result of that cycle while we are still computing it. Because /// of this we continuously recompute the cycle until the result /// of the previous iteration is equal to the final result, at which /// point we are done. - fn fixpoint_step_in_task( + fn evaluate_goal_in_task( &mut self, cx: X, input: X::Input, inspect: &mut D::ProofTreeBuilder, - prove_goal: &mut F, - ) -> StepResult - where - F: FnMut(&mut Self, &mut D::ProofTreeBuilder) -> X::Result, - { - let result = prove_goal(self, inspect); - let stack_entry = self.stack.pop().unwrap(); - debug_assert_eq!(stack_entry.input, input); + mut evaluate_goal: impl FnMut(&mut Self, &mut D::ProofTreeBuilder) -> X::Result, + ) -> (StackEntry, X::Result) { + let mut i = 0; + loop { + let result = evaluate_goal(self, inspect); + let stack_entry = self.stack.pop().unwrap(); + debug_assert_eq!(stack_entry.input, input); - // If the current goal is not the root of a cycle, we are done. - let Some(usage_kind) = stack_entry.has_been_used else { - return StepResult::Done(stack_entry, result); - }; + // If the current goal is not the root of a cycle, we are done. + // + // There are no provisional cache entries which depend on this goal. + let Some(usage_kind) = stack_entry.has_been_used else { + return (stack_entry, result); + }; - // If it is a cycle head, we have to keep trying to prove it until - // we reach a fixpoint. We need to do so for all cycle heads, - // not only for the root. - // - // See tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.rs - // for an example. + // If it is a cycle head, we have to keep trying to prove it until + // we reach a fixpoint. We need to do so for all cycle heads, + // not only for the root. + // + // See tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.rs + // for an example. + // + // Check whether we reached a fixpoint, either because the final result + // is equal to the provisional result of the previous iteration, or because + // this was only the root of either coinductive or inductive cycles, and the + // final result is equal to the initial response for that case. + if self.reached_fixpoint(cx, &stack_entry, usage_kind, result) { + self.rebase_provisional_cache_entries(cx, &stack_entry, |_, result| result); + return (stack_entry, result); + } - // Start by clearing all provisional cache entries which depend on this - // the current goal. - Self::clear_dependent_provisional_results( - &mut self.provisional_cache, - self.stack.next_index(), - ); + // If computing this goal results in ambiguity with no constraints, + // we do not rerun it. It's incredibly difficult to get a different + // response in the next iteration in this case. These changes would + // likely either be caused by incompleteness or can change the maybe + // cause from ambiguity to overflow. Returning ambiguity always + // preserves soundness and completeness even if the goal is be known + // to succeed or fail. + // + // This prevents exponential blowup affecting multiple major crates. + // As we only get to this branch if we haven't yet reached a fixpoint, + // we also taint all provisional cache entries which depend on the + // current goal. + if D::is_ambiguous_result(result) { + self.rebase_provisional_cache_entries(cx, &stack_entry, |input, _| { + D::propagate_ambiguity(cx, input, result) + }); + return (stack_entry, result); + }; - // Check whether we reached a fixpoint, either because the final result - // is equal to the provisional result of the previous iteration, or because - // this was only the root of either coinductive or inductive cycles, and the - // final result is equal to the initial response for that case. - // - // If we did not reach a fixpoint, update the provisional result and reevaluate. - if D::reached_fixpoint(cx, usage_kind, input, stack_entry.provisional_result, result) { - StepResult::Done(stack_entry, result) - } else { - let depth = self.stack.push(StackEntry { + // If we've reached the fixpoint step limit, we bail with overflow and taint all + // provisional cache entries which depend on the current goal. + i += 1; + if i >= D::FIXPOINT_STEP_LIMIT { + debug!("canonical cycle overflow"); + let result = D::on_fixpoint_overflow(cx, input); + self.rebase_provisional_cache_entries(cx, &stack_entry, |input, _| { + D::on_fixpoint_overflow(cx, input) + }); + return (stack_entry, result); + } + + // Clear all provisional cache entries which depend on a previous provisional + // result of this goal and rerun. + self.clear_dependent_provisional_results(); + + debug!(?result, "fixpoint changed provisional results"); + self.stack.push(StackEntry { has_been_used: None, provisional_result: Some(result), ..stack_entry }); - debug_assert_eq!(self.provisional_cache[&input].stack_depth, Some(depth)); - StepResult::HasChanged } } + + /// When encountering a cycle, both inductive and coinductive, we only + /// move the root into the global cache. We also store all other cycle + /// participants involved. + /// + /// We must not use the global cache entry of a root goal if a cycle + /// participant is on the stack. This is necessary to prevent unstable + /// results. See the comment of `StackEntry::nested_goals` for + /// more details. + fn insert_global_cache( + &mut self, + cx: X, + input: X::Input, + final_entry: StackEntry, + result: X::Result, + dep_node: X::DepNodeIndex, + ) { + let additional_depth = final_entry.reached_depth.as_usize() - self.stack.len(); + debug!(?final_entry, ?result, "insert global cache"); + cx.with_global_cache(self.mode, |cache| { + cache.insert( + cx, + input, + result, + dep_node, + additional_depth, + final_entry.encountered_overflow, + final_entry.nested_goals, + ) + }) + } } diff --git a/compiler/rustc_type_ir/src/search_graph/validate.rs b/compiler/rustc_type_ir/src/search_graph/validate.rs deleted file mode 100644 index 1ae806834ba..00000000000 --- a/compiler/rustc_type_ir/src/search_graph/validate.rs +++ /dev/null @@ -1,75 +0,0 @@ -use super::*; - -impl, X: Cx> SearchGraph { - #[allow(rustc::potential_query_instability)] - pub(super) fn check_invariants(&self) { - if !cfg!(debug_assertions) { - return; - } - - let SearchGraph { mode: _, stack, provisional_cache, _marker } = self; - if stack.is_empty() { - assert!(provisional_cache.is_empty()); - } - - for (depth, entry) in stack.iter_enumerated() { - let StackEntry { - input, - available_depth: _, - reached_depth: _, - non_root_cycle_participant, - encountered_overflow: _, - has_been_used, - ref nested_goals, - provisional_result, - } = *entry; - let cache_entry = provisional_cache.get(&entry.input).unwrap(); - assert_eq!(cache_entry.stack_depth, Some(depth)); - if let Some(head) = non_root_cycle_participant { - assert!(head < depth); - assert!(nested_goals.is_empty()); - assert_ne!(stack[head].has_been_used, None); - - let mut current_root = head; - while let Some(parent) = stack[current_root].non_root_cycle_participant { - current_root = parent; - } - assert!(stack[current_root].nested_goals.contains(&input)); - } - - if !nested_goals.is_empty() { - assert!(provisional_result.is_some() || has_been_used.is_some()); - for entry in stack.iter().take(depth.as_usize()) { - assert_eq!(nested_goals.get(&entry.input), None); - } - } - } - - for (&input, entry) in &self.provisional_cache { - let ProvisionalCacheEntry { stack_depth, with_coinductive_stack, with_inductive_stack } = - entry; - assert!( - stack_depth.is_some() - || with_coinductive_stack.is_some() - || with_inductive_stack.is_some() - ); - - if let &Some(stack_depth) = stack_depth { - assert_eq!(stack[stack_depth].input, input); - } - - let check_detached = |detached_entry: &DetachedEntry| { - let DetachedEntry { head, result: _ } = *detached_entry; - assert_ne!(stack[head].has_been_used, None); - }; - - if let Some(with_coinductive_stack) = with_coinductive_stack { - check_detached(with_coinductive_stack); - } - - if let Some(with_inductive_stack) = with_inductive_stack { - check_detached(with_inductive_stack); - } - } - } -} diff --git a/compiler/rustc_type_ir/src/solve/inspect.rs b/compiler/rustc_type_ir/src/solve/inspect.rs index 47d5e0dace7..099c66f6bdc 100644 --- a/compiler/rustc_type_ir/src/solve/inspect.rs +++ b/compiler/rustc_type_ir/src/solve/inspect.rs @@ -69,9 +69,7 @@ pub struct CanonicalGoalEvaluation { #[derive_where(PartialEq, Eq, Hash, Debug; I: Interner)] pub enum CanonicalGoalEvaluationKind { Overflow, - CycleInStack, - ProvisionalCacheHit, - Evaluation { final_revision: I::CanonicalGoalEvaluationStepRef }, + Evaluation { final_revision: CanonicalGoalEvaluationStep }, } #[derive_where(PartialEq, Eq, Hash, Debug; I: Interner)] diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index 444fd01f012..00fc6ba1c5c 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -340,11 +340,3 @@ impl MaybeCause { } } } - -#[derive_where(PartialEq, Eq, Debug; I: Interner)] -pub struct CacheData { - pub result: QueryResult, - pub proof_tree: Option, - pub additional_depth: usize, - pub encountered_overflow: bool, -} diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 7e48f1b20a8..328b6739d97 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -143,7 +143,12 @@ pub enum TyKind { /// fn foo() -> i32 { 1 } /// let bar: fn() -> i32 = foo; /// ``` - FnPtr(ty::Binder>), + /// + /// These two fields are equivalent to a `ty::Binder>`. But by + /// splitting that into two pieces, we get a more compact data layout that + /// reduces the size of `TyKind` by 8 bytes. It is a very hot type, so it's + /// worth the mild inconvenience. + FnPtr(ty::Binder>, FnHeader), /// A trait object. Written as `dyn for<'b> Trait<'b, Assoc = u32> + Send + 'a`. Dynamic(I::BoundExistentialPredicates, I::Region, DynKind), @@ -288,7 +293,7 @@ impl fmt::Debug for TyKind { RawPtr(ty, mutbl) => write!(f, "*{} {:?}", mutbl.ptr_str(), ty), Ref(r, t, m) => write!(f, "&{:?} {}{:?}", r, m.prefix_str(), t), FnDef(d, s) => f.debug_tuple("FnDef").field(d).field(&s).finish(), - FnPtr(s) => write!(f, "{s:?}"), + FnPtr(sig_tys, hdr) => write!(f, "{:?}", sig_tys.with(*hdr)), Dynamic(p, r, repr) => match repr { DynKind::Dyn => write!(f, "dyn {p:?} + {r:?}"), DynKind::DynStar => write!(f, "dyn* {p:?} + {r:?}"), @@ -868,16 +873,12 @@ pub struct FnSig { } impl FnSig { - pub fn split_inputs_and_output(self) -> (I::FnInputTys, I::Ty) { - self.inputs_and_output.split_inputs_and_output() - } - pub fn inputs(self) -> I::FnInputTys { - self.split_inputs_and_output().0 + self.inputs_and_output.inputs() } pub fn output(self) -> I::Ty { - self.split_inputs_and_output().1 + self.inputs_and_output.output() } pub fn is_fn_trait_compatible(self) -> bool { @@ -922,6 +923,13 @@ impl ty::Binder> { pub fn is_fn_trait_compatible(&self) -> bool { self.skip_binder().is_fn_trait_compatible() } + + // Used to split a single value into the two fields in `TyKind::FnPtr`. + pub fn split(self) -> (ty::Binder>, FnHeader) { + let hdr = + FnHeader { c_variadic: self.c_variadic(), safety: self.safety(), abi: self.abi() }; + (self.map_bound(|sig| FnSigTys { inputs_and_output: sig.inputs_and_output }), hdr) + } } impl fmt::Debug for FnSig { @@ -935,7 +943,7 @@ impl fmt::Debug for FnSig { } write!(f, "fn(")?; - let (inputs, output) = sig.split_inputs_and_output(); + let inputs = sig.inputs(); for (i, ty) in inputs.iter().enumerate() { if i > 0 { write!(f, ", ")?; @@ -951,9 +959,69 @@ impl fmt::Debug for FnSig { } write!(f, ")")?; + let output = sig.output(); match output.kind() { Tuple(list) if list.is_empty() => Ok(()), _ => write!(f, " -> {:?}", sig.output()), } } } + +// This is just a `FnSig` without the `FnHeader` fields. +#[derive_where(Clone, Copy, Debug, PartialEq, Eq, Hash; I: Interner)] +#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] +pub struct FnSigTys { + pub inputs_and_output: I::Tys, +} + +impl FnSigTys { + pub fn inputs(self) -> I::FnInputTys { + self.inputs_and_output.inputs() + } + + pub fn output(self) -> I::Ty { + self.inputs_and_output.output() + } +} + +impl ty::Binder> { + // Used to combine the two fields in `TyKind::FnPtr` into a single value. + pub fn with(self, hdr: FnHeader) -> ty::Binder> { + self.map_bound(|sig_tys| FnSig { + inputs_and_output: sig_tys.inputs_and_output, + c_variadic: hdr.c_variadic, + safety: hdr.safety, + abi: hdr.abi, + }) + } + + #[inline] + pub fn inputs(self) -> ty::Binder { + self.map_bound(|sig_tys| sig_tys.inputs()) + } + + #[inline] + #[track_caller] + pub fn input(self, index: usize) -> ty::Binder { + self.map_bound(|sig_tys| sig_tys.inputs().get(index).unwrap()) + } + + pub fn inputs_and_output(self) -> ty::Binder { + self.map_bound(|sig_tys| sig_tys.inputs_and_output) + } + + #[inline] + pub fn output(self) -> ty::Binder { + self.map_bound(|sig_tys| sig_tys.output()) + } +} + +#[derive_where(Clone, Copy, Debug, PartialEq, Eq, Hash; I: Interner)] +#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] +pub struct FnHeader { + pub c_variadic: bool, + pub safety: I::Safety, + pub abi: I::Abi, +} diff --git a/compiler/rustc_type_ir/src/ty_kind/closure.rs b/compiler/rustc_type_ir/src/ty_kind/closure.rs index 81717ce4a22..9d907baeeb3 100644 --- a/compiler/rustc_type_ir/src/ty_kind/closure.rs +++ b/compiler/rustc_type_ir/src/ty_kind/closure.rs @@ -197,7 +197,7 @@ impl ClosureArgs { /// Extracts the signature from the closure. pub fn sig(self) -> ty::Binder> { match self.sig_as_fn_ptr_ty().kind() { - ty::FnPtr(sig) => sig, + ty::FnPtr(sig_tys, hdr) => sig_tys.with(hdr), ty => panic!("closure_sig_as_fn_ptr_ty is not a fn-ptr: {ty:?}"), } } @@ -292,21 +292,23 @@ impl CoroutineClosureArgs { pub fn coroutine_closure_sig(self) -> ty::Binder> { let interior = self.coroutine_witness_ty(); - let ty::FnPtr(sig) = self.signature_parts_ty().kind() else { panic!() }; - sig.map_bound(|sig| { - let [resume_ty, tupled_inputs_ty] = *sig.inputs().as_slice() else { + let ty::FnPtr(sig_tys, hdr) = self.signature_parts_ty().kind() else { panic!() }; + sig_tys.map_bound(|sig_tys| { + let [resume_ty, tupled_inputs_ty] = *sig_tys.inputs().as_slice() else { panic!(); }; - let [yield_ty, return_ty] = *sig.output().tuple_fields().as_slice() else { panic!() }; + let [yield_ty, return_ty] = *sig_tys.output().tuple_fields().as_slice() else { + panic!() + }; CoroutineClosureSignature { interior, tupled_inputs_ty, resume_ty, yield_ty, return_ty, - c_variadic: sig.c_variadic, - safety: sig.safety, - abi: sig.abi, + c_variadic: hdr.c_variadic, + safety: hdr.safety, + abi: hdr.abi, } }) } @@ -321,7 +323,7 @@ impl CoroutineClosureArgs { pub fn has_self_borrows(&self) -> bool { match self.coroutine_captures_by_ref_ty().kind() { - ty::FnPtr(sig) => sig + ty::FnPtr(sig_tys, _) => sig_tys .skip_binder() .visit_with(&mut HasRegionsBoundAt { binder: ty::INNERMOST }) .is_break(), @@ -460,11 +462,11 @@ impl CoroutineClosureSignature { ) -> I::Ty { match kind { ty::ClosureKind::Fn | ty::ClosureKind::FnMut => { - let ty::FnPtr(sig) = coroutine_captures_by_ref_ty.kind() else { + let ty::FnPtr(sig_tys, _) = coroutine_captures_by_ref_ty.kind() else { panic!(); }; let coroutine_captures_by_ref_ty = - sig.output().skip_binder().fold_with(&mut FoldEscapingRegions { + sig_tys.output().skip_binder().fold_with(&mut FoldEscapingRegions { interner: cx, region: env_region, debruijn: ty::INNERMOST, diff --git a/compiler/stable_mir/src/mir/visit.rs b/compiler/stable_mir/src/mir/visit.rs index 50d7bae21db..aeae866e9d3 100644 --- a/compiler/stable_mir/src/mir/visit.rs +++ b/compiler/stable_mir/src/mir/visit.rs @@ -465,6 +465,22 @@ impl Location { } } +/// Location of the statement at the given index for a given basic block. Assumes that `stmt_idx` +/// and `bb_idx` are valid for a given body. +pub fn statement_location(body: &Body, bb_idx: &BasicBlockIdx, stmt_idx: usize) -> Location { + let bb = &body.blocks[*bb_idx]; + let stmt = &bb.statements[stmt_idx]; + Location(stmt.span) +} + +/// Location of the terminator for a given basic block. Assumes that `bb_idx` is valid for a given +/// body. +pub fn terminator_location(body: &Body, bb_idx: &BasicBlockIdx) -> Location { + let bb = &body.blocks[*bb_idx]; + let terminator = &bb.terminator; + Location(terminator.span) +} + /// Reference to a place used to represent a partial projection. pub struct PlaceRef<'a> { pub local: Local, diff --git a/config.example.toml b/config.example.toml index 1b7de662e84..f1dc32234cc 100644 --- a/config.example.toml +++ b/config.example.toml @@ -337,6 +337,7 @@ # "analysis", # "src", # "wasm-component-ld", +# "miri", "cargo-miri" # for dev/nightly channels #] # Verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose, 3 == print environment variables on each rustc invocation diff --git a/library/Cargo.lock b/library/Cargo.lock index b36399d880e..54ad052c523 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -58,9 +58,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.118" +version = "0.1.123" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92afe7344b64cccf3662ca26d5d1c0828ab826f04206b97d856e3625e390e4b5" +checksum = "b47fcbecb558bdad78c7d3a998523c60a50dd6cd046d5fe74163e309e878fff7" dependencies = [ "cc", "rustc-std-workspace-core", @@ -155,9 +155,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.155" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" dependencies = [ "rustc-std-workspace-core", ] @@ -339,6 +339,7 @@ dependencies = [ "std_detect", "unwind", "wasi", + "windows-targets 0.0.0", ] [[package]] @@ -421,9 +422,13 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.5", ] +[[package]] +name = "windows-targets" +version = "0.0.0" + [[package]] name = "windows-targets" version = "0.52.5" diff --git a/library/Cargo.toml b/library/Cargo.toml index c4513b4c127..d8ece6b0ebd 100644 --- a/library/Cargo.toml +++ b/library/Cargo.toml @@ -8,6 +8,7 @@ members = [ exclude = [ # stdarch has its own Cargo workspace "stdarch", + "windows_targets" ] [profile.release.package.compiler_builtins] diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index bdf16257c7c..4365bcc4ad0 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -10,7 +10,7 @@ edition = "2021" [dependencies] core = { path = "../core" } -compiler_builtins = { version = "0.1.118", features = ['rustc-dep-of-std'] } +compiler_builtins = { version = "0.1.123", features = ['rustc-dep-of-std'] } [dev-dependencies] rand = { version = "0.8.5", default-features = false, features = ["alloc"] } diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 7de41259599..38b1766c174 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -262,8 +262,6 @@ impl Box { /// # Examples /// /// ``` - /// #![feature(new_uninit)] - /// /// let mut five = Box::::new_uninit(); /// /// let five = unsafe { @@ -276,7 +274,7 @@ impl Box { /// assert_eq!(*five, 5) /// ``` #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[must_use] #[inline] pub fn new_uninit() -> Box> { @@ -292,7 +290,7 @@ impl Box { /// # Examples /// /// ``` - /// #![feature(new_uninit)] + /// #![feature(new_zeroed_alloc)] /// /// let zero = Box::::new_zeroed(); /// let zero = unsafe { zero.assume_init() }; @@ -303,7 +301,7 @@ impl Box { /// [zeroed]: mem::MaybeUninit::zeroed #[cfg(not(no_global_oom_handling))] #[inline] - #[unstable(feature = "new_uninit", issue = "63291")] + #[unstable(feature = "new_zeroed_alloc", issue = "129396")] #[must_use] pub fn new_zeroed() -> Box> { Self::new_zeroed_in(Global) @@ -349,7 +347,7 @@ impl Box { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// let mut five = Box::::try_new_uninit()?; /// @@ -379,7 +377,7 @@ impl Box { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// let zero = Box::::try_new_zeroed()?; /// let zero = unsafe { zero.assume_init() }; @@ -459,7 +457,7 @@ impl Box { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// use std::alloc::System; /// @@ -497,7 +495,7 @@ impl Box { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// use std::alloc::System; /// @@ -537,7 +535,7 @@ impl Box { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// use std::alloc::System; /// @@ -575,7 +573,7 @@ impl Box { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// use std::alloc::System; /// @@ -653,8 +651,6 @@ impl Box<[T]> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] - /// /// let mut values = Box::<[u32]>::new_uninit_slice(3); /// /// let values = unsafe { @@ -669,7 +665,7 @@ impl Box<[T]> { /// assert_eq!(*values, [1, 2, 3]) /// ``` #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[must_use] pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit]> { unsafe { RawVec::with_capacity(len).into_box(len) } @@ -684,7 +680,7 @@ impl Box<[T]> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] + /// #![feature(new_zeroed_alloc)] /// /// let values = Box::<[u32]>::new_zeroed_slice(3); /// let values = unsafe { values.assume_init() }; @@ -694,7 +690,7 @@ impl Box<[T]> { /// /// [zeroed]: mem::MaybeUninit::zeroed #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "new_uninit", issue = "63291")] + #[unstable(feature = "new_zeroed_alloc", issue = "129396")] #[must_use] pub fn new_zeroed_slice(len: usize) -> Box<[mem::MaybeUninit]> { unsafe { RawVec::with_capacity_zeroed(len).into_box(len) } @@ -706,7 +702,7 @@ impl Box<[T]> { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// let mut values = Box::<[u32]>::try_new_uninit_slice(3)?; /// let values = unsafe { @@ -744,7 +740,7 @@ impl Box<[T]> { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// let values = Box::<[u32]>::try_new_zeroed_slice(3)?; /// let values = unsafe { values.assume_init() }; @@ -776,7 +772,7 @@ impl Box<[T], A> { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// use std::alloc::System; /// @@ -810,7 +806,7 @@ impl Box<[T], A> { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// use std::alloc::System; /// @@ -835,7 +831,7 @@ impl Box<[T], A> { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// use std::alloc::System; /// @@ -878,7 +874,7 @@ impl Box<[T], A> { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// use std::alloc::System; /// @@ -925,8 +921,6 @@ impl Box, A> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] - /// /// let mut five = Box::::new_uninit(); /// /// let five: Box = unsafe { @@ -938,7 +932,7 @@ impl Box, A> { /// /// assert_eq!(*five, 5) /// ``` - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[inline] pub unsafe fn assume_init(self) -> Box { let (raw, alloc) = Box::into_raw_with_allocator(self); @@ -955,7 +949,7 @@ impl Box, A> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] + /// #![feature(box_uninit_write)] /// /// let big_box = Box::<[usize; 1024]>::new_uninit(); /// @@ -972,7 +966,7 @@ impl Box, A> { /// assert_eq!(*x, i); /// } /// ``` - #[unstable(feature = "new_uninit", issue = "63291")] + #[unstable(feature = "box_uninit_write", issue = "129397")] #[inline] pub fn write(mut boxed: Self, value: T) -> Box { unsafe { @@ -998,8 +992,6 @@ impl Box<[mem::MaybeUninit], A> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] - /// /// let mut values = Box::<[u32]>::new_uninit_slice(3); /// /// let values = unsafe { @@ -1013,7 +1005,7 @@ impl Box<[mem::MaybeUninit], A> { /// /// assert_eq!(*values, [1, 2, 3]) /// ``` - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[inline] pub unsafe fn assume_init(self) -> Box<[T], A> { let (raw, alloc) = Box::into_raw_with_allocator(self); @@ -1254,6 +1246,95 @@ impl Box { unsafe { (Unique::from(&mut *ptr), alloc) } } + /// Returns a raw mutable pointer to the `Box`'s contents. + /// + /// The caller must ensure that the `Box` outlives the pointer this + /// function returns, or else it will end up dangling. + /// + /// This method guarantees that for the purpose of the aliasing model, this method + /// does not materialize a reference to the underlying memory, and thus the returned pointer + /// will remain valid when mixed with other calls to [`as_ptr`] and [`as_mut_ptr`]. + /// Note that calling other methods that materialize references to the memory + /// may still invalidate this pointer. + /// See the example below for how this guarantee can be used. + /// + /// # Examples + /// + /// Due to the aliasing guarantee, the following code is legal: + /// + /// ```rust + /// #![feature(box_as_ptr)] + /// + /// unsafe { + /// let mut b = Box::new(0); + /// let ptr1 = Box::as_mut_ptr(&mut b); + /// ptr1.write(1); + /// let ptr2 = Box::as_mut_ptr(&mut b); + /// ptr2.write(2); + /// // Notably, the write to `ptr2` did *not* invalidate `ptr1`: + /// ptr1.write(3); + /// } + /// ``` + /// + /// [`as_mut_ptr`]: Self::as_mut_ptr + /// [`as_ptr`]: Self::as_ptr + #[unstable(feature = "box_as_ptr", issue = "129090")] + #[rustc_never_returns_null_ptr] + #[inline] + pub fn as_mut_ptr(b: &mut Self) -> *mut T { + // This is a primitive deref, not going through `DerefMut`, and therefore not materializing + // any references. + ptr::addr_of_mut!(**b) + } + + /// Returns a raw pointer to the `Box`'s contents. + /// + /// The caller must ensure that the `Box` outlives the pointer this + /// function returns, or else it will end up dangling. + /// + /// The caller must also ensure that the memory the pointer (non-transitively) points to + /// is never written to (except inside an `UnsafeCell`) using this pointer or any pointer + /// derived from it. If you need to mutate the contents of the `Box`, use [`as_mut_ptr`]. + /// + /// This method guarantees that for the purpose of the aliasing model, this method + /// does not materialize a reference to the underlying memory, and thus the returned pointer + /// will remain valid when mixed with other calls to [`as_ptr`] and [`as_mut_ptr`]. + /// Note that calling other methods that materialize mutable references to the memory, + /// as well as writing to this memory, may still invalidate this pointer. + /// See the example below for how this guarantee can be used. + /// + /// # Examples + /// + /// Due to the aliasing guarantee, the following code is legal: + /// + /// ```rust + /// #![feature(box_as_ptr)] + /// + /// unsafe { + /// let mut v = Box::new(0); + /// let ptr1 = Box::as_ptr(&v); + /// let ptr2 = Box::as_mut_ptr(&mut v); + /// let _val = ptr2.read(); + /// // No write to this memory has happened yet, so `ptr1` is still valid. + /// let _val = ptr1.read(); + /// // However, once we do a write... + /// ptr2.write(1); + /// // ... `ptr1` is no longer valid. + /// // This would be UB: let _val = ptr1.read(); + /// } + /// ``` + /// + /// [`as_mut_ptr`]: Self::as_mut_ptr + /// [`as_ptr`]: Self::as_ptr + #[unstable(feature = "box_as_ptr", issue = "129090")] + #[rustc_never_returns_null_ptr] + #[inline] + pub fn as_ptr(b: &Self) -> *const T { + // This is a primitive deref, not going through `DerefMut`, and therefore not materializing + // any references. + ptr::addr_of!(**b) + } + /// Returns a reference to the underlying allocator. /// /// Note: this is an associated function, which means that you have diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 3e44adf73f0..c459a8da820 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -93,7 +93,6 @@ // tidy-alphabetical-start #![cfg_attr(not(no_global_oom_handling), feature(const_alloc_error))] #![cfg_attr(not(no_global_oom_handling), feature(const_btree_len))] -#![cfg_attr(test, feature(new_uninit))] #![feature(alloc_layout_extra)] #![feature(allocator_api)] #![feature(array_chunks)] @@ -131,7 +130,6 @@ #![feature(inplace_iteration)] #![feature(iter_advance_by)] #![feature(iter_next_chunk)] -#![feature(iter_repeat_n)] #![feature(layout_for_ptr)] #![feature(local_waker)] #![feature(maybe_uninit_slice)] diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index bdee06154fa..1b31a78394e 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -503,7 +503,6 @@ impl Rc { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// /// use std::rc::Rc; @@ -518,7 +517,7 @@ impl Rc { /// assert_eq!(*five, 5) /// ``` #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[must_use] pub fn new_uninit() -> Rc> { unsafe { @@ -539,7 +538,7 @@ impl Rc { /// # Examples /// /// ``` - /// #![feature(new_uninit)] + /// #![feature(new_zeroed_alloc)] /// /// use std::rc::Rc; /// @@ -551,7 +550,7 @@ impl Rc { /// /// [zeroed]: mem::MaybeUninit::zeroed #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "new_uninit", issue = "63291")] + #[unstable(feature = "new_zeroed_alloc", issue = "129396")] #[must_use] pub fn new_zeroed() -> Rc> { unsafe { @@ -593,7 +592,7 @@ impl Rc { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// #![feature(get_mut_unchecked)] /// /// use std::rc::Rc; @@ -629,7 +628,7 @@ impl Rc { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// use std::rc::Rc; /// @@ -691,7 +690,6 @@ impl Rc { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// #![feature(allocator_api)] /// @@ -735,7 +733,6 @@ impl Rc { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(allocator_api)] /// /// use std::rc::Rc; @@ -798,7 +795,7 @@ impl Rc { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// #![feature(get_mut_unchecked)] /// /// use std::rc::Rc; @@ -842,7 +839,7 @@ impl Rc { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// use std::rc::Rc; /// use std::alloc::System; @@ -966,7 +963,6 @@ impl Rc<[T]> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// /// use std::rc::Rc; @@ -984,7 +980,7 @@ impl Rc<[T]> { /// assert_eq!(*values, [1, 2, 3]) /// ``` #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[must_use] pub fn new_uninit_slice(len: usize) -> Rc<[mem::MaybeUninit]> { unsafe { Rc::from_ptr(Rc::allocate_for_slice(len)) } @@ -999,7 +995,7 @@ impl Rc<[T]> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] + /// #![feature(new_zeroed_alloc)] /// /// use std::rc::Rc; /// @@ -1011,7 +1007,7 @@ impl Rc<[T]> { /// /// [zeroed]: mem::MaybeUninit::zeroed #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "new_uninit", issue = "63291")] + #[unstable(feature = "new_zeroed_alloc", issue = "129396")] #[must_use] pub fn new_zeroed_slice(len: usize) -> Rc<[mem::MaybeUninit]> { unsafe { @@ -1033,7 +1029,6 @@ impl Rc<[T], A> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// #![feature(allocator_api)] /// @@ -1070,7 +1065,6 @@ impl Rc<[T], A> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(allocator_api)] /// /// use std::rc::Rc; @@ -1120,7 +1114,6 @@ impl Rc, A> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// /// use std::rc::Rc; @@ -1134,7 +1127,7 @@ impl Rc, A> { /// /// assert_eq!(*five, 5) /// ``` - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[inline] pub unsafe fn assume_init(self) -> Rc { let (ptr, alloc) = Rc::into_inner_with_allocator(self); @@ -1158,7 +1151,6 @@ impl Rc<[mem::MaybeUninit], A> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// /// use std::rc::Rc; @@ -1175,7 +1167,7 @@ impl Rc<[mem::MaybeUninit], A> { /// /// assert_eq!(*values, [1, 2, 3]) /// ``` - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[inline] pub unsafe fn assume_init(self) -> Rc<[T], A> { let (ptr, alloc) = Rc::into_inner_with_allocator(self); diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 124230812df..e628be1546f 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -2643,14 +2643,54 @@ impl ToString for i8 { } } -#[doc(hidden)] +// Generic/generated code can sometimes have multiple, nested references +// for strings, including `&&&str`s that would never be written +// by hand. This macro generates twelve layers of nested `&`-impl +// for primitive strings. #[cfg(not(no_global_oom_handling))] -#[stable(feature = "str_to_string_specialization", since = "1.9.0")] -impl ToString for str { - #[inline] - fn to_string(&self) -> String { - String::from(self) - } +macro_rules! to_string_str_wrap_in_ref { + {x $($x:ident)*} => { + &to_string_str_wrap_in_ref! { $($x)* } + }; + {} => { str }; +} +#[cfg(not(no_global_oom_handling))] +macro_rules! to_string_expr_wrap_in_deref { + {$self:expr ; x $($x:ident)*} => { + *(to_string_expr_wrap_in_deref! { $self ; $($x)* }) + }; + {$self:expr ;} => { $self }; +} +#[cfg(not(no_global_oom_handling))] +macro_rules! to_string_str { + {$($($x:ident)*),+} => { + $( + #[doc(hidden)] + #[stable(feature = "str_to_string_specialization", since = "1.9.0")] + impl ToString for to_string_str_wrap_in_ref!($($x)*) { + #[inline] + fn to_string(&self) -> String { + String::from(to_string_expr_wrap_in_deref!(self ; $($x)*)) + } + } + )+ + }; +} + +#[cfg(not(no_global_oom_handling))] +to_string_str! { + x x x x x x x x x x x x, + x x x x x x x x x x x, + x x x x x x x x x x, + x x x x x x x x x, + x x x x x x x x, + x x x x x x x, + x x x x x x, + x x x x x, + x x x x, + x x x, + x x, + x, } #[doc(hidden)] diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 2c0d19b0ada..024a794f17b 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -335,7 +335,7 @@ impl, U: ?Sized, A: Allocator> CoerceUnsized> f impl, U: ?Sized> DispatchFromDyn> for Weak {} #[stable(feature = "arc_weak", since = "1.4.0")] -impl fmt::Debug for Weak { +impl fmt::Debug for Weak { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "(Weak)") } @@ -505,7 +505,6 @@ impl Arc { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// /// use std::sync::Arc; @@ -521,7 +520,7 @@ impl Arc { /// ``` #[cfg(not(no_global_oom_handling))] #[inline] - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[must_use] pub fn new_uninit() -> Arc> { unsafe { @@ -542,7 +541,7 @@ impl Arc { /// # Examples /// /// ``` - /// #![feature(new_uninit)] + /// #![feature(new_zeroed_alloc)] /// /// use std::sync::Arc; /// @@ -555,7 +554,7 @@ impl Arc { /// [zeroed]: mem::MaybeUninit::zeroed #[cfg(not(no_global_oom_handling))] #[inline] - #[unstable(feature = "new_uninit", issue = "63291")] + #[unstable(feature = "new_zeroed_alloc", issue = "129396")] #[must_use] pub fn new_zeroed() -> Arc> { unsafe { @@ -613,7 +612,7 @@ impl Arc { /// # Examples /// /// ``` - /// #![feature(new_uninit, allocator_api)] + /// #![feature(allocator_api)] /// #![feature(get_mut_unchecked)] /// /// use std::sync::Arc; @@ -649,7 +648,7 @@ impl Arc { /// # Examples /// /// ``` - /// #![feature(new_uninit, allocator_api)] + /// #![feature( allocator_api)] /// /// use std::sync::Arc; /// @@ -710,7 +709,6 @@ impl Arc { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// #![feature(allocator_api)] /// @@ -754,7 +752,6 @@ impl Arc { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(allocator_api)] /// /// use std::sync::Arc; @@ -844,7 +841,7 @@ impl Arc { /// # Examples /// /// ``` - /// #![feature(new_uninit, allocator_api)] + /// #![feature(allocator_api)] /// #![feature(get_mut_unchecked)] /// /// use std::sync::Arc; @@ -888,7 +885,7 @@ impl Arc { /// # Examples /// /// ``` - /// #![feature(new_uninit, allocator_api)] + /// #![feature(allocator_api)] /// /// use std::sync::Arc; /// use std::alloc::System; @@ -1100,7 +1097,6 @@ impl Arc<[T]> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// /// use std::sync::Arc; @@ -1119,7 +1115,7 @@ impl Arc<[T]> { /// ``` #[cfg(not(no_global_oom_handling))] #[inline] - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[must_use] pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit]> { unsafe { Arc::from_ptr(Arc::allocate_for_slice(len)) } @@ -1134,7 +1130,7 @@ impl Arc<[T]> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] + /// #![feature(new_zeroed_alloc)] /// /// use std::sync::Arc; /// @@ -1147,7 +1143,7 @@ impl Arc<[T]> { /// [zeroed]: mem::MaybeUninit::zeroed #[cfg(not(no_global_oom_handling))] #[inline] - #[unstable(feature = "new_uninit", issue = "63291")] + #[unstable(feature = "new_zeroed_alloc", issue = "129396")] #[must_use] pub fn new_zeroed_slice(len: usize) -> Arc<[mem::MaybeUninit]> { unsafe { @@ -1170,7 +1166,6 @@ impl Arc<[T], A> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// #![feature(allocator_api)] /// @@ -1191,7 +1186,7 @@ impl Arc<[T], A> { /// assert_eq!(*values, [1, 2, 3]) /// ``` #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "new_uninit", issue = "63291")] + #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn new_uninit_slice_in(len: usize, alloc: A) -> Arc<[mem::MaybeUninit], A> { unsafe { Arc::from_ptr_in(Arc::allocate_for_slice_in(len, &alloc), alloc) } @@ -1206,7 +1201,6 @@ impl Arc<[T], A> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(allocator_api)] /// /// use std::sync::Arc; @@ -1220,7 +1214,7 @@ impl Arc<[T], A> { /// /// [zeroed]: mem::MaybeUninit::zeroed #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "new_uninit", issue = "63291")] + #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn new_zeroed_slice_in(len: usize, alloc: A) -> Arc<[mem::MaybeUninit], A> { unsafe { @@ -1255,7 +1249,6 @@ impl Arc, A> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// /// use std::sync::Arc; @@ -1269,7 +1262,7 @@ impl Arc, A> { /// /// assert_eq!(*five, 5) /// ``` - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[must_use = "`self` will be dropped if the result is not used"] #[inline] pub unsafe fn assume_init(self) -> Arc { @@ -1294,7 +1287,6 @@ impl Arc<[mem::MaybeUninit], A> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// /// use std::sync::Arc; @@ -1311,7 +1303,7 @@ impl Arc<[mem::MaybeUninit], A> { /// /// assert_eq!(*values, [1, 2, 3]) /// ``` - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[must_use = "`self` will be dropped if the result is not used"] #[inline] pub unsafe fn assume_init(self) -> Arc<[T], A> { diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index b4e0bc5fcbe..cfd2e4a1512 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1334,7 +1334,7 @@ impl Vec { self.buf.ptr() } - /// Returns an unsafe mutable pointer to the vector's buffer, or a dangling + /// Returns a raw mutable pointer to the vector's buffer, or a dangling /// raw pointer valid for zero sized reads if the vector didn't allocate. /// /// The caller must ensure that the vector outlives the pointer this @@ -1350,7 +1350,6 @@ impl Vec { /// may still invalidate this pointer. /// See the second example below for how this guarantee can be used. /// - /// /// # Examples /// /// ``` diff --git a/library/alloc/tests/boxed.rs b/library/alloc/tests/boxed.rs index faee64b2f67..bfc31a626fa 100644 --- a/library/alloc/tests/boxed.rs +++ b/library/alloc/tests/boxed.rs @@ -59,6 +59,7 @@ fn box_deref_lval() { assert_eq!(x.get(), 1000); } +#[allow(unused)] pub struct ConstAllocator; unsafe impl Allocator for ConstAllocator { diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index 3d4add6fae4..c5c6a122cfe 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -15,7 +15,6 @@ #![feature(exact_size_is_empty)] #![feature(linked_list_cursors)] #![feature(map_try_insert)] -#![feature(new_uninit)] #![feature(pattern)] #![feature(trusted_len)] #![feature(try_reserve_kind)] diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index 549a4bc6727..ad3f9d80878 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -6,7 +6,7 @@ use crate::error::Error; use crate::ptr::{Alignment, NonNull}; -use crate::{cmp, fmt, mem}; +use crate::{assert_unsafe_precondition, cmp, fmt, mem}; // While this function is used in one place and its implementation // could be inlined, the previous attempts to do so made rustc @@ -66,12 +66,20 @@ impl Layout { #[inline] #[rustc_allow_const_fn_unstable(ptr_alignment_type)] pub const fn from_size_align(size: usize, align: usize) -> Result { - if !align.is_power_of_two() { - return Err(LayoutError); + if Layout::is_size_align_valid(size, align) { + // SAFETY: Layout::is_size_align_valid checks the preconditions for this call. + unsafe { Ok(Layout { size, align: mem::transmute(align) }) } + } else { + Err(LayoutError) } + } - // SAFETY: just checked that align is a power of two. - Layout::from_size_alignment(size, unsafe { Alignment::new_unchecked(align) }) + const fn is_size_align_valid(size: usize, align: usize) -> bool { + let Some(align) = Alignment::new(align) else { return false }; + if size > Self::max_size_for_align(align) { + return false; + } + true } #[inline(always)] @@ -116,8 +124,17 @@ impl Layout { #[inline] #[rustc_allow_const_fn_unstable(ptr_alignment_type)] pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self { + assert_unsafe_precondition!( + check_library_ub, + "Layout::from_size_align_unchecked requires that align is a power of 2 \ + and the rounded-up allocation size does not exceed isize::MAX", + ( + size: usize = size, + align: usize = align, + ) => Layout::is_size_align_valid(size, align) + ); // SAFETY: the caller is required to uphold the preconditions. - unsafe { Layout { size, align: Alignment::new_unchecked(align) } } + unsafe { Layout { size, align: mem::transmute(align) } } } /// The minimum size in bytes for a memory block of this layout. diff --git a/library/core/src/ascii/ascii_char.rs b/library/core/src/ascii/ascii_char.rs index 375358dddf5..ce09a0b444d 100644 --- a/library/core/src/ascii/ascii_char.rs +++ b/library/core/src/ascii/ascii_char.rs @@ -3,8 +3,8 @@ //! suggestions from rustc if you get anything slightly wrong in here, and overall //! helps with clarity as we're also referring to `char` intentionally in here. -use crate::fmt; use crate::mem::transmute; +use crate::{assert_unsafe_precondition, fmt}; /// One of the 128 Unicode characters from U+0000 through U+007F, /// often known as the [ASCII] subset. @@ -497,14 +497,18 @@ impl AsciiChar { /// Notably, it should not be expected to return hex digits, or any other /// reasonable extension of the decimal digits. /// - /// (This lose safety condition is intended to simplify soundness proofs + /// (This loose safety condition is intended to simplify soundness proofs /// when writing code using this method, since the implementation doesn't /// need something really specific, not to make those other arguments do /// something useful. It might be tightened before stabilization.) #[unstable(feature = "ascii_char", issue = "110998")] #[inline] pub const unsafe fn digit_unchecked(d: u8) -> Self { - debug_assert!(d < 10); + assert_unsafe_precondition!( + check_language_ub, + "`AsciiChar::digit_unchecked` input cannot exceed 9.", + (d: u8 = d) => d < 10 + ); // SAFETY: `'0'` through `'9'` are U+00030 through U+0039, // so because `d` must be 64 or less the addition can return at most diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index d860f3415d9..5dd9721d3fe 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -306,6 +306,7 @@ pub use once::OnceCell; /// See the [module-level documentation](self) for more. #[stable(feature = "rust1", since = "1.0.0")] #[repr(transparent)] +#[cfg_attr(not(bootstrap), rustc_pub_transparent)] pub struct Cell { value: UnsafeCell, } @@ -2055,6 +2056,7 @@ impl fmt::Display for RefMut<'_, T> { #[lang = "unsafe_cell"] #[stable(feature = "rust1", since = "1.0.0")] #[repr(transparent)] +#[cfg_attr(not(bootstrap), rustc_pub_transparent)] pub struct UnsafeCell { value: T, } @@ -2297,6 +2299,7 @@ impl UnsafeCell<*mut T> { /// See [`UnsafeCell`] for details. #[unstable(feature = "sync_unsafe_cell", issue = "95439")] #[repr(transparent)] +#[cfg_attr(not(bootstrap), rustc_pub_transparent)] pub struct SyncUnsafeCell { value: UnsafeCell, } diff --git a/library/core/src/cell/once.rs b/library/core/src/cell/once.rs index 097fa86c938..87df8a4e272 100644 --- a/library/core/src/cell/once.rs +++ b/library/core/src/cell/once.rs @@ -309,7 +309,8 @@ impl OnceCell { /// ``` #[inline] #[stable(feature = "once_cell", since = "1.70.0")] - pub fn into_inner(self) -> Option { + #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "78729")] + pub const fn into_inner(self) -> Option { // Because `into_inner` takes `self` by value, the compiler statically verifies // that it is not currently borrowed. So it is safe to move out `Option`. self.inner.into_inner() diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index 76a89eaaff8..21504630672 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -36,8 +36,7 @@ #![stable(feature = "rust1", since = "1.0.0")] -use crate::mem::{self, MaybeUninit}; -use crate::ptr; +mod uninit; /// A common trait for the ability to explicitly duplicate an object. /// @@ -248,7 +247,7 @@ pub unsafe trait CloneToUninit { /// * `dst` must be properly aligned. /// * `dst` must have the same [pointer metadata] (slice length or `dyn` vtable) as `self`. /// - /// [valid]: ptr#safety + /// [valid]: crate::ptr#safety /// [pointer metadata]: crate::ptr::metadata() /// /// # Panics @@ -272,124 +271,42 @@ pub unsafe trait CloneToUninit { #[unstable(feature = "clone_to_uninit", issue = "126799")] unsafe impl CloneToUninit for T { - default unsafe fn clone_to_uninit(&self, dst: *mut Self) { - // SAFETY: The safety conditions of clone_to_uninit() are a superset of those of - // ptr::write(). - unsafe { - // We hope the optimizer will figure out to create the cloned value in-place, - // skipping ever storing it on the stack and the copy to the destination. - ptr::write(dst, self.clone()); - } - } -} - -// Specialized implementation for types that are [`Copy`], not just [`Clone`], -// and can therefore be copied bitwise. -#[unstable(feature = "clone_to_uninit", issue = "126799")] -unsafe impl CloneToUninit for T { + #[inline] unsafe fn clone_to_uninit(&self, dst: *mut Self) { - // SAFETY: The safety conditions of clone_to_uninit() are a superset of those of - // ptr::copy_nonoverlapping(). - unsafe { - ptr::copy_nonoverlapping(self, dst, 1); - } + // SAFETY: we're calling a specialization with the same contract + unsafe { ::clone_one(self, dst) } } } #[unstable(feature = "clone_to_uninit", issue = "126799")] unsafe impl CloneToUninit for [T] { + #[inline] #[cfg_attr(debug_assertions, track_caller)] - default unsafe fn clone_to_uninit(&self, dst: *mut Self) { - let len = self.len(); - // This is the most likely mistake to make, so check it as a debug assertion. - debug_assert_eq!( - len, - dst.len(), - "clone_to_uninit() source and destination must have equal lengths", - ); - - // SAFETY: The produced `&mut` is valid because: - // * The caller is obligated to provide a pointer which is valid for writes. - // * All bytes pointed to are in MaybeUninit, so we don't care about the memory's - // initialization status. - let uninit_ref = unsafe { &mut *(dst as *mut [MaybeUninit]) }; - - // Copy the elements - let mut initializing = InitializingSlice::from_fully_uninit(uninit_ref); - for element_ref in self.iter() { - // If the clone() panics, `initializing` will take care of the cleanup. - initializing.push(element_ref.clone()); - } - // If we reach here, then the entire slice is initialized, and we've satisfied our - // responsibilities to the caller. Disarm the cleanup guard by forgetting it. - mem::forget(initializing); + unsafe fn clone_to_uninit(&self, dst: *mut Self) { + // SAFETY: we're calling a specialization with the same contract + unsafe { ::clone_slice(self, dst) } } } #[unstable(feature = "clone_to_uninit", issue = "126799")] -unsafe impl CloneToUninit for [T] { +unsafe impl CloneToUninit for str { + #[inline] #[cfg_attr(debug_assertions, track_caller)] unsafe fn clone_to_uninit(&self, dst: *mut Self) { - let len = self.len(); - // This is the most likely mistake to make, so check it as a debug assertion. - debug_assert_eq!( - len, - dst.len(), - "clone_to_uninit() source and destination must have equal lengths", - ); - - // SAFETY: The safety conditions of clone_to_uninit() are a superset of those of - // ptr::copy_nonoverlapping(). - unsafe { - ptr::copy_nonoverlapping(self.as_ptr(), dst.as_mut_ptr(), len); - } + // SAFETY: str is just a [u8] with UTF-8 invariant + unsafe { self.as_bytes().clone_to_uninit(dst as *mut [u8]) } } } -/// Ownership of a collection of values stored in a non-owned `[MaybeUninit]`, some of which -/// are not yet initialized. This is sort of like a `Vec` that doesn't own its allocation. -/// Its responsibility is to provide cleanup on unwind by dropping the values that *are* -/// initialized, unless disarmed by forgetting. -/// -/// This is a helper for `impl CloneToUninit for [T]`. -struct InitializingSlice<'a, T> { - data: &'a mut [MaybeUninit], - /// Number of elements of `*self.data` that are initialized. - initialized_len: usize, -} - -impl<'a, T> InitializingSlice<'a, T> { - #[inline] - fn from_fully_uninit(data: &'a mut [MaybeUninit]) -> Self { - Self { data, initialized_len: 0 } - } - - /// Push a value onto the end of the initialized part of the slice. - /// - /// # Panics - /// - /// Panics if the slice is already fully initialized. - #[inline] - fn push(&mut self, value: T) { - MaybeUninit::write(&mut self.data[self.initialized_len], value); - self.initialized_len += 1; - } -} - -impl<'a, T> Drop for InitializingSlice<'a, T> { - #[cold] // will only be invoked on unwind - fn drop(&mut self) { - let initialized_slice = ptr::slice_from_raw_parts_mut( - MaybeUninit::slice_as_mut_ptr(self.data), - self.initialized_len, - ); - // SAFETY: - // * the pointer is valid because it was made from a mutable reference - // * `initialized_len` counts the initialized elements as an invariant of this type, - // so each of the pointed-to elements is initialized and may be dropped. - unsafe { - ptr::drop_in_place::<[T]>(initialized_slice); - } +#[unstable(feature = "clone_to_uninit", issue = "126799")] +unsafe impl CloneToUninit for crate::ffi::CStr { + #[cfg_attr(debug_assertions, track_caller)] + unsafe fn clone_to_uninit(&self, dst: *mut Self) { + // SAFETY: For now, CStr is just a #[repr(trasnsparent)] [c_char] with some invariants. + // And we can cast [c_char] to [u8] on all supported platforms (see: to_bytes_with_nul). + // The pointer metadata properly preserves the length (NUL included). + // See: `cstr_metadata_is_length_with_nul` in tests. + unsafe { self.to_bytes_with_nul().clone_to_uninit(dst as *mut [u8]) } } } diff --git a/library/core/src/clone/uninit.rs b/library/core/src/clone/uninit.rs new file mode 100644 index 00000000000..8b738bec796 --- /dev/null +++ b/library/core/src/clone/uninit.rs @@ -0,0 +1,128 @@ +use crate::mem::{self, MaybeUninit}; +use crate::ptr; + +/// Private specialization trait used by CloneToUninit, as per +/// [the dev guide](https://std-dev-guide.rust-lang.org/policy/specialization.html). +pub(super) unsafe trait CopySpec: Clone { + unsafe fn clone_one(src: &Self, dst: *mut Self); + unsafe fn clone_slice(src: &[Self], dst: *mut [Self]); +} + +unsafe impl CopySpec for T { + #[inline] + default unsafe fn clone_one(src: &Self, dst: *mut Self) { + // SAFETY: The safety conditions of clone_to_uninit() are a superset of those of + // ptr::write(). + unsafe { + // We hope the optimizer will figure out to create the cloned value in-place, + // skipping ever storing it on the stack and the copy to the destination. + ptr::write(dst, src.clone()); + } + } + + #[inline] + #[cfg_attr(debug_assertions, track_caller)] + default unsafe fn clone_slice(src: &[Self], dst: *mut [Self]) { + let len = src.len(); + // This is the most likely mistake to make, so check it as a debug assertion. + debug_assert_eq!( + len, + dst.len(), + "clone_to_uninit() source and destination must have equal lengths", + ); + + // SAFETY: The produced `&mut` is valid because: + // * The caller is obligated to provide a pointer which is valid for writes. + // * All bytes pointed to are in MaybeUninit, so we don't care about the memory's + // initialization status. + let uninit_ref = unsafe { &mut *(dst as *mut [MaybeUninit]) }; + + // Copy the elements + let mut initializing = InitializingSlice::from_fully_uninit(uninit_ref); + for element_ref in src { + // If the clone() panics, `initializing` will take care of the cleanup. + initializing.push(element_ref.clone()); + } + // If we reach here, then the entire slice is initialized, and we've satisfied our + // responsibilities to the caller. Disarm the cleanup guard by forgetting it. + mem::forget(initializing); + } +} + +// Specialized implementation for types that are [`Copy`], not just [`Clone`], +// and can therefore be copied bitwise. +unsafe impl CopySpec for T { + #[inline] + unsafe fn clone_one(src: &Self, dst: *mut Self) { + // SAFETY: The safety conditions of clone_to_uninit() are a superset of those of + // ptr::copy_nonoverlapping(). + unsafe { + ptr::copy_nonoverlapping(src, dst, 1); + } + } + + #[inline] + #[cfg_attr(debug_assertions, track_caller)] + unsafe fn clone_slice(src: &[Self], dst: *mut [Self]) { + let len = src.len(); + // This is the most likely mistake to make, so check it as a debug assertion. + debug_assert_eq!( + len, + dst.len(), + "clone_to_uninit() source and destination must have equal lengths", + ); + + // SAFETY: The safety conditions of clone_to_uninit() are a superset of those of + // ptr::copy_nonoverlapping(). + unsafe { + ptr::copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr(), len); + } + } +} + +/// Ownership of a collection of values stored in a non-owned `[MaybeUninit]`, some of which +/// are not yet initialized. This is sort of like a `Vec` that doesn't own its allocation. +/// Its responsibility is to provide cleanup on unwind by dropping the values that *are* +/// initialized, unless disarmed by forgetting. +/// +/// This is a helper for `impl CloneToUninit for [T]`. +struct InitializingSlice<'a, T> { + data: &'a mut [MaybeUninit], + /// Number of elements of `*self.data` that are initialized. + initialized_len: usize, +} + +impl<'a, T> InitializingSlice<'a, T> { + #[inline] + fn from_fully_uninit(data: &'a mut [MaybeUninit]) -> Self { + Self { data, initialized_len: 0 } + } + + /// Push a value onto the end of the initialized part of the slice. + /// + /// # Panics + /// + /// Panics if the slice is already fully initialized. + #[inline] + fn push(&mut self, value: T) { + MaybeUninit::write(&mut self.data[self.initialized_len], value); + self.initialized_len += 1; + } +} + +impl<'a, T> Drop for InitializingSlice<'a, T> { + #[cold] // will only be invoked on unwind + fn drop(&mut self) { + let initialized_slice = ptr::slice_from_raw_parts_mut( + MaybeUninit::slice_as_mut_ptr(self.data), + self.initialized_len, + ); + // SAFETY: + // * the pointer is valid because it was made from a mutable reference + // * `initialized_len` counts the initialized elements as an invariant of this type, + // so each of the pointed-to elements is initialized and may be dropped. + unsafe { + ptr::drop_in_place::<[T]>(initialized_slice); + } + } +} diff --git a/library/core/src/error.rs b/library/core/src/error.rs index 6cc91849e1d..cac00b37d1f 100644 --- a/library/core/src/error.rs +++ b/library/core/src/error.rs @@ -1,9 +1,6 @@ #![doc = include_str!("error.md")] #![stable(feature = "error_in_core", since = "1.81.0")] -#[cfg(test)] -mod tests; - use crate::any::TypeId; use crate::fmt::{Debug, Display, Formatter, Result}; diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index 22084dcff8f..7808d42ab5d 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -91,6 +91,7 @@ use crate::{fmt, intrinsics, ops, slice, str}; /// [str]: prim@str "str" #[derive(PartialEq, Eq, Hash)] #[stable(feature = "core_c_str", since = "1.64.0")] +#[rustc_diagnostic_item = "cstr_type"] #[rustc_has_incoherent_inherent_impls] #[lang = "CStr"] // `fn from` in `impl From<&CStr> for Box` current implementation relies diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs index 467fa17a6f3..c7c462a4df1 100644 --- a/library/core/src/fmt/builders.rs +++ b/library/core/src/fmt/builders.rs @@ -78,7 +78,7 @@ impl fmt::Write for PadAdapter<'_, '_> { /// /// assert_eq!( /// format!("{:?}", Foo { bar: 10, baz: "Hello World".to_string() }), -/// "Foo { bar: 10, baz: \"Hello World\" }", +/// r#"Foo { bar: 10, baz: "Hello World" }"#, /// ); /// ``` #[must_use = "must eventually call `finish()` on Debug builders"] @@ -125,7 +125,7 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { /// /// assert_eq!( /// format!("{:?}", Bar { bar: 10, another: "Hello World".to_string() }), - /// "Bar { bar: 10, another: \"Hello World\", nonexistent_field: 1 }", + /// r#"Bar { bar: 10, another: "Hello World", nonexistent_field: 1 }"#, /// ); /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] @@ -237,7 +237,7 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { /// /// assert_eq!( /// format!("{:?}", Bar { bar: 10, baz: "Hello World".to_string() }), - /// "Bar { bar: 10, baz: \"Hello World\" }", + /// r#"Bar { bar: 10, baz: "Hello World" }"#, /// ); /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] @@ -280,7 +280,7 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { /// /// assert_eq!( /// format!("{:?}", Foo(10, "Hello World".to_string())), -/// "Foo(10, \"Hello World\")", +/// r#"Foo(10, "Hello World")"#, /// ); /// ``` #[must_use = "must eventually call `finish()` on Debug builders"] @@ -322,7 +322,7 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { /// /// assert_eq!( /// format!("{:?}", Foo(10, "Hello World".to_string())), - /// "Foo(10, \"Hello World\")", + /// r#"Foo(10, "Hello World")"#, /// ); /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] @@ -360,6 +360,51 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { self } + /// Marks the tuple struct as non-exhaustive, indicating to the reader that there are some + /// other fields that are not shown in the debug representation. + /// + /// # Examples + /// + /// ``` + /// #![feature(debug_more_non_exhaustive)] + /// + /// use std::fmt; + /// + /// struct Foo(i32, String); + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// fmt.debug_tuple("Foo") + /// .field(&self.0) + /// .finish_non_exhaustive() // Show that some other field(s) exist. + /// } + /// } + /// + /// assert_eq!( + /// format!("{:?}", Foo(10, "secret!".to_owned())), + /// "Foo(10, ..)", + /// ); + /// ``` + #[unstable(feature = "debug_more_non_exhaustive", issue = "127942")] + pub fn finish_non_exhaustive(&mut self) -> fmt::Result { + self.result = self.result.and_then(|_| { + if self.fields > 0 { + if self.is_pretty() { + let mut slot = None; + let mut state = Default::default(); + let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state); + writer.write_str("..\n")?; + self.fmt.write_str(")") + } else { + self.fmt.write_str(", ..)") + } + } else { + self.fmt.write_str("(..)") + } + }); + self.result + } + /// Finishes output and returns any error encountered. /// /// # Examples @@ -381,7 +426,7 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { /// /// assert_eq!( /// format!("{:?}", Foo(10, "Hello World".to_string())), - /// "Foo(10, \"Hello World\")", + /// r#"Foo(10, "Hello World")"#, /// ); /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] @@ -555,6 +600,56 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> { self } + /// Marks the set as non-exhaustive, indicating to the reader that there are some other + /// elements that are not shown in the debug representation. + /// + /// # Examples + /// + /// ``` + /// #![feature(debug_more_non_exhaustive)] + /// + /// use std::fmt; + /// + /// struct Foo(Vec); + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// // Print at most two elements, abbreviate the rest + /// let mut f = fmt.debug_set(); + /// let mut f = f.entries(self.0.iter().take(2)); + /// if self.0.len() > 2 { + /// f.finish_non_exhaustive() + /// } else { + /// f.finish() + /// } + /// } + /// } + /// + /// assert_eq!( + /// format!("{:?}", Foo(vec![1, 2, 3, 4])), + /// "{1, 2, ..}", + /// ); + /// ``` + #[unstable(feature = "debug_more_non_exhaustive", issue = "127942")] + pub fn finish_non_exhaustive(&mut self) -> fmt::Result { + self.inner.result = self.inner.result.and_then(|_| { + if self.inner.has_fields { + if self.inner.is_pretty() { + let mut slot = None; + let mut state = Default::default(); + let mut writer = PadAdapter::wrap(self.inner.fmt, &mut slot, &mut state); + writer.write_str("..\n")?; + self.inner.fmt.write_str("}") + } else { + self.inner.fmt.write_str(", ..}") + } + } else { + self.inner.fmt.write_str("..}") + } + }); + self.inner.result + } + /// Finishes output and returns any error encountered. /// /// # Examples @@ -699,6 +794,55 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> { self } + /// Marks the list as non-exhaustive, indicating to the reader that there are some other + /// elements that are not shown in the debug representation. + /// + /// # Examples + /// + /// ``` + /// #![feature(debug_more_non_exhaustive)] + /// + /// use std::fmt; + /// + /// struct Foo(Vec); + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// // Print at most two elements, abbreviate the rest + /// let mut f = fmt.debug_list(); + /// let mut f = f.entries(self.0.iter().take(2)); + /// if self.0.len() > 2 { + /// f.finish_non_exhaustive() + /// } else { + /// f.finish() + /// } + /// } + /// } + /// + /// assert_eq!( + /// format!("{:?}", Foo(vec![1, 2, 3, 4])), + /// "[1, 2, ..]", + /// ); + /// ``` + #[unstable(feature = "debug_more_non_exhaustive", issue = "127942")] + pub fn finish_non_exhaustive(&mut self) -> fmt::Result { + self.inner.result.and_then(|_| { + if self.inner.has_fields { + if self.inner.is_pretty() { + let mut slot = None; + let mut state = Default::default(); + let mut writer = PadAdapter::wrap(self.inner.fmt, &mut slot, &mut state); + writer.write_str("..\n")?; + self.inner.fmt.write_str("]") + } else { + self.inner.fmt.write_str(", ..]") + } + } else { + self.inner.fmt.write_str("..]") + } + }) + } + /// Finishes output and returns any error encountered. /// /// # Examples @@ -750,7 +894,7 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> { /// /// assert_eq!( /// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])), -/// "{\"A\": 10, \"B\": 11}", +/// r#"{"A": 10, "B": 11}"#, /// ); /// ``` #[must_use = "must eventually call `finish()` on Debug builders"] @@ -790,7 +934,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// /// assert_eq!( /// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])), - /// "{\"whole\": [(\"A\", 10), (\"B\", 11)]}", + /// r#"{"whole": [("A", 10), ("B", 11)]}"#, /// ); /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] @@ -826,7 +970,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// /// assert_eq!( /// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])), - /// "{\"whole\": [(\"A\", 10), (\"B\", 11)]}", + /// r#"{"whole": [("A", 10), ("B", 11)]}"#, /// ); /// ``` #[stable(feature = "debug_map_key_value", since = "1.42.0")] @@ -902,7 +1046,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// /// assert_eq!( /// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])), - /// "{\"whole\": [(\"A\", 10), (\"B\", 11)]}", + /// r#"{"whole": [("A", 10), ("B", 11)]}"#, /// ); /// ``` #[stable(feature = "debug_map_key_value", since = "1.42.0")] @@ -960,7 +1104,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// /// assert_eq!( /// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])), - /// "{\"A\": 10, \"B\": 11}", + /// r#"{"A": 10, "B": 11}"#, /// ); /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] @@ -976,6 +1120,62 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { self } + /// Marks the map as non-exhaustive, indicating to the reader that there are some other + /// entries that are not shown in the debug representation. + /// + /// # Examples + /// + /// ``` + /// #![feature(debug_more_non_exhaustive)] + /// + /// use std::fmt; + /// + /// struct Foo(Vec<(String, i32)>); + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// // Print at most two elements, abbreviate the rest + /// let mut f = fmt.debug_map(); + /// let mut f = f.entries(self.0.iter().take(2).map(|&(ref k, ref v)| (k, v))); + /// if self.0.len() > 2 { + /// f.finish_non_exhaustive() + /// } else { + /// f.finish() + /// } + /// } + /// } + /// + /// assert_eq!( + /// format!("{:?}", Foo(vec![ + /// ("A".to_string(), 10), + /// ("B".to_string(), 11), + /// ("C".to_string(), 12), + /// ])), + /// r#"{"A": 10, "B": 11, ..}"#, + /// ); + /// ``` + #[unstable(feature = "debug_more_non_exhaustive", issue = "127942")] + pub fn finish_non_exhaustive(&mut self) -> fmt::Result { + self.result = self.result.and_then(|_| { + assert!(!self.has_key, "attempted to finish a map with a partial entry"); + + if self.has_fields { + if self.is_pretty() { + let mut slot = None; + let mut state = Default::default(); + let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state); + writer.write_str("..\n")?; + self.fmt.write_str("}") + } else { + self.fmt.write_str(", ..}") + } + } else { + self.fmt.write_str("..}") + } + }); + self.result + } + /// Finishes output and returns any error encountered. /// /// # Panics @@ -1000,7 +1200,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// /// assert_eq!( /// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])), - /// "{\"A\": 10, \"B\": 11}", + /// r#"{"A": 10, "B": 11}"#, /// ); /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 485ad4aee19..45c2b6a6a0f 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -1626,6 +1626,11 @@ impl<'a> Formatter<'a> { self.buf.write_str(data) } + /// Glue for usage of the [`write!`] macro with implementors of this trait. + /// + /// This method should generally not be invoked manually, but rather through + /// the [`write!`] macro itself. + /// /// Writes some formatted information into this instance. /// /// # Examples diff --git a/library/core/src/future/ready.rs b/library/core/src/future/ready.rs index a07b63fb62b..6f6da8ce51d 100644 --- a/library/core/src/future/ready.rs +++ b/library/core/src/future/ready.rs @@ -34,13 +34,12 @@ impl Ready { /// # Examples /// /// ``` - /// #![feature(ready_into_inner)] /// use std::future; /// /// let a = future::ready(1); /// assert_eq!(a.into_inner(), 1); /// ``` - #[unstable(feature = "ready_into_inner", issue = "101196")] + #[stable(feature = "ready_into_inner", since = "CURRENT_RUSTC_VERSION")] #[must_use] #[inline] pub fn into_inner(self) -> T { diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index bd99e90376a..8cb9accd59d 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2949,7 +2949,7 @@ pub const unsafe fn typed_swap(x: *mut T, y: *mut T) { /// sysroot which is built without ub_checks but with `#[rustc_preserve_ub_checks]`. /// For code that gets monomorphized in the user crate (i.e., generic functions and functions with /// `#[inline]`), gating assertions on `ub_checks()` rather than `cfg!(ub_checks)` means that -/// assertions are enabled whenever the *user crate* has UB checks enabled. However if the +/// assertions are enabled whenever the *user crate* has UB checks enabled. However, if the /// user has UB checks disabled, the checks will still get optimized out. This intrinsic is /// primarily used by [`ub_checks::assert_unsafe_precondition`]. #[rustc_const_unstable(feature = "const_ub_checks", issue = "none")] @@ -2957,7 +2957,7 @@ pub const unsafe fn typed_swap(x: *mut T, y: *mut T) { #[inline(always)] #[rustc_intrinsic] pub const fn ub_checks() -> bool { - cfg!(debug_assertions) + cfg!(ub_checks) } /// Allocates a block of memory at compile time. diff --git a/library/core/src/intrinsics/simd.rs b/library/core/src/intrinsics/simd.rs index 221724d7b4a..59828198099 100644 --- a/library/core/src/intrinsics/simd.rs +++ b/library/core/src/intrinsics/simd.rs @@ -232,7 +232,7 @@ extern "rust-intrinsic" { /// /// `T` must be a vector. /// - /// `U` must be a **const** array of `i32`s. This means it must either refer to a named + /// `U` must be a **const** array or vector of `u32`s. This means it must either refer to a named /// const or be given as an inline const expression (`const { ... }`). /// /// `V` must be a vector with the same element type as `T` and the same length as `U`. diff --git a/library/core/src/iter/adapters/take.rs b/library/core/src/iter/adapters/take.rs index 297dd0acadd..4c8f9fe16da 100644 --- a/library/core/src/iter/adapters/take.rs +++ b/library/core/src/iter/adapters/take.rs @@ -317,3 +317,60 @@ impl SpecTake for Take { } } } + +#[stable(feature = "exact_size_take_repeat", since = "CURRENT_RUSTC_VERSION")] +impl DoubleEndedIterator for Take> { + #[inline] + fn next_back(&mut self) -> Option { + self.next() + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + self.nth(n) + } + + #[inline] + fn try_rfold(&mut self, init: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + self.try_fold(init, fold) + } + + #[inline] + fn rfold(self, init: Acc, fold: Fold) -> Acc + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.fold(init, fold) + } + + #[inline] + #[rustc_inherit_overflow_checks] + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + self.advance_by(n) + } +} + +// Note: It may be tempting to impl DoubleEndedIterator for Take. +// One must fight that temptation since such implementation wouldn’t be correct +// because we have no way to return value of nth invocation of repeater followed +// by n-1st without remembering all results. + +#[stable(feature = "exact_size_take_repeat", since = "CURRENT_RUSTC_VERSION")] +impl ExactSizeIterator for Take> { + fn len(&self) -> usize { + self.n + } +} + +#[stable(feature = "exact_size_take_repeat", since = "CURRENT_RUSTC_VERSION")] +impl A, A> ExactSizeIterator for Take> { + fn len(&self) -> usize { + self.n + } +} diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs index 1f2bf49d2b7..5dad9e1a75e 100644 --- a/library/core/src/iter/mod.rs +++ b/library/core/src/iter/mod.rs @@ -436,7 +436,7 @@ pub use self::sources::{once, Once}; pub use self::sources::{once_with, OnceWith}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::sources::{repeat, Repeat}; -#[unstable(feature = "iter_repeat_n", issue = "104434")] +#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")] pub use self::sources::{repeat_n, RepeatN}; #[stable(feature = "iterator_repeat_with", since = "1.28.0")] pub use self::sources::{repeat_with, RepeatWith}; diff --git a/library/core/src/iter/sources.rs b/library/core/src/iter/sources.rs index 6a94051b7c7..55901e1e50b 100644 --- a/library/core/src/iter/sources.rs +++ b/library/core/src/iter/sources.rs @@ -24,7 +24,7 @@ pub use self::once::{once, Once}; pub use self::once_with::{once_with, OnceWith}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::repeat::{repeat, Repeat}; -#[unstable(feature = "iter_repeat_n", issue = "104434")] +#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")] pub use self::repeat_n::{repeat_n, RepeatN}; #[stable(feature = "iterator_repeat_with", since = "1.28.0")] pub use self::repeat_with::{repeat_with, RepeatWith}; diff --git a/library/core/src/iter/sources/repeat_n.rs b/library/core/src/iter/sources/repeat_n.rs index 4c4ae39f836..2e247a34075 100644 --- a/library/core/src/iter/sources/repeat_n.rs +++ b/library/core/src/iter/sources/repeat_n.rs @@ -18,7 +18,6 @@ use crate::num::NonZero; /// Basic usage: /// /// ``` -/// #![feature(iter_repeat_n)] /// use std::iter; /// /// // four of the number four: @@ -36,7 +35,6 @@ use crate::num::NonZero; /// For non-`Copy` types, /// /// ``` -/// #![feature(iter_repeat_n)] /// use std::iter; /// /// let v: Vec = Vec::with_capacity(123); @@ -58,7 +56,7 @@ use crate::num::NonZero; /// assert_eq!(None, it.next()); /// ``` #[inline] -#[unstable(feature = "iter_repeat_n", issue = "104434")] +#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")] pub fn repeat_n(element: T, count: usize) -> RepeatN { let mut element = ManuallyDrop::new(element); @@ -77,7 +75,7 @@ pub fn repeat_n(element: T, count: usize) -> RepeatN { /// This `struct` is created by the [`repeat_n()`] function. /// See its documentation for more. #[derive(Clone, Debug)] -#[unstable(feature = "iter_repeat_n", issue = "104434")] +#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")] pub struct RepeatN { count: usize, // Invariant: has been dropped iff count == 0. @@ -101,14 +99,14 @@ impl RepeatN { } } -#[unstable(feature = "iter_repeat_n", issue = "104434")] +#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")] impl Drop for RepeatN { fn drop(&mut self) { self.take_element(); } } -#[unstable(feature = "iter_repeat_n", issue = "104434")] +#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")] impl Iterator for RepeatN { type Item = A; @@ -156,14 +154,14 @@ impl Iterator for RepeatN { } } -#[unstable(feature = "iter_repeat_n", issue = "104434")] +#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")] impl ExactSizeIterator for RepeatN { fn len(&self) -> usize { self.count } } -#[unstable(feature = "iter_repeat_n", issue = "104434")] +#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")] impl DoubleEndedIterator for RepeatN { #[inline] fn next_back(&mut self) -> Option { @@ -181,12 +179,12 @@ impl DoubleEndedIterator for RepeatN { } } -#[unstable(feature = "iter_repeat_n", issue = "104434")] +#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")] impl FusedIterator for RepeatN {} #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for RepeatN {} -#[unstable(feature = "trusted_len_next_unchecked", issue = "37572")] +#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")] impl UncheckedIterator for RepeatN { #[inline] unsafe fn next_unchecked(&mut self) -> Self::Item { diff --git a/library/core/src/iter/traits/accum.rs b/library/core/src/iter/traits/accum.rs index c97cd042ab4..5b7d95c2f65 100644 --- a/library/core/src/iter/traits/accum.rs +++ b/library/core/src/iter/traits/accum.rs @@ -104,7 +104,7 @@ macro_rules! float_sum_product { impl Sum for $a { fn sum>(iter: I) -> Self { iter.fold( - 0.0, + -0.0, #[rustc_inherit_overflow_checks] |a, b| a + b, ) @@ -126,7 +126,7 @@ macro_rules! float_sum_product { impl<'a> Sum<&'a $a> for $a { fn sum>(iter: I) -> Self { iter.fold( - 0.0, + -0.0, #[rustc_inherit_overflow_checks] |a, b| a + b, ) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 07daa32afa8..06a745b690a 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -110,7 +110,6 @@ #![cfg_attr(bootstrap, feature(offset_of_nested))] #![feature(array_ptr_get)] #![feature(asm_experimental_arch)] -#![feature(char_indices_offset)] #![feature(const_align_of_val)] #![feature(const_align_of_val_raw)] #![feature(const_align_offset)] @@ -170,6 +169,7 @@ #![feature(internal_impls_macro)] #![feature(ip)] #![feature(is_ascii_octdigit)] +#![feature(is_val_statically_known)] #![feature(isqrt)] #![feature(link_cfg)] #![feature(offset_of_enum)] @@ -192,17 +192,18 @@ // // Language features: // tidy-alphabetical-start +#![cfg_attr(bootstrap, feature(asm_const))] +#![cfg_attr(bootstrap, feature(const_fn_floating_point_arithmetic))] #![cfg_attr(bootstrap, feature(min_exhaustive_patterns))] #![feature(abi_unadjusted)] #![feature(adt_const_params)] #![feature(allow_internal_unsafe)] #![feature(allow_internal_unstable)] -#![feature(asm_const)] #![feature(auto_traits)] #![feature(cfg_sanitize)] #![feature(cfg_target_has_atomic)] #![feature(cfg_target_has_atomic_equal_alignment)] -#![feature(const_fn_floating_point_arithmetic)] +#![feature(cfg_ub_checks)] #![feature(const_for)] #![feature(const_mut_refs)] #![feature(const_precise_live_drops)] diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 6a83ec2eb1e..5654f5aa4b8 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -1060,7 +1060,7 @@ pub trait FnPtr: Copy + Clone { } /// Derive macro generating impls of traits related to smart pointers. -#[rustc_builtin_macro] +#[rustc_builtin_macro(SmartPointer, attributes(pointee))] #[allow_internal_unstable(dispatch_from_dyn, coerce_unsized, unsize)] #[unstable(feature = "derive_smart_pointer", issue = "123430")] pub macro SmartPointer($item:item) { @@ -1097,7 +1097,6 @@ pub mod effects { pub trait TyCompat {} impl TyCompat for T {} - impl TyCompat for Maybe {} impl TyCompat for T {} #[lang = "EffectsIntersection"] diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs index 00c837041b6..be5cee2e852 100644 --- a/library/core/src/mem/manually_drop.rs +++ b/library/core/src/mem/manually_drop.rs @@ -47,6 +47,7 @@ use crate::ptr; #[lang = "manually_drop"] #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(transparent)] +#[cfg_attr(not(bootstrap), rustc_pub_transparent)] pub struct ManuallyDrop { value: T, } diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index f920ab1792d..c308def2f57 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -237,6 +237,7 @@ use crate::{fmt, intrinsics, ptr, slice}; #[lang = "maybe_uninit"] #[derive(Copy)] #[repr(transparent)] +#[cfg_attr(not(bootstrap), rustc_pub_transparent)] pub union MaybeUninit { uninit: (), value: ManuallyDrop, diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 7a9ca4011be..e602b497d17 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -19,7 +19,7 @@ pub use maybe_uninit::MaybeUninit; mod transmutability; #[unstable(feature = "transmutability", issue = "99571")] -pub use transmutability::{Assume, BikeshedIntrinsicFrom}; +pub use transmutability::{Assume, TransmuteFrom}; #[stable(feature = "rust1", since = "1.0.0")] #[doc(inline)] diff --git a/library/core/src/mem/transmutability.rs b/library/core/src/mem/transmutability.rs index ea73c5b80ba..049b32ede9c 100644 --- a/library/core/src/mem/transmutability.rs +++ b/library/core/src/mem/transmutability.rs @@ -1,40 +1,295 @@ use crate::marker::{ConstParamTy_, UnsizedConstParamTy}; -/// Are values of a type transmutable into values of another type? +/// Marks that `Src` is transmutable into `Self`. /// -/// This trait is implemented on-the-fly by the compiler for types `Src` and `Self` when the bits of -/// any value of type `Self` are safely transmutable into a value of type `Dst`, in a given `Context`, -/// notwithstanding whatever safety checks you have asked the compiler to [`Assume`] are satisfied. +/// # Implementation +/// +/// This trait cannot be implemented explicitly. It is implemented on-the-fly by +/// the compiler for all types `Src` and `Self` such that, given a set of safety +/// obligations on the programmer (see [`Assume`]), the compiler has proved that +/// the bits of a value of type `Src` can be soundly reinterpreted as a `Self`. +/// +/// # Safety +/// +/// If `Dst: TransmuteFrom`, the compiler guarantees that +/// `Src` is soundly *union-transmutable* into a value of type `Dst`, provided +/// that the programmer has guaranteed that the given [`ASSUMPTIONS`](Assume) +/// are satisfied. +/// +/// A union-transmute is any bit-reinterpretation conversion in the form of: +/// +/// ```rust +/// pub unsafe fn transmute_via_union(src: Src) -> Dst { +/// use core::mem::ManuallyDrop; +/// +/// #[repr(C)] +/// union Transmute { +/// src: ManuallyDrop, +/// dst: ManuallyDrop, +/// } +/// +/// let transmute = Transmute { +/// src: ManuallyDrop::new(src), +/// }; +/// +/// let dst = transmute.dst; +/// +/// ManuallyDrop::into_inner(dst) +/// } +/// ``` +/// +/// Note that this construction is more permissive than +/// [`mem::transmute_copy`](super::transmute_copy); union-transmutes permit +/// conversions that extend the bits of `Src` with trailing padding to fill +/// trailing uninitialized bytes of `Self`; e.g.: +/// +#[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")] +#[cfg_attr(not(bootstrap), doc = "```rust")] +/// #![feature(transmutability)] +/// +/// use core::mem::{Assume, TransmuteFrom}; +/// +/// let src = 42u8; // size = 1 +/// +/// #[repr(C, align(2))] +/// struct Dst(u8); // size = 2 +// +/// let _ = unsafe { +/// >::transmute(src) +/// }; +/// ``` +/// +/// # Caveats +/// +/// ## Portability +/// +/// Implementations of this trait do not provide any guarantee of portability +/// across toolchains, targets or compilations. This trait may be implemented +/// for certain combinations of `Src`, `Self` and `ASSUME` on some toolchains, +/// targets or compilations, but not others. For example, if the layouts of +/// `Src` or `Self` are non-deterministic, the presence or absence of an +/// implementation of this trait may also be non-deterministic. Even if `Src` +/// and `Self` have deterministic layouts (e.g., they are `repr(C)` structs), +/// Rust does not specify the alignments of its primitive integer types, and +/// layouts that involve these types may vary across toolchains, targets or +/// compilations. +/// +/// ## Stability +/// +/// Implementations of this trait do not provide any guarantee of SemVer +/// stability across the crate versions that define the `Src` and `Self` types. +/// If SemVer stability is crucial to your application, you must consult the +/// documentation of `Src` and `Self`s' defining crates. Note that the presence +/// of `repr(C)`, alone, does not carry a safety invariant of SemVer stability. +/// Furthermore, stability does not imply portability. For example, the size of +/// `usize` is stable, but not portable. #[unstable(feature = "transmutability", issue = "99571")] #[lang = "transmute_trait"] #[rustc_deny_explicit_impl(implement_via_object = false)] #[rustc_coinductive] -pub unsafe trait BikeshedIntrinsicFrom +pub unsafe trait TransmuteFrom where Src: ?Sized, { + /// Transmutes a `Src` value into a `Self`. + /// + /// # Safety + /// + /// The safety obligations of the caller depend on the value of `ASSUME`: + /// - If [`ASSUME.alignment`](Assume::alignment), the caller must guarantee + /// that the addresses of references in the returned `Self` satisfy the + /// alignment requirements of their referent types. + /// - If [`ASSUME.lifetimes`](Assume::lifetimes), the caller must guarantee + /// that references in the returned `Self` will not outlive their + /// referents. + /// - If [`ASSUME.safety`](Assume::safety), the returned value might not + /// satisfy the library safety invariants of `Self`, and the caller must + /// guarantee that undefined behavior does not arise from uses of the + /// returned value. + /// - If [`ASSUME.validity`](Assume::validity), the caller must guarantee + /// that `src` is a bit-valid instance of `Self`. + /// + /// When satisfying the above obligations (if any), the caller must *not* + /// assume that this trait provides any inherent guarantee of layout + /// [portability](#portability) or [stability](#stability). + unsafe fn transmute(src: Src) -> Self + where + Src: Sized, + Self: Sized, + { + use super::ManuallyDrop; + + #[repr(C)] + union Transmute { + src: ManuallyDrop, + dst: ManuallyDrop, + } + + let transmute = Transmute { src: ManuallyDrop::new(src) }; + + // SAFETY: It is safe to reinterpret the bits of `src` as a value of + // type `Self`, because, by combination of invariant on this trait and + // contract on the caller, `src` has been proven to satisfy both the + // language and library invariants of `Self`. For all invariants not + // `ASSUME`'d by the caller, the safety obligation is supplied by the + // compiler. Conversely, for all invariants `ASSUME`'d by the caller, + // the safety obligation is supplied by contract on the caller. + let dst = unsafe { transmute.dst }; + + ManuallyDrop::into_inner(dst) + } } -/// What transmutation safety conditions shall the compiler assume that *you* are checking? +/// Configurable proof assumptions of [`TransmuteFrom`]. +/// +/// When `false`, the respective proof obligation belongs to the compiler. When +/// `true`, the onus of the safety proof belongs to the programmer. #[unstable(feature = "transmutability", issue = "99571")] #[lang = "transmute_opts"] #[derive(PartialEq, Eq, Clone, Copy, Debug)] pub struct Assume { - /// When `true`, the compiler assumes that *you* are ensuring (either dynamically or statically) that - /// destination referents do not have stricter alignment requirements than source referents. + /// When `false`, [`TransmuteFrom`] is not implemented for transmutations + /// that might violate the the alignment requirements of references; e.g.: + /// + #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")] + #[cfg_attr(not(bootstrap), doc = "```compile_fail,E0277")] + /// #![feature(transmutability)] + /// use core::mem::{align_of, TransmuteFrom}; + /// + /// assert_eq!(align_of::<[u8; 2]>(), 1); + /// assert_eq!(align_of::(), 2); + /// + /// let src: &[u8; 2] = &[0xFF, 0xFF]; + /// + /// // SAFETY: No safety obligations. + /// let dst: &u16 = unsafe { + /// <_ as TransmuteFrom<_>>::transmute(src) + /// }; + /// ``` + /// + /// When `true`, [`TransmuteFrom`] assumes that *you* have ensured + /// that references in the transmuted value satisfy the alignment + /// requirements of their referent types; e.g.: + /// + #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")] + #[cfg_attr(not(bootstrap), doc = "```rust")] + /// #![feature(pointer_is_aligned_to, transmutability)] + /// use core::mem::{align_of, Assume, TransmuteFrom}; + /// + /// let src: &[u8; 2] = &[0xFF, 0xFF]; + /// + /// let maybe_dst: Option<&u16> = if <*const _>::is_aligned_to(src, align_of::()) { + /// // SAFETY: We have checked above that the address of `src` satisfies the + /// // alignment requirements of `u16`. + /// Some(unsafe { + /// <_ as TransmuteFrom<_, { Assume::ALIGNMENT }>>::transmute(src) + /// }) + /// } else { + /// None + /// }; + /// + /// assert!(matches!(maybe_dst, Some(&u16::MAX) | None)); + /// ``` pub alignment: bool, - /// When `true`, the compiler assume that *you* are ensuring that lifetimes are not extended in a manner - /// that violates Rust's memory model. + /// When `false`, [`TransmuteFrom`] is not implemented for transmutations + /// that extend the lifetimes of references. + /// + /// When `true`, [`TransmuteFrom`] assumes that *you* have ensured that + /// references in the transmuted value do not outlive their referents. pub lifetimes: bool, - /// When `true`, the compiler assumes that *you* have ensured that no - /// unsoundness will arise from violating the safety invariants of the - /// destination type (and sometimes of the source type, too). + /// When `false`, [`TransmuteFrom`] is not implemented for transmutations + /// that might violate the library safety invariants of the destination + /// type; e.g.: + /// + #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")] + #[cfg_attr(not(bootstrap), doc = "```compile_fail,E0277")] + /// #![feature(transmutability)] + /// use core::mem::TransmuteFrom; + /// + /// let src: u8 = 3; + /// + /// struct EvenU8 { + /// // SAFETY: `val` must be an even number. + /// val: u8, + /// } + /// + /// // SAFETY: No safety obligations. + /// let dst: EvenU8 = unsafe { + /// <_ as TransmuteFrom<_>>::transmute(src) + /// }; + /// ``` + /// + /// When `true`, [`TransmuteFrom`] assumes that *you* have ensured + /// that undefined behavior does not arise from using the transmuted value; + /// e.g.: + /// + #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")] + #[cfg_attr(not(bootstrap), doc = "```rust")] + /// #![feature(transmutability)] + /// use core::mem::{Assume, TransmuteFrom}; + /// + /// let src: u8 = 42; + /// + /// struct EvenU8 { + /// // SAFETY: `val` must be an even number. + /// val: u8, + /// } + /// + /// let maybe_dst: Option = if src % 2 == 0 { + /// // SAFETY: We have checked above that the value of `src` is even. + /// Some(unsafe { + /// <_ as TransmuteFrom<_, { Assume::SAFETY }>>::transmute(src) + /// }) + /// } else { + /// None + /// }; + /// + /// assert!(matches!(maybe_dst, Some(EvenU8 { val: 42 }))); + /// ``` pub safety: bool, - /// When `true`, the compiler assumes that *you* are ensuring that the source type is actually a valid - /// instance of the destination type. + /// When `false`, [`TransmuteFrom`] is not implemented for transmutations + /// that might violate the language-level bit-validity invariant of the + /// destination type; e.g.: + /// + #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")] + #[cfg_attr(not(bootstrap), doc = "```compile_fail,E0277")] + /// #![feature(transmutability)] + /// use core::mem::TransmuteFrom; + /// + /// let src: u8 = 3; + /// + /// // SAFETY: No safety obligations. + /// let dst: bool = unsafe { + /// <_ as TransmuteFrom<_>>::transmute(src) + /// }; + /// ``` + /// + /// When `true`, [`TransmuteFrom`] assumes that *you* have ensured + /// that the value being transmuted is a bit-valid instance of the + /// transmuted value; e.g.: + /// + #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")] + #[cfg_attr(not(bootstrap), doc = "```rust")] + /// #![feature(transmutability)] + /// use core::mem::{Assume, TransmuteFrom}; + /// + /// let src: u8 = 1; + /// + /// let maybe_dst: Option = if src == 0 || src == 1 { + /// // SAFETY: We have checked above that the value of `src` is a bit-valid + /// // instance of `bool`. + /// Some(unsafe { + /// <_ as TransmuteFrom<_, { Assume::VALIDITY }>>::transmute(src) + /// }) + /// } else { + /// None + /// }; + /// + /// assert_eq!(maybe_dst, Some(true)); + /// ``` pub validity: bool, } @@ -44,29 +299,86 @@ impl ConstParamTy_ for Assume {} impl UnsizedConstParamTy for Assume {} impl Assume { - /// Do not assume that *you* have ensured any safety properties are met. + /// With this, [`TransmuteFrom`] does not assume you have ensured any safety + /// obligations are met, and relies only upon its own analysis to (dis)prove + /// transmutability. #[unstable(feature = "transmutability", issue = "99571")] pub const NOTHING: Self = Self { alignment: false, lifetimes: false, safety: false, validity: false }; - /// Assume only that alignment conditions are met. + /// With this, [`TransmuteFrom`] assumes only that you have ensured that + /// references in the transmuted value satisfy the alignment requirements of + /// their referent types. See [`Assume::alignment`] for examples. #[unstable(feature = "transmutability", issue = "99571")] pub const ALIGNMENT: Self = Self { alignment: true, ..Self::NOTHING }; - /// Assume only that lifetime conditions are met. + /// With this, [`TransmuteFrom`] assumes only that you have ensured that + /// references in the transmuted value do not outlive their referents. See + /// [`Assume::lifetimes`] for examples. #[unstable(feature = "transmutability", issue = "99571")] pub const LIFETIMES: Self = Self { lifetimes: true, ..Self::NOTHING }; - /// Assume only that safety conditions are met. + /// With this, [`TransmuteFrom`] assumes only that you have ensured that + /// undefined behavior does not arise from using the transmuted value. See + /// [`Assume::safety`] for examples. #[unstable(feature = "transmutability", issue = "99571")] pub const SAFETY: Self = Self { safety: true, ..Self::NOTHING }; - /// Assume only that dynamically-satisfiable validity conditions are met. + /// With this, [`TransmuteFrom`] assumes only that you have ensured that the + /// value being transmuted is a bit-valid instance of the transmuted value. + /// See [`Assume::validity`] for examples. #[unstable(feature = "transmutability", issue = "99571")] pub const VALIDITY: Self = Self { validity: true, ..Self::NOTHING }; - /// Assume both `self` and `other_assumptions`. + /// Combine the assumptions of `self` and `other_assumptions`. + /// + /// This is especially useful for extending [`Assume`] in generic contexts; + /// e.g.: + /// + #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")] + #[cfg_attr(not(bootstrap), doc = "```rust")] #[unstable(feature = "transmutability", issue = "99571")] + /// #![feature( + /// adt_const_params, + /// generic_const_exprs, + /// pointer_is_aligned_to, + /// transmutability, + /// )] + /// #![allow(incomplete_features)] + /// use core::mem::{align_of, Assume, TransmuteFrom}; + /// + /// /// Attempts to transmute `src` to `&Dst`. + /// /// + /// /// Returns `None` if `src` violates the alignment requirements of `&Dst`. + /// /// + /// /// # Safety + /// /// + /// /// The caller guarantees that the obligations required by `ASSUME`, except + /// /// alignment, are satisfied. + /// unsafe fn try_transmute_ref<'a, Src, Dst, const ASSUME: Assume>(src: &'a Src) -> Option<&'a Dst> + /// where + /// &'a Dst: TransmuteFrom<&'a Src, { ASSUME.and(Assume::ALIGNMENT) }>, + /// { + /// if <*const _>::is_aligned_to(src, align_of::()) { + /// // SAFETY: By the above dynamic check, we have ensured that the address + /// // of `src` satisfies the alignment requirements of `&Dst`. By contract + /// // on the caller, the safety obligations required by `ASSUME` have also + /// // been satisfied. + /// Some(unsafe { + /// <_ as TransmuteFrom<_, { ASSUME.and(Assume::ALIGNMENT) }>>::transmute(src) + /// }) + /// } else { + /// None + /// } + /// } + /// + /// let src: &[u8; 2] = &[0xFF, 0xFF]; + /// + /// // SAFETY: No safety obligations. + /// let maybe_dst: Option<&u16> = unsafe { + /// try_transmute_ref::<_, _, { Assume::NOTHING }>(src) + /// }; + ///``` pub const fn and(self, other_assumptions: Self) -> Self { Self { alignment: self.alignment || other_assumptions.alignment, @@ -76,7 +388,21 @@ impl Assume { } } - /// Assume `self`, excepting `other_assumptions`. + /// Remove `other_assumptions` the obligations of `self`; e.g.: + /// + #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")] + #[cfg_attr(not(bootstrap), doc = "```rust")] + /// #![feature(transmutability)] + /// use core::mem::Assume; + /// + /// let assumptions = Assume::ALIGNMENT.and(Assume::SAFETY); + /// let to_be_removed = Assume::SAFETY.and(Assume::VALIDITY); + /// + /// assert_eq!( + /// assumptions.but_not(to_be_removed), + /// Assume::ALIGNMENT, + /// ); + /// ``` #[unstable(feature = "transmutability", issue = "99571")] pub const fn but_not(self, other_assumptions: Self) -> Self { Self { diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs index 3e036b88128..919f681f911 100644 --- a/library/core/src/net/ip_addr.rs +++ b/library/core/src/net/ip_addr.rs @@ -1,6 +1,7 @@ use super::display_buffer::DisplayBuffer; use crate::cmp::Ordering; use crate::fmt::{self, Write}; +use crate::hash::{Hash, Hasher}; use crate::iter; use crate::mem::transmute; use crate::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, Not}; @@ -67,12 +68,22 @@ pub enum IpAddr { /// assert!("0000000.0.0.0".parse::().is_err()); // first octet is a zero in octal /// assert!("0xcb.0x0.0x71.0x00".parse::().is_err()); // all octets are in hex /// ``` -#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, PartialEq, Eq)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Ipv4Addr { octets: [u8; 4], } +#[stable(feature = "rust1", since = "1.0.0")] +impl Hash for Ipv4Addr { + fn hash(&self, state: &mut H) { + // Hashers are often more efficient at hashing a fixed-width integer + // than a bytestring, so convert before hashing. We don't use to_bits() + // here as that may involve a byteswap which is unnecessary. + u32::from_ne_bytes(self.octets).hash(state); + } +} + /// An IPv6 address. /// /// IPv6 addresses are defined as 128-bit integers in [IETF RFC 4291]. @@ -149,12 +160,22 @@ pub struct Ipv4Addr { /// assert_eq!("::1".parse(), Ok(localhost)); /// assert_eq!(localhost.is_loopback(), true); /// ``` -#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, PartialEq, Eq)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Ipv6Addr { octets: [u8; 16], } +#[stable(feature = "rust1", since = "1.0.0")] +impl Hash for Ipv6Addr { + fn hash(&self, state: &mut H) { + // Hashers are often more efficient at hashing a fixed-width integer + // than a bytestring, so convert before hashing. We don't use to_bits() + // here as that may involve unnecessary byteswaps. + u128::from_ne_bytes(self.octets).hash(state); + } +} + /// Scope of an [IPv6 multicast address] as defined in [IETF RFC 7346 section 2]. /// /// # Stability Guarantees diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index 0c04f47fe7d..d4236e47bfe 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -290,7 +290,7 @@ impl f128 { #[inline] #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] pub(crate) const fn abs_private(self) -> f128 { - // SAFETY: This transmutation is fine. Probably. For the reasons std is using it. + // SAFETY: This transmutation is fine just like in `to_bits`/`from_bits`. unsafe { mem::transmute::(mem::transmute::(self) & !Self::SIGN_MASK) } @@ -439,22 +439,12 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] pub const fn classify(self) -> FpCategory { - // Other float types cannot use a bitwise classify because they may suffer a variety - // of errors if the backend chooses to cast to different float types (x87). `f128` cannot - // fit into any other float types so this is not a concern, and we rely on bit patterns. + // Other float types suffer from various platform bugs that violate the usual IEEE semantics + // and also make bitwise classification not always work reliably. However, `f128` cannot fit + // into any other float types so this is not a concern, and we can rely on bit patterns. - // SAFETY: POD bitcast, same as in `to_bits`. - let bits = unsafe { mem::transmute::(self) }; - Self::classify_bits(bits) - } - - /// This operates on bits, and only bits, so it can ignore concerns about weird FPUs. - /// FIXME(jubilee): In a just world, this would be the entire impl for classify, - /// plus a transmute. We do not live in a just world, but we can make it more so. - #[inline] - #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] - const fn classify_bits(b: u128) -> FpCategory { - match (b & Self::MAN_MASK, b & Self::EXP_MASK) { + let bits = self.to_bits(); + match (bits & Self::MAN_MASK, bits & Self::EXP_MASK) { (0, Self::EXP_MASK) => FpCategory::Infinite, (_, Self::EXP_MASK) => FpCategory::Nan, (0, 0) => FpCategory::Zero, @@ -464,11 +454,14 @@ impl f128 { } /// Returns `true` if `self` has a positive sign, including `+0.0`, NaNs with - /// positive sign bit and positive infinity. Note that IEEE 754 doesn't assign any - /// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that - /// the bit pattern of NaNs are conserved over arithmetic operations, the result of - /// `is_sign_positive` on a NaN might produce an unexpected result in some cases. - /// See [explanation of NaN as a special value](f128) for more info. + /// positive sign bit and positive infinity. + /// + /// Note that IEEE 754 doesn't assign any meaning to the sign bit in case of + /// a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs are + /// conserved over arithmetic operations, the result of `is_sign_positive` on + /// a NaN might produce an unexpected or non-portable result. See the [specification + /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == 1.0` + /// if you need fully portable behavior (will return `false` for all NaNs). /// /// ``` /// #![feature(f128)] @@ -487,11 +480,14 @@ impl f128 { } /// Returns `true` if `self` has a negative sign, including `-0.0`, NaNs with - /// negative sign bit and negative infinity. Note that IEEE 754 doesn't assign any - /// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that - /// the bit pattern of NaNs are conserved over arithmetic operations, the result of - /// `is_sign_negative` on a NaN might produce an unexpected result in some cases. - /// See [explanation of NaN as a special value](f128) for more info. + /// negative sign bit and negative infinity. + /// + /// Note that IEEE 754 doesn't assign any meaning to the sign bit in case of + /// a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs are + /// conserved over arithmetic operations, the result of `is_sign_negative` on + /// a NaN might produce an unexpected or non-portable result. See the [specification + /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == -1.0` + /// if you need fully portable behavior (will return `false` for all NaNs). /// /// ``` /// #![feature(f128)] @@ -760,7 +756,7 @@ impl f128 { /// Note that this follows the semantics specified in IEEE 754-2019. /// /// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN - /// operand is conserved; see [explanation of NaN as a special value](f128) for more info. + /// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info. #[inline] #[unstable(feature = "f128", issue = "116909")] // #[unstable(feature = "float_minimum_maximum", issue = "91079")] @@ -801,7 +797,7 @@ impl f128 { /// Note that this follows the semantics specified in IEEE 754-2019. /// /// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN - /// operand is conserved; see [explanation of NaN as a special value](f128) for more info. + /// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info. #[inline] #[unstable(feature = "f128", issue = "116909")] // #[unstable(feature = "float_minimum_maximum", issue = "91079")] @@ -922,48 +918,7 @@ impl f128 { #[must_use = "this returns the result of the operation, without modifying the original"] pub const fn to_bits(self) -> u128 { // SAFETY: `u128` is a plain old datatype so we can always transmute to it. - // ...sorta. - // - // It turns out that at runtime, it is possible for a floating point number - // to be subject to a floating point mode that alters nonzero subnormal numbers - // to zero on reads and writes, aka "denormals are zero" and "flush to zero". - // - // And, of course evaluating to a NaN value is fairly nondeterministic. - // More precisely: when NaN should be returned is knowable, but which NaN? - // So far that's defined by a combination of LLVM and the CPU, not Rust. - // This function, however, allows observing the bitstring of a NaN, - // thus introspection on CTFE. - // - // In order to preserve, at least for the moment, const-to-runtime equivalence, - // we reject any of these possible situations from happening. - #[inline] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] - const fn ct_f128_to_u128(ct: f128) -> u128 { - // FIXME(f16_f128): we should use `.classify()` like `f32` and `f64`, but that - // is not available on all platforms (needs `netf2` and `unordtf2`). So classify - // the bits instead. - - // SAFETY: this is a POD transmutation - let bits = unsafe { mem::transmute::(ct) }; - match f128::classify_bits(bits) { - FpCategory::Nan => { - panic!("const-eval error: cannot use f128::to_bits on a NaN") - } - FpCategory::Subnormal => { - panic!("const-eval error: cannot use f128::to_bits on a subnormal number") - } - FpCategory::Infinite | FpCategory::Normal | FpCategory::Zero => bits, - } - } - - #[inline(always)] // See https://github.com/rust-lang/compiler-builtins/issues/491 - fn rt_f128_to_u128(x: f128) -> u128 { - // SAFETY: `u128` is a plain old datatype so we can always... uh... - // ...look, just pretend you forgot what you just read. - // Stability concerns. - unsafe { mem::transmute(x) } - } - intrinsics::const_eval_select((self,), ct_f128_to_u128, rt_f128_to_u128) + unsafe { mem::transmute(self) } } /// Raw transmutation from `u128`. @@ -1011,49 +966,8 @@ impl f128 { #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] pub const fn from_bits(v: u128) -> Self { // It turns out the safety issues with sNaN were overblown! Hooray! - // SAFETY: `u128` is a plain old datatype so we can always transmute from it - // ...sorta. - // - // It turns out that at runtime, it is possible for a floating point number - // to be subject to floating point modes that alter nonzero subnormal numbers - // to zero on reads and writes, aka "denormals are zero" and "flush to zero". - // This is not a problem usually, but at least one tier2 platform for Rust - // actually exhibits this behavior by default: thumbv7neon - // aka "the Neon FPU in AArch32 state" - // - // And, of course evaluating to a NaN value is fairly nondeterministic. - // More precisely: when NaN should be returned is knowable, but which NaN? - // So far that's defined by a combination of LLVM and the CPU, not Rust. - // This function, however, allows observing the bitstring of a NaN, - // thus introspection on CTFE. - // - // In order to preserve, at least for the moment, const-to-runtime equivalence, - // reject any of these possible situations from happening. - #[inline] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] - const fn ct_u128_to_f128(ct: u128) -> f128 { - match f128::classify_bits(ct) { - FpCategory::Subnormal => { - panic!("const-eval error: cannot use f128::from_bits on a subnormal number") - } - FpCategory::Nan => { - panic!("const-eval error: cannot use f128::from_bits on NaN") - } - FpCategory::Infinite | FpCategory::Normal | FpCategory::Zero => { - // SAFETY: It's not a frumious number - unsafe { mem::transmute::(ct) } - } - } - } - - #[inline(always)] // See https://github.com/rust-lang/compiler-builtins/issues/491 - fn rt_u128_to_f128(x: u128) -> f128 { - // SAFETY: `u128` is a plain old datatype so we can always... uh... - // ...look, just pretend you forgot what you just read. - // Stability concerns. - unsafe { mem::transmute(x) } - } - intrinsics::const_eval_select((v,), ct_u128_to_f128, rt_u128_to_f128) + // SAFETY: `u128` is a plain old datatype so we can always transmute from it. + unsafe { mem::transmute(v) } } /// Returns the memory representation of this floating point number as a byte array in diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index e5b1148e192..1e2f841aca7 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -261,7 +261,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { /// /// let nan = f16::NAN; /// let f = 7.0_f16; @@ -284,7 +284,7 @@ impl f16 { #[inline] #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] pub(crate) const fn abs_private(self) -> f16 { - // SAFETY: This transmutation is fine. Probably. For the reasons std is using it. + // SAFETY: This transmutation is fine just like in `to_bits`/`from_bits`. unsafe { mem::transmute::(mem::transmute::(self) & !Self::SIGN_MASK) } } @@ -293,7 +293,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { /// /// let f = 7.0f16; /// let inf = f16::INFINITY; @@ -319,7 +319,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { /// /// let f = 7.0f16; /// let inf: f16 = f16::INFINITY; @@ -347,7 +347,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { /// /// let min = f16::MIN_POSITIVE; // 6.1035e-5 /// let max = f16::MAX; @@ -377,7 +377,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { /// /// let min = f16::MIN_POSITIVE; // 6.1035e-5 /// let max = f16::MAX; @@ -409,7 +409,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { /// /// use std::num::FpCategory; /// @@ -426,15 +426,15 @@ impl f16 { pub const fn classify(self) -> FpCategory { // A previous implementation for f32/f64 tried to only use bitmask-based checks, // using `to_bits` to transmute the float to its bit repr and match on that. - // Unfortunately, floating point numbers can be much worse than that. - // This also needs to not result in recursive evaluations of `to_bits`. + // If we only cared about being "technically" correct, that's an entirely legit + // implementation. // - - // Platforms without native support generally convert to `f32` to perform operations, - // and most of these platforms correctly round back to `f16` after each operation. - // However, some platforms have bugs where they keep the excess `f32` precision (e.g. - // WASM, see llvm/llvm-project#96437). This implementation makes a best-effort attempt - // to account for that excess precision. + // Unfortunately, there are platforms out there that do not correctly implement the IEEE + // float semantics Rust relies on: some hardware flushes denormals to zero, and some + // platforms convert to `f32` to perform operations without properly rounding back (e.g. + // WASM, see llvm/llvm-project#96437). These are platforms bugs, and Rust will misbehave on + // such platforms, but we can at least try to make things seem as sane as possible by being + // careful here. if self.is_infinite() { // Thus, a value may compare unequal to infinity, despite having a "full" exponent mask. FpCategory::Infinite @@ -446,58 +446,32 @@ impl f16 { // as correctness requires avoiding equality tests that may be Subnormal == -0.0 // because it may be wrong under "denormals are zero" and "flush to zero" modes. // Most of std's targets don't use those, but they are used for thumbv7neon. - // So, this does use bitpattern matching for the rest. - - // SAFETY: f16 to u16 is fine. Usually. - // If classify has gotten this far, the value is definitely in one of these categories. - unsafe { f16::partial_classify(self) } - } - } - - /// This doesn't actually return a right answer for NaN on purpose, - /// seeing as how it cannot correctly discern between a floating point NaN, - /// and some normal floating point numbers truncated from an x87 FPU. - /// - /// # Safety - /// - /// This requires making sure you call this function for values it answers correctly on, - /// otherwise it returns a wrong answer. This is not important for memory safety per se, - /// but getting floats correct is important for not accidentally leaking const eval - /// runtime-deviating logic which may or may not be acceptable. - #[inline] - #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] - const unsafe fn partial_classify(self) -> FpCategory { - // SAFETY: The caller is not asking questions for which this will tell lies. - let b = unsafe { mem::transmute::(self) }; - match (b & Self::MAN_MASK, b & Self::EXP_MASK) { - (0, Self::EXP_MASK) => FpCategory::Infinite, - (0, 0) => FpCategory::Zero, - (_, 0) => FpCategory::Subnormal, - _ => FpCategory::Normal, - } - } - - /// This operates on bits, and only bits, so it can ignore concerns about weird FPUs. - /// FIXME(jubilee): In a just world, this would be the entire impl for classify, - /// plus a transmute. We do not live in a just world, but we can make it more so. - #[inline] - #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] - const fn classify_bits(b: u16) -> FpCategory { - match (b & Self::MAN_MASK, b & Self::EXP_MASK) { - (0, Self::EXP_MASK) => FpCategory::Infinite, - (_, Self::EXP_MASK) => FpCategory::Nan, - (0, 0) => FpCategory::Zero, - (_, 0) => FpCategory::Subnormal, - _ => FpCategory::Normal, + // So, this does use bitpattern matching for the rest. On x87, due to the incorrect + // float codegen on this hardware, this doesn't actually return a right answer for NaN + // because it cannot correctly discern between a floating point NaN, and some normal + // floating point numbers truncated from an x87 FPU -- but we took care of NaN above, so + // we are fine. + // FIXME(jubilee): This probably could at least answer things correctly for Infinity, + // like the f64 version does, but I need to run more checks on how things go on x86. + // I fear losing mantissa data that would have answered that differently. + let b = self.to_bits(); + match (b & Self::MAN_MASK, b & Self::EXP_MASK) { + (0, 0) => FpCategory::Zero, + (_, 0) => FpCategory::Subnormal, + _ => FpCategory::Normal, + } } } /// Returns `true` if `self` has a positive sign, including `+0.0`, NaNs with - /// positive sign bit and positive infinity. Note that IEEE 754 doesn't assign any - /// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that - /// the bit pattern of NaNs are conserved over arithmetic operations, the result of - /// `is_sign_positive` on a NaN might produce an unexpected result in some cases. - /// See [explanation of NaN as a special value](f16) for more info. + /// positive sign bit and positive infinity. + /// + /// Note that IEEE 754 doesn't assign any meaning to the sign bit in case of + /// a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs are + /// conserved over arithmetic operations, the result of `is_sign_positive` on + /// a NaN might produce an unexpected or non-portable result. See the [specification + /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == 1.0` + /// if you need fully portable behavior (will return `false` for all NaNs). /// /// ``` /// #![feature(f16)] @@ -519,11 +493,14 @@ impl f16 { } /// Returns `true` if `self` has a negative sign, including `-0.0`, NaNs with - /// negative sign bit and negative infinity. Note that IEEE 754 doesn't assign any - /// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that - /// the bit pattern of NaNs are conserved over arithmetic operations, the result of - /// `is_sign_negative` on a NaN might produce an unexpected result in some cases. - /// See [explanation of NaN as a special value](f16) for more info. + /// negative sign bit and negative infinity. + /// + /// Note that IEEE 754 doesn't assign any meaning to the sign bit in case of + /// a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs are + /// conserved over arithmetic operations, the result of `is_sign_negative` on + /// a NaN might produce an unexpected or non-portable result. See the [specification + /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == -1.0` + /// if you need fully portable behavior (will return `false` for all NaNs). /// /// ``` /// #![feature(f16)] @@ -791,7 +768,7 @@ impl f16 { /// Note that this follows the semantics specified in IEEE 754-2019. /// /// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN - /// operand is conserved; see [explanation of NaN as a special value](f16) for more info. + /// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info. #[inline] #[unstable(feature = "f16", issue = "116909")] // #[unstable(feature = "float_minimum_maximum", issue = "91079")] @@ -831,7 +808,7 @@ impl f16 { /// Note that this follows the semantics specified in IEEE 754-2019. /// /// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN - /// operand is conserved; see [explanation of NaN as a special value](f16) for more info. + /// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info. #[inline] #[unstable(feature = "f16", issue = "116909")] // #[unstable(feature = "float_minimum_maximum", issue = "91079")] @@ -896,7 +873,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { /// /// let value = 4.6_f16; /// let rounded = unsafe { value.to_int_unchecked::() }; @@ -939,7 +916,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { /// /// # // FIXME(f16_f128): enable this once const casting works /// # // assert_ne!((1f16).to_bits(), 1f16 as u128); // to_bits() is not casting! @@ -952,48 +929,7 @@ impl f16 { #[must_use = "this returns the result of the operation, without modifying the original"] pub const fn to_bits(self) -> u16 { // SAFETY: `u16` is a plain old datatype so we can always transmute to it. - // ...sorta. - // - // It turns out that at runtime, it is possible for a floating point number - // to be subject to a floating point mode that alters nonzero subnormal numbers - // to zero on reads and writes, aka "denormals are zero" and "flush to zero". - // - // And, of course evaluating to a NaN value is fairly nondeterministic. - // More precisely: when NaN should be returned is knowable, but which NaN? - // So far that's defined by a combination of LLVM and the CPU, not Rust. - // This function, however, allows observing the bitstring of a NaN, - // thus introspection on CTFE. - // - // In order to preserve, at least for the moment, const-to-runtime equivalence, - // we reject any of these possible situations from happening. - #[inline] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] - const fn ct_f16_to_u16(ct: f16) -> u16 { - // FIXME(f16_f128): we should use `.classify()` like `f32` and `f64`, but we don't yet - // want to rely on that on all platforms because it is nondeterministic (e.g. x86 has - // convention discrepancies calling intrinsics). So just classify the bits instead. - - // SAFETY: this is a POD transmutation - let bits = unsafe { mem::transmute::(ct) }; - match f16::classify_bits(bits) { - FpCategory::Nan => { - panic!("const-eval error: cannot use f16::to_bits on a NaN") - } - FpCategory::Subnormal => { - panic!("const-eval error: cannot use f16::to_bits on a subnormal number") - } - FpCategory::Infinite | FpCategory::Normal | FpCategory::Zero => bits, - } - } - - #[inline(always)] // See https://github.com/rust-lang/compiler-builtins/issues/491 - fn rt_f16_to_u16(x: f16) -> u16 { - // SAFETY: `u16` is a plain old datatype so we can always... uh... - // ...look, just pretend you forgot what you just read. - // Stability concerns. - unsafe { mem::transmute(x) } - } - intrinsics::const_eval_select((self,), ct_f16_to_u16, rt_f16_to_u16) + unsafe { mem::transmute(self) } } /// Raw transmutation from `u16`. @@ -1028,7 +964,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { /// /// let v = f16::from_bits(0x4a40); /// assert_eq!(v, 12.5); @@ -1040,49 +976,8 @@ impl f16 { #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] pub const fn from_bits(v: u16) -> Self { // It turns out the safety issues with sNaN were overblown! Hooray! - // SAFETY: `u16` is a plain old datatype so we can always transmute from it - // ...sorta. - // - // It turns out that at runtime, it is possible for a floating point number - // to be subject to floating point modes that alter nonzero subnormal numbers - // to zero on reads and writes, aka "denormals are zero" and "flush to zero". - // This is not a problem usually, but at least one tier2 platform for Rust - // actually exhibits this behavior by default: thumbv7neon - // aka "the Neon FPU in AArch32 state" - // - // And, of course evaluating to a NaN value is fairly nondeterministic. - // More precisely: when NaN should be returned is knowable, but which NaN? - // So far that's defined by a combination of LLVM and the CPU, not Rust. - // This function, however, allows observing the bitstring of a NaN, - // thus introspection on CTFE. - // - // In order to preserve, at least for the moment, const-to-runtime equivalence, - // reject any of these possible situations from happening. - #[inline] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] - const fn ct_u16_to_f16(ct: u16) -> f16 { - match f16::classify_bits(ct) { - FpCategory::Subnormal => { - panic!("const-eval error: cannot use f16::from_bits on a subnormal number") - } - FpCategory::Nan => { - panic!("const-eval error: cannot use f16::from_bits on NaN") - } - FpCategory::Infinite | FpCategory::Normal | FpCategory::Zero => { - // SAFETY: It's not a frumious number - unsafe { mem::transmute::(ct) } - } - } - } - - #[inline(always)] // See https://github.com/rust-lang/compiler-builtins/issues/491 - fn rt_u16_to_f16(x: u16) -> f16 { - // SAFETY: `u16` is a plain old datatype so we can always... uh... - // ...look, just pretend you forgot what you just read. - // Stability concerns. - unsafe { mem::transmute(x) } - } - intrinsics::const_eval_select((v,), ct_u16_to_f16, rt_u16_to_f16) + // SAFETY: `u16` is a plain old datatype so we can always transmute from it. + unsafe { mem::transmute(v) } } /// Returns the memory representation of this floating point number as a byte array in @@ -1182,7 +1077,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { /// /// let value = f16::from_be_bytes([0x4a, 0x40]); /// assert_eq!(value, 12.5); @@ -1205,7 +1100,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { /// /// let value = f16::from_le_bytes([0x40, 0x4a]); /// assert_eq!(value, 12.5); @@ -1235,7 +1130,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { /// /// let value = f16::from_ne_bytes(if cfg!(target_endian = "big") { /// [0x4a, 0x40] @@ -1368,7 +1263,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { /// /// assert!((-3.0f16).clamp(-2.0, 1.0) == -2.0); /// assert!((0.0f16).clamp(-2.0, 1.0) == 0.0); diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 7710e23edf0..c1adcc753f2 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -529,7 +529,7 @@ impl f32 { #[inline] #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] pub(crate) const fn abs_private(self) -> f32 { - // SAFETY: This transmutation is fine. Probably. For the reasons std is using it. + // SAFETY: This transmutation is fine just like in `to_bits`/`from_bits`. unsafe { mem::transmute::(mem::transmute::(self) & !Self::SIGN_MASK) } } @@ -654,18 +654,20 @@ impl f32 { pub const fn classify(self) -> FpCategory { // A previous implementation tried to only use bitmask-based checks, // using f32::to_bits to transmute the float to its bit repr and match on that. - // Unfortunately, floating point numbers can be much worse than that. - // This also needs to not result in recursive evaluations of f64::to_bits. + // If we only cared about being "technically" correct, that's an entirely legit + // implementation. + // + // Unfortunately, there is hardware out there that does not correctly implement the IEEE + // float semantics Rust relies on: x87 uses a too-large mantissa and exponent, and some + // hardware flushes subnormals to zero. These are platforms bugs, and Rust will misbehave on + // such hardware, but we can at least try to make things seem as sane as possible by being + // careful here. // - // On some processors, in some cases, LLVM will "helpfully" lower floating point ops, - // in spite of a request for them using f32 and f64, to things like x87 operations. - // These have an f64's mantissa, but can have a larger than normal exponent. // FIXME(jubilee): Using x87 operations is never necessary in order to function // on x86 processors for Rust-to-Rust calls, so this issue should not happen. // Code generation should be adjusted to use non-C calling conventions, avoiding this. - // if self.is_infinite() { - // Thus, a value may compare unequal to infinity, despite having a "full" exponent mask. + // A value may compare unequal to infinity, despite having a "full" exponent mask. FpCategory::Infinite } else if self.is_nan() { // And it may not be NaN, as it can simply be an "overextended" finite value. @@ -675,48 +677,20 @@ impl f32 { // as correctness requires avoiding equality tests that may be Subnormal == -0.0 // because it may be wrong under "denormals are zero" and "flush to zero" modes. // Most of std's targets don't use those, but they are used for thumbv7neon. - // So, this does use bitpattern matching for the rest. - - // SAFETY: f32 to u32 is fine. Usually. - // If classify has gotten this far, the value is definitely in one of these categories. - unsafe { f32::partial_classify(self) } - } - } - - // This doesn't actually return a right answer for NaN on purpose, - // seeing as how it cannot correctly discern between a floating point NaN, - // and some normal floating point numbers truncated from an x87 FPU. - // FIXME(jubilee): This probably could at least answer things correctly for Infinity, - // like the f64 version does, but I need to run more checks on how things go on x86. - // I fear losing mantissa data that would have answered that differently. - // - // # Safety - // This requires making sure you call this function for values it answers correctly on, - // otherwise it returns a wrong answer. This is not important for memory safety per se, - // but getting floats correct is important for not accidentally leaking const eval - // runtime-deviating logic which may or may not be acceptable. - #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] - const unsafe fn partial_classify(self) -> FpCategory { - // SAFETY: The caller is not asking questions for which this will tell lies. - let b = unsafe { mem::transmute::(self) }; - match (b & Self::MAN_MASK, b & Self::EXP_MASK) { - (0, 0) => FpCategory::Zero, - (_, 0) => FpCategory::Subnormal, - _ => FpCategory::Normal, - } - } - - // This operates on bits, and only bits, so it can ignore concerns about weird FPUs. - // FIXME(jubilee): In a just world, this would be the entire impl for classify, - // plus a transmute. We do not live in a just world, but we can make it more so. - #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] - const fn classify_bits(b: u32) -> FpCategory { - match (b & Self::MAN_MASK, b & Self::EXP_MASK) { - (0, Self::EXP_MASK) => FpCategory::Infinite, - (_, Self::EXP_MASK) => FpCategory::Nan, - (0, 0) => FpCategory::Zero, - (_, 0) => FpCategory::Subnormal, - _ => FpCategory::Normal, + // So, this does use bitpattern matching for the rest. On x87, due to the incorrect + // float codegen on this hardware, this doesn't actually return a right answer for NaN + // because it cannot correctly discern between a floating point NaN, and some normal + // floating point numbers truncated from an x87 FPU -- but we took care of NaN above, so + // we are fine. + // FIXME(jubilee): This probably could at least answer things correctly for Infinity, + // like the f64 version does, but I need to run more checks on how things go on x86. + // I fear losing mantissa data that would have answered that differently. + let b = self.to_bits(); + match (b & Self::MAN_MASK, b & Self::EXP_MASK) { + (0, 0) => FpCategory::Zero, + (_, 0) => FpCategory::Subnormal, + _ => FpCategory::Normal, + } } } @@ -726,8 +700,9 @@ impl f32 { /// Note that IEEE 754 doesn't assign any meaning to the sign bit in case of /// a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs are /// conserved over arithmetic operations, the result of `is_sign_positive` on - /// a NaN might produce an unexpected result in some cases. See [explanation - /// of NaN as a special value](f32) for more info. + /// a NaN might produce an unexpected or non-portable result. See the [specification + /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == 1.0` + /// if you need fully portable behavior (will return `false` for all NaNs). /// /// ``` /// let f = 7.0_f32; @@ -750,8 +725,9 @@ impl f32 { /// Note that IEEE 754 doesn't assign any meaning to the sign bit in case of /// a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs are /// conserved over arithmetic operations, the result of `is_sign_negative` on - /// a NaN might produce an unexpected result in some cases. See [explanation - /// of NaN as a special value](f32) for more info. + /// a NaN might produce an unexpected or non-portable result. See the [specification + /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == -1.0` + /// if you need fully portable behavior (will return `false` for all NaNs). /// /// ``` /// let f = 7.0f32; @@ -980,7 +956,7 @@ impl f32 { /// Note that this follows the semantics specified in IEEE 754-2019. /// /// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN - /// operand is conserved; see [explanation of NaN as a special value](f32) for more info. + /// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info. #[must_use = "this returns the result of the comparison, without modifying either input"] #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[inline] @@ -1015,7 +991,7 @@ impl f32 { /// Note that this follows the semantics specified in IEEE 754-2019. /// /// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN - /// operand is conserved; see [explanation of NaN as a special value](f32) for more info. + /// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info. #[must_use = "this returns the result of the comparison, without modifying either input"] #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[inline] @@ -1143,51 +1119,7 @@ impl f32 { #[inline] pub const fn to_bits(self) -> u32 { // SAFETY: `u32` is a plain old datatype so we can always transmute to it. - // ...sorta. - // - // It turns out that at runtime, it is possible for a floating point number - // to be subject to a floating point mode that alters nonzero subnormal numbers - // to zero on reads and writes, aka "denormals are zero" and "flush to zero". - // This is not a problem per se, but at least one tier2 platform for Rust - // actually exhibits this behavior by default. - // - // In addition, on x86 targets with SSE or SSE2 disabled and the x87 FPU enabled, - // i.e. not soft-float, the way Rust does parameter passing can actually alter - // a number that is "not infinity" to have the same exponent as infinity, - // in a slightly unpredictable manner. - // - // And, of course evaluating to a NaN value is fairly nondeterministic. - // More precisely: when NaN should be returned is knowable, but which NaN? - // So far that's defined by a combination of LLVM and the CPU, not Rust. - // This function, however, allows observing the bitstring of a NaN, - // thus introspection on CTFE. - // - // In order to preserve, at least for the moment, const-to-runtime equivalence, - // we reject any of these possible situations from happening. - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] - const fn ct_f32_to_u32(ct: f32) -> u32 { - match ct.classify() { - FpCategory::Nan => { - panic!("const-eval error: cannot use f32::to_bits on a NaN") - } - FpCategory::Subnormal => { - panic!("const-eval error: cannot use f32::to_bits on a subnormal number") - } - FpCategory::Infinite | FpCategory::Normal | FpCategory::Zero => { - // SAFETY: We have a normal floating point number. Now we transmute, i.e. do a bitcopy. - unsafe { mem::transmute::(ct) } - } - } - } - - #[inline(always)] // See https://github.com/rust-lang/compiler-builtins/issues/491 - fn rt_f32_to_u32(x: f32) -> u32 { - // SAFETY: `u32` is a plain old datatype so we can always... uh... - // ...look, just pretend you forgot what you just read. - // Stability concerns. - unsafe { mem::transmute(x) } - } - intrinsics::const_eval_select((self,), ct_f32_to_u32, rt_f32_to_u32) + unsafe { mem::transmute(self) } } /// Raw transmutation from `u32`. @@ -1232,53 +1164,8 @@ impl f32 { #[inline] pub const fn from_bits(v: u32) -> Self { // It turns out the safety issues with sNaN were overblown! Hooray! - // SAFETY: `u32` is a plain old datatype so we can always transmute from it - // ...sorta. - // - // It turns out that at runtime, it is possible for a floating point number - // to be subject to floating point modes that alter nonzero subnormal numbers - // to zero on reads and writes, aka "denormals are zero" and "flush to zero". - // This is not a problem usually, but at least one tier2 platform for Rust - // actually exhibits this behavior by default: thumbv7neon - // aka "the Neon FPU in AArch32 state" - // - // In addition, on x86 targets with SSE or SSE2 disabled and the x87 FPU enabled, - // i.e. not soft-float, the way Rust does parameter passing can actually alter - // a number that is "not infinity" to have the same exponent as infinity, - // in a slightly unpredictable manner. - // - // And, of course evaluating to a NaN value is fairly nondeterministic. - // More precisely: when NaN should be returned is knowable, but which NaN? - // So far that's defined by a combination of LLVM and the CPU, not Rust. - // This function, however, allows observing the bitstring of a NaN, - // thus introspection on CTFE. - // - // In order to preserve, at least for the moment, const-to-runtime equivalence, - // reject any of these possible situations from happening. - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] - const fn ct_u32_to_f32(ct: u32) -> f32 { - match f32::classify_bits(ct) { - FpCategory::Subnormal => { - panic!("const-eval error: cannot use f32::from_bits on a subnormal number") - } - FpCategory::Nan => { - panic!("const-eval error: cannot use f32::from_bits on NaN") - } - FpCategory::Infinite | FpCategory::Normal | FpCategory::Zero => { - // SAFETY: It's not a frumious number - unsafe { mem::transmute::(ct) } - } - } - } - - #[inline(always)] // See https://github.com/rust-lang/compiler-builtins/issues/491 - fn rt_u32_to_f32(x: u32) -> f32 { - // SAFETY: `u32` is a plain old datatype so we can always... uh... - // ...look, just pretend you forgot what you just read. - // Stability concerns. - unsafe { mem::transmute(x) } - } - intrinsics::const_eval_select((v,), ct_u32_to_f32, rt_u32_to_f32) + // SAFETY: `u32` is a plain old datatype so we can always transmute from it. + unsafe { mem::transmute(v) } } /// Returns the memory representation of this floating point number as a byte array in diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index a89859be7ef..e6406771ad3 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -528,7 +528,7 @@ impl f64 { #[inline] #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] pub(crate) const fn abs_private(self) -> f64 { - // SAFETY: This transmutation is fine. Probably. For the reasons std is using it. + // SAFETY: This transmutation is fine just like in `to_bits`/`from_bits`. unsafe { mem::transmute::(mem::transmute::(self) & !Self::SIGN_MASK) } } @@ -653,12 +653,14 @@ impl f64 { pub const fn classify(self) -> FpCategory { // A previous implementation tried to only use bitmask-based checks, // using f64::to_bits to transmute the float to its bit repr and match on that. - // Unfortunately, floating point numbers can be much worse than that. - // This also needs to not result in recursive evaluations of f64::to_bits. + // If we only cared about being "technically" correct, that's an entirely legit + // implementation. + // + // Unfortunately, there is hardware out there that does not correctly implement the IEEE + // float semantics Rust relies on: x87 uses a too-large exponent, and some hardware flushes + // subnormals to zero. These are platforms bugs, and Rust will misbehave on such hardware, + // but we can at least try to make things seem as sane as possible by being careful here. // - // On some processors, in some cases, LLVM will "helpfully" lower floating point ops, - // in spite of a request for them using f32 and f64, to things like x87 operations. - // These have an f64's mantissa, but can have a larger than normal exponent. // FIXME(jubilee): Using x87 operations is never necessary in order to function // on x86 processors for Rust-to-Rust calls, so this issue should not happen. // Code generation should be adjusted to use non-C calling conventions, avoiding this. @@ -672,41 +674,18 @@ impl f64 { // as correctness requires avoiding equality tests that may be Subnormal == -0.0 // because it may be wrong under "denormals are zero" and "flush to zero" modes. // Most of std's targets don't use those, but they are used for thumbv7neon. - // So, this does use bitpattern matching for the rest. - - // SAFETY: f64 to u64 is fine. Usually. - // If control flow has gotten this far, the value is definitely in one of the categories - // that f64::partial_classify can correctly analyze. - unsafe { f64::partial_classify(self) } - } - } - - // This doesn't actually return a right answer for NaN on purpose, - // seeing as how it cannot correctly discern between a floating point NaN, - // and some normal floating point numbers truncated from an x87 FPU. - #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] - const unsafe fn partial_classify(self) -> FpCategory { - // SAFETY: The caller is not asking questions for which this will tell lies. - let b = unsafe { mem::transmute::(self) }; - match (b & Self::MAN_MASK, b & Self::EXP_MASK) { - (0, Self::EXP_MASK) => FpCategory::Infinite, - (0, 0) => FpCategory::Zero, - (_, 0) => FpCategory::Subnormal, - _ => FpCategory::Normal, - } - } - - // This operates on bits, and only bits, so it can ignore concerns about weird FPUs. - // FIXME(jubilee): In a just world, this would be the entire impl for classify, - // plus a transmute. We do not live in a just world, but we can make it more so. - #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] - const fn classify_bits(b: u64) -> FpCategory { - match (b & Self::MAN_MASK, b & Self::EXP_MASK) { - (0, Self::EXP_MASK) => FpCategory::Infinite, - (_, Self::EXP_MASK) => FpCategory::Nan, - (0, 0) => FpCategory::Zero, - (_, 0) => FpCategory::Subnormal, - _ => FpCategory::Normal, + // So, this does use bitpattern matching for the rest. On x87, due to the incorrect + // float codegen on this hardware, this doesn't actually return a right answer for NaN + // because it cannot correctly discern between a floating point NaN, and some normal + // floating point numbers truncated from an x87 FPU -- but we took care of NaN above, so + // we are fine. + let b = self.to_bits(); + match (b & Self::MAN_MASK, b & Self::EXP_MASK) { + (0, Self::EXP_MASK) => FpCategory::Infinite, + (0, 0) => FpCategory::Zero, + (_, 0) => FpCategory::Subnormal, + _ => FpCategory::Normal, + } } } @@ -716,8 +695,9 @@ impl f64 { /// Note that IEEE 754 doesn't assign any meaning to the sign bit in case of /// a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs are /// conserved over arithmetic operations, the result of `is_sign_positive` on - /// a NaN might produce an unexpected result in some cases. See [explanation - /// of NaN as a special value](f32) for more info. + /// a NaN might produce an unexpected or non-portable result. See the [specification + /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == 1.0` + /// if you need fully portable behavior (will return `false` for all NaNs). /// /// ``` /// let f = 7.0_f64; @@ -749,8 +729,9 @@ impl f64 { /// Note that IEEE 754 doesn't assign any meaning to the sign bit in case of /// a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs are /// conserved over arithmetic operations, the result of `is_sign_negative` on - /// a NaN might produce an unexpected result in some cases. See [explanation - /// of NaN as a special value](f32) for more info. + /// a NaN might produce an unexpected or non-portable result. See the [specification + /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == -1.0` + /// if you need fully portable behavior (will return `false` for all NaNs). /// /// ``` /// let f = 7.0_f64; @@ -989,7 +970,7 @@ impl f64 { /// Note that this follows the semantics specified in IEEE 754-2019. /// /// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN - /// operand is conserved; see [explanation of NaN as a special value](f32) for more info. + /// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info. #[must_use = "this returns the result of the comparison, without modifying either input"] #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[inline] @@ -1024,7 +1005,7 @@ impl f64 { /// Note that this follows the semantics specified in IEEE 754-2019. /// /// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN - /// operand is conserved; see [explanation of NaN as a special value](f32) for more info. + /// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info. #[must_use = "this returns the result of the comparison, without modifying either input"] #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[inline] @@ -1134,33 +1115,7 @@ impl f64 { #[inline] pub const fn to_bits(self) -> u64 { // SAFETY: `u64` is a plain old datatype so we can always transmute to it. - // ...sorta. - // - // See the SAFETY comment in f64::from_bits for more. - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] - const fn ct_f64_to_u64(ct: f64) -> u64 { - match ct.classify() { - FpCategory::Nan => { - panic!("const-eval error: cannot use f64::to_bits on a NaN") - } - FpCategory::Subnormal => { - panic!("const-eval error: cannot use f64::to_bits on a subnormal number") - } - FpCategory::Infinite | FpCategory::Normal | FpCategory::Zero => { - // SAFETY: We have a normal floating point number. Now we transmute, i.e. do a bitcopy. - unsafe { mem::transmute::(ct) } - } - } - } - - #[inline(always)] // See https://github.com/rust-lang/compiler-builtins/issues/491 - fn rt_f64_to_u64(rt: f64) -> u64 { - // SAFETY: `u64` is a plain old datatype so we can always... uh... - // ...look, just pretend you forgot what you just read. - // Stability concerns. - unsafe { mem::transmute::(rt) } - } - intrinsics::const_eval_select((self,), ct_f64_to_u64, rt_f64_to_u64) + unsafe { mem::transmute(self) } } /// Raw transmutation from `u64`. @@ -1205,58 +1160,8 @@ impl f64 { #[inline] pub const fn from_bits(v: u64) -> Self { // It turns out the safety issues with sNaN were overblown! Hooray! - // SAFETY: `u64` is a plain old datatype so we can always transmute from it - // ...sorta. - // - // It turns out that at runtime, it is possible for a floating point number - // to be subject to floating point modes that alter nonzero subnormal numbers - // to zero on reads and writes, aka "denormals are zero" and "flush to zero". - // This is not a problem usually, but at least one tier2 platform for Rust - // actually exhibits an FTZ behavior by default: thumbv7neon - // aka "the Neon FPU in AArch32 state" - // - // Even with this, not all instructions exhibit the FTZ behaviors on thumbv7neon, - // so this should load the same bits if LLVM emits the "correct" instructions, - // but LLVM sometimes makes interesting choices about float optimization, - // and other FPUs may do similar. Thus, it is wise to indulge luxuriously in caution. - // - // In addition, on x86 targets with SSE or SSE2 disabled and the x87 FPU enabled, - // i.e. not soft-float, the way Rust does parameter passing can actually alter - // a number that is "not infinity" to have the same exponent as infinity, - // in a slightly unpredictable manner. - // - // And, of course evaluating to a NaN value is fairly nondeterministic. - // More precisely: when NaN should be returned is knowable, but which NaN? - // So far that's defined by a combination of LLVM and the CPU, not Rust. - // This function, however, allows observing the bitstring of a NaN, - // thus introspection on CTFE. - // - // In order to preserve, at least for the moment, const-to-runtime equivalence, - // reject any of these possible situations from happening. - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] - const fn ct_u64_to_f64(ct: u64) -> f64 { - match f64::classify_bits(ct) { - FpCategory::Subnormal => { - panic!("const-eval error: cannot use f64::from_bits on a subnormal number") - } - FpCategory::Nan => { - panic!("const-eval error: cannot use f64::from_bits on NaN") - } - FpCategory::Infinite | FpCategory::Normal | FpCategory::Zero => { - // SAFETY: It's not a frumious number - unsafe { mem::transmute::(ct) } - } - } - } - - #[inline(always)] // See https://github.com/rust-lang/compiler-builtins/issues/491 - fn rt_u64_to_f64(rt: u64) -> f64 { - // SAFETY: `u64` is a plain old datatype so we can always... uh... - // ...look, just pretend you forgot what you just read. - // Stability concerns. - unsafe { mem::transmute::(rt) } - } - intrinsics::const_eval_select((v,), ct_u64_to_f64, rt_u64_to_f64) + // SAFETY: `u64` is a plain old datatype so we can always transmute from it. + unsafe { mem::transmute(v) } } /// Returns the memory representation of this floating point number as a byte array in diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index dd88e859b30..42461a3345b 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -1312,6 +1312,34 @@ macro_rules! int_impl { } } + /// Unbounded shift left. Computes `self << rhs`, without bounding the value of `rhs` + /// + /// If `rhs` is larger or equal to the number of bits in `self`, + /// the entire value is shifted out, and `0` is returned. + /// + /// # Examples + /// + /// Basic usage: + /// ``` + /// #![feature(unbounded_shifts)] + #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".unbounded_shl(4), 0x10);")] + #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".unbounded_shl(129), 0);")] + /// ``` + #[unstable(feature = "unbounded_shifts", issue = "129375")] + #[rustc_const_unstable(feature = "const_unbounded_shifts", issue = "129375")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn unbounded_shl(self, rhs: u32) -> $SelfT{ + if rhs < Self::BITS { + // SAFETY: + // rhs is just checked to be in-range above + unsafe { self.unchecked_shl(rhs) } + } else { + 0 + } + } + /// Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` is /// larger than or equal to the number of bits in `self`. /// @@ -1410,6 +1438,40 @@ macro_rules! int_impl { } } + /// Unbounded shift right. Computes `self >> rhs`, without bounding the value of `rhs` + /// + /// If `rhs` is larger or equal to the number of bits in `self`, + /// the entire value is shifted out, which yields `0` for a positive number, + /// and `-1` for a negative number. + /// + /// # Examples + /// + /// Basic usage: + /// ``` + /// #![feature(unbounded_shifts)] + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".unbounded_shr(4), 0x1);")] + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".unbounded_shr(129), 0);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.unbounded_shr(129), -1);")] + /// ``` + #[unstable(feature = "unbounded_shifts", issue = "129375")] + #[rustc_const_unstable(feature = "const_unbounded_shifts", issue = "129375")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn unbounded_shr(self, rhs: u32) -> $SelfT{ + if rhs < Self::BITS { + // SAFETY: + // rhs is just checked to be in-range above + unsafe { self.unchecked_shr(rhs) } + } else { + // A shift by `Self::BITS-1` suffices for signed integers, because the sign bit is copied for each of the shifted bits. + + // SAFETY: + // `Self::BITS-1` is guaranteed to be less than `Self::BITS` + unsafe { self.unchecked_shr(Self::BITS - 1) } + } + } + /// Checked absolute value. Computes `self.abs()`, returning `None` if /// `self == MIN`. /// @@ -1496,18 +1558,17 @@ macro_rules! int_impl { let mut base = self; let mut acc: Self = 1; - while exp > 1 { + loop { if (exp & 1) == 1 { acc = try_opt!(acc.checked_mul(base)); + // since exp!=0, finally the exp must be 1. + if exp == 1 { + return Some(acc); + } } exp /= 2; base = try_opt!(base.checked_mul(base)); } - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - acc.checked_mul(base) } /// Strict exponentiation. Computes `self.pow(exp)`, panicking if @@ -1547,18 +1608,17 @@ macro_rules! int_impl { let mut base = self; let mut acc: Self = 1; - while exp > 1 { + loop { if (exp & 1) == 1 { acc = acc.strict_mul(base); + // since exp!=0, finally the exp must be 1. + if exp == 1 { + return acc; + } } exp /= 2; base = base.strict_mul(base); } - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - acc.strict_mul(base) } /// Returns the square root of the number, rounded down. @@ -2175,6 +2235,7 @@ macro_rules! int_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] + #[rustc_allow_const_fn_unstable(is_val_statically_known)] pub const fn wrapping_pow(self, mut exp: u32) -> Self { if exp == 0 { return 1; @@ -2182,19 +2243,36 @@ macro_rules! int_impl { let mut base = self; let mut acc: Self = 1; - while exp > 1 { - if (exp & 1) == 1 { - acc = acc.wrapping_mul(base); + if intrinsics::is_val_statically_known(exp) { + while exp > 1 { + if (exp & 1) == 1 { + acc = acc.wrapping_mul(base); + } + exp /= 2; + base = base.wrapping_mul(base); } - exp /= 2; - base = base.wrapping_mul(base); - } - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - acc.wrapping_mul(base) + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary. + acc.wrapping_mul(base) + } else { + // This is faster than the above when the exponent is not known + // at compile time. We can't use the same code for the constant + // exponent case because LLVM is currently unable to unroll + // this loop. + loop { + if (exp & 1) == 1 { + acc = acc.wrapping_mul(base); + // since exp!=0, finally the exp must be 1. + if exp == 1 { + return acc; + } + } + exp /= 2; + base = base.wrapping_mul(base); + } + } } /// Calculates `self` + `rhs`. @@ -2690,9 +2768,14 @@ macro_rules! int_impl { // Scratch space for storing results of overflowing_mul. let mut r; - while exp > 1 { + loop { if (exp & 1) == 1 { r = acc.overflowing_mul(base); + // since exp!=0, finally the exp must be 1. + if exp == 1 { + r.1 |= overflown; + return r; + } acc = r.0; overflown |= r.1; } @@ -2701,14 +2784,6 @@ macro_rules! int_impl { base = r.0; overflown |= r.1; } - - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - r = acc.overflowing_mul(base); - r.1 |= overflown; - r } /// Raises self to the power of `exp`, using exponentiation by squaring. @@ -2728,6 +2803,7 @@ macro_rules! int_impl { without modifying the original"] #[inline] #[rustc_inherit_overflow_checks] + #[rustc_allow_const_fn_unstable(is_val_statically_known)] pub const fn pow(self, mut exp: u32) -> Self { if exp == 0 { return 1; @@ -2735,19 +2811,37 @@ macro_rules! int_impl { let mut base = self; let mut acc = 1; - while exp > 1 { - if (exp & 1) == 1 { - acc = acc * base; + if intrinsics::is_val_statically_known(exp) { + while exp > 1 { + if (exp & 1) == 1 { + acc = acc * base; + } + exp /= 2; + base = base * base; } - exp /= 2; - base = base * base; - } - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - acc * base + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + acc * base + } else { + // This is faster than the above when the exponent is not known + // at compile time. We can't use the same code for the constant + // exponent case because LLVM is currently unable to unroll + // this loop. + loop { + if (exp & 1) == 1 { + acc = acc * base; + // since exp!=0, finally the exp must be 1. + if exp == 1 { + return acc; + } + } + exp /= 2; + base = base * base; + } + } } /// Returns the square root of the number, rounded down. @@ -2794,8 +2888,8 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0 or if `self` is -1 and `rhs` is - /// `Self::MIN`. This behavior is not affected by the `overflow-checks` flag. + /// This function will panic if `rhs` is 0 or if `self` is `Self::MIN` + /// and `rhs` is -1. This behavior is not affected by the `overflow-checks` flag. /// /// # Examples /// @@ -2833,8 +2927,8 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0 or if `self` is -1 and `rhs` is - /// `Self::MIN`. This behavior is not affected by the `overflow-checks` flag. + /// This function will panic if `rhs` is 0 or if `self` is `Self::MIN` and + /// `rhs` is -1. This behavior is not affected by the `overflow-checks` flag. /// /// # Examples /// @@ -2849,6 +2943,11 @@ macro_rules! int_impl { /// assert_eq!(a.rem_euclid(-b), 3); /// assert_eq!((-a).rem_euclid(-b), 1); /// ``` + /// + /// This will panic: + /// ```should_panic + #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.rem_euclid(-1);")] + /// ``` #[doc(alias = "modulo", alias = "mod")] #[stable(feature = "euclidean_division", since = "1.38.0")] #[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")] @@ -2877,8 +2976,8 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0 or if `self` is -1 and `rhs` is - /// `Self::MIN`. This behavior is not affected by the `overflow-checks` flag. + /// This function will panic if `rhs` is 0 or if `self` is `Self::MIN` + /// and `rhs` is -1. This behavior is not affected by the `overflow-checks` flag. /// /// # Examples /// @@ -2913,8 +3012,8 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0 or if `self` is -1 and `rhs` is - /// `Self::MIN`. This behavior is not affected by the `overflow-checks` flag. + /// This function will panic if `rhs` is 0 or if `self` is `Self::MIN` + /// and `rhs` is -1. This behavior is not affected by the `overflow-checks` flag. /// /// # Examples /// diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index a2e17fae768..0d0bbc5256f 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1501,6 +1501,34 @@ macro_rules! uint_impl { } } + /// Unbounded shift left. Computes `self << rhs`, without bounding the value of `rhs` + /// + /// If `rhs` is larger or equal to the number of bits in `self`, + /// the entire value is shifted out, and `0` is returned. + /// + /// # Examples + /// + /// Basic usage: + /// ``` + /// #![feature(unbounded_shifts)] + #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".unbounded_shl(4), 0x10);")] + #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".unbounded_shl(129), 0);")] + /// ``` + #[unstable(feature = "unbounded_shifts", issue = "129375")] + #[rustc_const_unstable(feature = "const_unbounded_shifts", issue = "129375")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn unbounded_shl(self, rhs: u32) -> $SelfT{ + if rhs < Self::BITS { + // SAFETY: + // rhs is just checked to be in-range above + unsafe { self.unchecked_shl(rhs) } + } else { + 0 + } + } + /// Checked shift right. Computes `self >> rhs`, returning `None` /// if `rhs` is larger than or equal to the number of bits in `self`. /// @@ -1599,6 +1627,34 @@ macro_rules! uint_impl { } } + /// Unbounded shift right. Computes `self >> rhs`, without bounding the value of `rhs` + /// + /// If `rhs` is larger or equal to the number of bits in `self`, + /// the entire value is shifted out, and `0` is returned. + /// + /// # Examples + /// + /// Basic usage: + /// ``` + /// #![feature(unbounded_shifts)] + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".unbounded_shr(4), 0x1);")] + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".unbounded_shr(129), 0);")] + /// ``` + #[unstable(feature = "unbounded_shifts", issue = "129375")] + #[rustc_const_unstable(feature = "const_unbounded_shifts", issue = "129375")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn unbounded_shr(self, rhs: u32) -> $SelfT{ + if rhs < Self::BITS { + // SAFETY: + // rhs is just checked to be in-range above + unsafe { self.unchecked_shr(rhs) } + } else { + 0 + } + } + /// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if /// overflow occurred. /// @@ -1622,20 +1678,17 @@ macro_rules! uint_impl { let mut base = self; let mut acc: Self = 1; - while exp > 1 { + loop { if (exp & 1) == 1 { acc = try_opt!(acc.checked_mul(base)); + // since exp!=0, finally the exp must be 1. + if exp == 1 { + return Some(acc); + } } exp /= 2; base = try_opt!(base.checked_mul(base)); } - - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - - acc.checked_mul(base) } /// Strict exponentiation. Computes `self.pow(exp)`, panicking if @@ -1675,18 +1728,17 @@ macro_rules! uint_impl { let mut base = self; let mut acc: Self = 1; - while exp > 1 { + loop { if (exp & 1) == 1 { acc = acc.strict_mul(base); + // since exp!=0, finally the exp must be 1. + if exp == 1 { + return acc; + } } exp /= 2; base = base.strict_mul(base); } - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - acc.strict_mul(base) } /// Saturating integer addition. Computes `self + rhs`, saturating at @@ -2138,6 +2190,7 @@ macro_rules! uint_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] + #[rustc_allow_const_fn_unstable(is_val_statically_known)] pub const fn wrapping_pow(self, mut exp: u32) -> Self { if exp == 0 { return 1; @@ -2145,19 +2198,36 @@ macro_rules! uint_impl { let mut base = self; let mut acc: Self = 1; - while exp > 1 { - if (exp & 1) == 1 { - acc = acc.wrapping_mul(base); + if intrinsics::is_val_statically_known(exp) { + while exp > 1 { + if (exp & 1) == 1 { + acc = acc.wrapping_mul(base); + } + exp /= 2; + base = base.wrapping_mul(base); } - exp /= 2; - base = base.wrapping_mul(base); - } - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - acc.wrapping_mul(base) + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary. + acc.wrapping_mul(base) + } else { + // This is faster than the above when the exponent is not known + // at compile time. We can't use the same code for the constant + // exponent case because LLVM is currently unable to unroll + // this loop. + loop { + if (exp & 1) == 1 { + acc = acc.wrapping_mul(base); + // since exp!=0, finally the exp must be 1. + if exp == 1 { + return acc; + } + } + exp /= 2; + base = base.wrapping_mul(base); + } + } } /// Calculates `self` + `rhs`. @@ -2603,9 +2673,14 @@ macro_rules! uint_impl { // Scratch space for storing results of overflowing_mul. let mut r; - while exp > 1 { + loop { if (exp & 1) == 1 { r = acc.overflowing_mul(base); + // since exp!=0, finally the exp must be 1. + if exp == 1 { + r.1 |= overflown; + return r; + } acc = r.0; overflown |= r.1; } @@ -2614,15 +2689,6 @@ macro_rules! uint_impl { base = r.0; overflown |= r.1; } - - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - r = acc.overflowing_mul(base); - r.1 |= overflown; - - r } /// Raises self to the power of `exp`, using exponentiation by squaring. @@ -2640,6 +2706,7 @@ macro_rules! uint_impl { without modifying the original"] #[inline] #[rustc_inherit_overflow_checks] + #[rustc_allow_const_fn_unstable(is_val_statically_known)] pub const fn pow(self, mut exp: u32) -> Self { if exp == 0 { return 1; @@ -2647,19 +2714,37 @@ macro_rules! uint_impl { let mut base = self; let mut acc = 1; - while exp > 1 { - if (exp & 1) == 1 { - acc = acc * base; + if intrinsics::is_val_statically_known(exp) { + while exp > 1 { + if (exp & 1) == 1 { + acc = acc * base; + } + exp /= 2; + base = base * base; } - exp /= 2; - base = base * base; - } - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - acc * base + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + acc * base + } else { + // This is faster than the above when the exponent is not known + // at compile time. We can't use the same code for the constant + // exponent case because LLVM is currently unable to unroll + // this loop. + loop { + if (exp & 1) == 1 { + acc = acc * base; + // since exp!=0, finally the exp must be 1. + if exp == 1 { + return acc; + } + } + exp /= 2; + base = base * base; + } + } } /// Returns the square root of the number, rounded down. diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index a2709c66b06..ab73dc19fcc 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -116,7 +116,9 @@ impl ops::Try for ControlFlow { } #[unstable(feature = "try_trait_v2", issue = "84277")] -impl ops::FromResidual for ControlFlow { +// Note: manually specifying the residual type instead of using the default to work around +// https://github.com/rust-lang/rust/issues/99940 +impl ops::FromResidual> for ControlFlow { #[inline] fn from_residual(residual: ControlFlow) -> Self { match residual { diff --git a/library/core/src/ops/coroutine.rs b/library/core/src/ops/coroutine.rs index 13df888d24c..c7d596d74c3 100644 --- a/library/core/src/ops/coroutine.rs +++ b/library/core/src/ops/coroutine.rs @@ -69,6 +69,7 @@ pub enum CoroutineState { #[lang = "coroutine"] #[unstable(feature = "coroutine_trait", issue = "43122")] #[fundamental] +#[must_use = "coroutines are lazy and do nothing unless resumed"] pub trait Coroutine { /// The type of value this coroutine yields. /// diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 6c89c810180..50cb22b7eb3 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -656,8 +656,6 @@ impl Option { /// # Examples /// /// ``` - /// #![feature(is_none_or)] - /// /// let x: Option = Some(2); /// assert_eq!(x.is_none_or(|x| x > 1), true); /// @@ -669,7 +667,7 @@ impl Option { /// ``` #[must_use] #[inline] - #[unstable(feature = "is_none_or", issue = "126383")] + #[stable(feature = "is_none_or", since = "CURRENT_RUSTC_VERSION")] pub fn is_none_or(self, f: impl FnOnce(T) -> bool) -> bool { match self { None => true, @@ -2495,7 +2493,9 @@ impl ops::Try for Option { } #[unstable(feature = "try_trait_v2", issue = "84277")] -impl ops::FromResidual for Option { +// Note: manually specifying the residual type instead of using the default to work around +// https://github.com/rust-lang/rust/issues/99940 +impl ops::FromResidual> for Option { #[inline] fn from_residual(residual: Option) -> Self { match residual { diff --git a/library/core/src/panic/location.rs b/library/core/src/panic/location.rs index 8c04994ac0f..e2a842046a9 100644 --- a/library/core/src/panic/location.rs +++ b/library/core/src/panic/location.rs @@ -44,7 +44,7 @@ impl<'a> Location<'a> { /// /// # Examples /// - /// ``` + /// ```standalone /// use std::panic::Location; /// /// /// Returns the [`Location`] at which it is called. @@ -195,6 +195,7 @@ impl<'a> Location<'a> { #[stable(feature = "panic_hook_display", since = "1.26.0")] impl fmt::Display for Location<'_> { + #[inline] fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { write!(formatter, "{}:{}:{}", self.file, self.line, self.col) } diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 0569b8b7624..65f6bfb7ee1 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -1084,6 +1084,7 @@ use crate::{cmp, fmt}; #[lang = "pin"] #[fundamental] #[repr(transparent)] +#[cfg_attr(not(bootstrap), rustc_pub_transparent)] #[derive(Copy, Clone)] pub struct Pin { // FIXME(#93176): this field is made `#[unstable] #[doc(hidden)] pub` to: @@ -1291,8 +1292,8 @@ impl Pin { /// // Now, if `x` was the only reference, we have a mutable reference to /// // data that we pinned above, which we could use to move it as we have /// // seen in the previous example. We have violated the pinning API contract. - /// } - /// ``` + /// } + /// ``` /// /// ## Pinning of closure captures /// @@ -1369,33 +1370,14 @@ impl Pin { // SAFETY: see documentation on this function unsafe { Pin::new_unchecked(&*self.__pointer) } } - - /// Unwraps this `Pin`, returning the underlying `Ptr`. - /// - /// # Safety - /// - /// This function is unsafe. You must guarantee that you will continue to - /// treat the pointer `Ptr` as pinned after you call this function, so that - /// the invariants on the `Pin` type can be upheld. If the code using the - /// resulting `Ptr` does not continue to maintain the pinning invariants that - /// is a violation of the API contract and may lead to undefined behavior in - /// later (safe) operations. - /// - /// Note that you must be able to guarantee that the data pointed to by `Ptr` - /// will be treated as pinned all the way until its `drop` handler is complete! - /// - /// *For more information, see the [`pin` module docs][self]* - /// - /// If the underlying data is [`Unpin`], [`Pin::into_inner`] should be used - /// instead. - #[inline(always)] - #[rustc_const_unstable(feature = "const_pin", issue = "76654")] - #[stable(feature = "pin_into_inner", since = "1.39.0")] - pub const unsafe fn into_inner_unchecked(pin: Pin) -> Ptr { - pin.__pointer - } } +// These methods being in a `Ptr: DerefMut` impl block concerns semver stability. +// Currently, calling e.g. `.set()` on a `Pin<&T>` sees that `Ptr: DerefMut` +// doesn't hold, and goes to check for a `.set()` method on `T`. But, if the +// `where Ptr: DerefMut` bound is moved to the method, rustc sees the impl block +// as a valid candidate, and doesn't go on to check other candidates when it +// sees that the bound on the method. impl Pin { /// Gets a mutable reference to the pinned value this `Pin` points to. /// @@ -1433,6 +1415,44 @@ impl Pin { unsafe { Pin::new_unchecked(&mut *self.__pointer) } } + /// Gets `Pin<&mut T>` to the underlying pinned value from this nested `Pin`-pointer. + /// + /// This is a generic method to go from `Pin<&mut Pin>>` to `Pin<&mut T>`. It is + /// safe because the existence of a `Pin>` ensures that the pointee, `T`, cannot + /// move in the future, and this method does not enable the pointee to move. "Malicious" + /// implementations of `Ptr::DerefMut` are likewise ruled out by the contract of + /// `Pin::new_unchecked`. + #[unstable(feature = "pin_deref_mut", issue = "86918")] + #[must_use = "`self` will be dropped if the result is not used"] + #[inline(always)] + pub fn as_deref_mut(self: Pin<&mut Pin>) -> Pin<&mut Ptr::Target> { + // SAFETY: What we're asserting here is that going from + // + // Pin<&mut Pin> + // + // to + // + // Pin<&mut Ptr::Target> + // + // is safe. + // + // We need to ensure that two things hold for that to be the case: + // + // 1) Once we give out a `Pin<&mut Ptr::Target>`, a `&mut Ptr::Target` will not be given out. + // 2) By giving out a `Pin<&mut Ptr::Target>`, we do not risk violating + // `Pin<&mut Pin>` + // + // The existence of `Pin` is sufficient to guarantee #1: since we already have a + // `Pin`, it must already uphold the pinning guarantees, which must mean that + // `Pin<&mut Ptr::Target>` does as well, since `Pin::as_mut` is safe. We do not have to rely + // on the fact that `Ptr` is _also_ pinned. + // + // For #2, we need to ensure that code given a `Pin<&mut Ptr::Target>` cannot cause the + // `Pin` to move? That is not possible, since `Pin<&mut Ptr::Target>` no longer retains + // any access to the `Ptr` itself, much less the `Pin`. + unsafe { self.get_unchecked_mut() }.as_mut() + } + /// Assigns a new value to the memory location pointed to by the `Pin`. /// /// This overwrites pinned data, but that is okay: the original pinned value's destructor gets @@ -1463,6 +1483,33 @@ impl Pin { } } +impl Pin { + /// Unwraps this `Pin`, returning the underlying `Ptr`. + /// + /// # Safety + /// + /// This function is unsafe. You must guarantee that you will continue to + /// treat the pointer `Ptr` as pinned after you call this function, so that + /// the invariants on the `Pin` type can be upheld. If the code using the + /// resulting `Ptr` does not continue to maintain the pinning invariants that + /// is a violation of the API contract and may lead to undefined behavior in + /// later (safe) operations. + /// + /// Note that you must be able to guarantee that the data pointed to by `Ptr` + /// will be treated as pinned all the way until its `drop` handler is complete! + /// + /// *For more information, see the [`pin` module docs][self]* + /// + /// If the underlying data is [`Unpin`], [`Pin::into_inner`] should be used + /// instead. + #[inline(always)] + #[rustc_const_unstable(feature = "const_pin", issue = "76654")] + #[stable(feature = "pin_into_inner", since = "1.39.0")] + pub const unsafe fn into_inner_unchecked(pin: Pin) -> Ptr { + pin.__pointer + } +} + impl<'a, T: ?Sized> Pin<&'a T> { /// Constructs a new pin by mapping the interior value. /// @@ -1613,46 +1660,6 @@ impl Pin<&'static T> { } } -impl<'a, Ptr: DerefMut> Pin<&'a mut Pin> { - /// Gets `Pin<&mut T>` to the underlying pinned value from this nested `Pin`-pointer. - /// - /// This is a generic method to go from `Pin<&mut Pin>>` to `Pin<&mut T>`. It is - /// safe because the existence of a `Pin>` ensures that the pointee, `T`, cannot - /// move in the future, and this method does not enable the pointee to move. "Malicious" - /// implementations of `Ptr::DerefMut` are likewise ruled out by the contract of - /// `Pin::new_unchecked`. - #[unstable(feature = "pin_deref_mut", issue = "86918")] - #[must_use = "`self` will be dropped if the result is not used"] - #[inline(always)] - pub fn as_deref_mut(self) -> Pin<&'a mut Ptr::Target> { - // SAFETY: What we're asserting here is that going from - // - // Pin<&mut Pin> - // - // to - // - // Pin<&mut Ptr::Target> - // - // is safe. - // - // We need to ensure that two things hold for that to be the case: - // - // 1) Once we give out a `Pin<&mut Ptr::Target>`, a `&mut Ptr::Target` will not be given out. - // 2) By giving out a `Pin<&mut Ptr::Target>`, we do not risk violating - // `Pin<&mut Pin>` - // - // The existence of `Pin` is sufficient to guarantee #1: since we already have a - // `Pin`, it must already uphold the pinning guarantees, which must mean that - // `Pin<&mut Ptr::Target>` does as well, since `Pin::as_mut` is safe. We do not have to rely - // on the fact that `Ptr` is _also_ pinned. - // - // For #2, we need to ensure that code given a `Pin<&mut Ptr::Target>` cannot cause the - // `Pin` to move? That is not possible, since `Pin<&mut Ptr::Target>` no longer retains - // any access to the `Ptr` itself, much less the `Pin`. - unsafe { self.get_unchecked_mut() }.as_mut() - } -} - impl Pin<&'static mut T> { /// Gets a pinning mutable reference from a static mutable reference. /// diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 09ebef89fb0..fe6ed7e0cf3 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -1130,8 +1130,8 @@ impl (T,) {} /// A 16-bit floating point type (specifically, the "binary16" type defined in IEEE 754-2008). /// /// This type is very similar to [`prim@f32`] but has decreased precision because it uses half as many -/// bits. Please see [the documentation for [`prim@f32`] or [Wikipedia on -/// half-precision values][wikipedia] for more information. +/// bits. Please see [the documentation for `f32`](prim@f32) or [Wikipedia on half-precision +/// values][wikipedia] for more information. /// /// Note that most common platforms will not support `f16` in hardware without enabling extra target /// features, with the notable exception of Apple Silicon (also known as M1, M2, etc.) processors. @@ -1190,6 +1190,11 @@ mod prim_f16 {} /// portable or even fully deterministic! This means that there may be some /// surprising results upon inspecting the bit patterns, /// as the same calculations might produce NaNs with different bit patterns. +/// This also affects the sign of the NaN: checking `is_sign_positive` or `is_sign_negative` on +/// a NaN is the most common way to run into these surprising results. +/// (Checking `x >= 0.0` or `x <= 0.0` avoids those surprises, but also how negative/positive +/// zero are treated.) +/// See the section below for what exactly is guaranteed about the bit pattern of a NaN. /// /// When a primitive operation (addition, subtraction, multiplication, or /// division) is performed on this type, the result is rounded according to the @@ -1211,6 +1216,79 @@ mod prim_f16 {} /// *[See also the `std::f32::consts` module](crate::f32::consts).* /// /// [wikipedia]: https://en.wikipedia.org/wiki/Single-precision_floating-point_format +/// +/// # NaN bit patterns +/// +/// This section defines the possible NaN bit patterns returned by non-"bitwise" floating point +/// operations. The bitwise operations are unary `-`, `abs`, `copysign`; those are guaranteed to +/// exactly preserve the bit pattern of their input except for possibly changing the sign bit. +/// +/// A floating-point NaN value consists of: +/// - a sign bit +/// - a quiet/signaling bit +/// - a payload, which makes up the rest of the significand (i.e., the mantissa) except for the +/// quiet/signaling bit. +/// +/// Rust assumes that the quiet/signaling bit being set to `1` indicates a quiet NaN (QNaN), and a +/// value of `0` indicates a signaling NaN (SNaN). In the following we will hence just call it the +/// "quiet bit". +/// +/// The following rules apply when a NaN value is returned: the result has a non-deterministic sign. +/// The quiet bit and payload are non-deterministically chosen from the following set of options: +/// +/// - **Preferred NaN**: The quiet bit is set and the payload is all-zero. +/// - **Quieting NaN propagation**: The quiet bit is set and the payload is copied from any input +/// operand that is a NaN. If the inputs and outputs do not have the same payload size (i.e., for +/// `as` casts), then +/// - If the output is smaller than the input, low-order bits of the payload get dropped. +/// - If the output is larger than the input, the payload gets filled up with 0s in the low-order +/// bits. +/// - **Unchanged NaN propagation**: The quiet bit and payload are copied from any input operand +/// that is a NaN. If the inputs and outputs do not have the same size (i.e., for `as` casts), the +/// same rules as for "quieting NaN propagation" apply, with one caveat: if the output is smaller +/// than the input, droppig the low-order bits may result in a payload of 0; a payload of 0 is not +/// possible with a signaling NaN (the all-0 significand encodes an infinity) so unchanged NaN +/// propagation cannot occur with some inputs. +/// - **Target-specific NaN**: The quiet bit is set and the payload is picked from a target-specific +/// set of "extra" possible NaN payloads. The set can depend on the input operand values. +/// See the table below for the concrete NaNs this set contains on various targets. +/// +/// In particular, if all input NaNs are quiet (or if there are no input NaNs), then the output NaN +/// is definitely quiet. Signaling NaN outputs can only occur if they are provided as an input +/// value. Similarly, if all input NaNs are preferred (or if there are no input NaNs) and the target +/// does not have any "extra" NaN payloads, then the output NaN is guaranteed to be preferred. +/// +/// The non-deterministic choice happens when the operation is executed; i.e., the result of a +/// NaN-producing floating point operation is a stable bit pattern (looking at these bits multiple +/// times will yield consistent results), but running the same operation twice with the same inputs +/// can produce different results. +/// +/// These guarantees are neither stronger nor weaker than those of IEEE 754: IEEE 754 guarantees +/// that an operation never returns a signaling NaN, whereas it is possible for operations like +/// `SNAN * 1.0` to return a signaling NaN in Rust. Conversely, IEEE 754 makes no statement at all +/// about which quiet NaN is returned, whereas Rust restricts the set of possible results to the +/// ones listed above. +/// +/// Unless noted otherwise, the same rules also apply to NaNs returned by other library functions +/// (e.g. `min`, `minimum`, `max`, `maximum`); other aspects of their semantics and which IEEE 754 +/// operation they correspond to are documented with the respective functions. +/// +/// When a floating-point operation is executed in `const` context, the same rules apply: no +/// guarantee is made about which of the NaN bit patterns described above will be returned. The +/// result does not have to match what happens when executing the same code at runtime, and the +/// result can vary depending on factors such as compiler version and flags. +/// +/// ### Target-specific "extra" NaN values +// FIXME: Is there a better place to put this? +/// +/// | `target_arch` | Extra payloads possible on this platform | +/// |---------------|---------| +/// | `x86`, `x86_64`, `arm`, `aarch64`, `riscv32`, `riscv64` | None | +/// | `sparc`, `sparc64` | The all-one payload | +/// | `wasm32`, `wasm64` | If all input NaNs are quiet with all-zero payload: None.
Otherwise: all possible payloads. | +/// +/// For targets not in this table, all payloads are possible. + #[stable(feature = "rust1", since = "1.0.0")] mod prim_f32 {} @@ -1218,14 +1296,12 @@ mod prim_f32 {} #[doc(alias = "double")] /// A 64-bit floating point type (specifically, the "binary64" type defined in IEEE 754-2008). /// -/// This type is very similar to [`f32`], but has increased -/// precision by using twice as many bits. Please see [the documentation for -/// `f32`][`f32`] or [Wikipedia on double precision +/// This type is very similar to [`prim@f32`], but has increased precision by using twice as many +/// bits. Please see [the documentation for `f32`](prim@f32) or [Wikipedia on double-precision /// values][wikipedia] for more information. /// /// *[See also the `std::f64::consts` module](crate::f64::consts).* /// -/// [`f32`]: prim@f32 /// [wikipedia]: https://en.wikipedia.org/wiki/Double-precision_floating-point_format #[stable(feature = "rust1", since = "1.0.0")] mod prim_f64 {} @@ -1235,12 +1311,12 @@ mod prim_f64 {} /// A 128-bit floating point type (specifically, the "binary128" type defined in IEEE 754-2008). /// /// This type is very similar to [`prim@f32`] and [`prim@f64`], but has increased precision by using twice -/// as many bits as `f64`. Please see [the documentation for [`prim@f32`] or [Wikipedia on +/// as many bits as `f64`. Please see [the documentation for `f32`](prim@f32) or [Wikipedia on /// quad-precision values][wikipedia] for more information. /// /// Note that no platforms have hardware support for `f128` without enabling target specific features, /// as for all instruction set architectures `f128` is considered an optional feature. -/// Only Power ISA ("PowerPC") and RISCV specify it, and only certain microarchitectures +/// Only Power ISA ("PowerPC") and RISC-V specify it, and only certain microarchitectures /// actually implement it. For x86-64 and AArch64, ISA support is not even specified, /// so it will always be a software implementation significantly slower than `f64`. /// diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs index 68fce3960c7..19fe03d57cc 100644 --- a/library/core/src/ptr/alignment.rs +++ b/library/core/src/ptr/alignment.rs @@ -1,5 +1,4 @@ use crate::num::NonZero; -#[cfg(debug_assertions)] use crate::ub_checks::assert_unsafe_precondition; use crate::{cmp, fmt, hash, mem, num}; @@ -77,7 +76,6 @@ impl Alignment { #[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")] #[inline] pub const unsafe fn new_unchecked(align: usize) -> Self { - #[cfg(debug_assertions)] assert_unsafe_precondition!( check_language_ub, "Alignment::new_unchecked requires a power of two", diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 93bbd92593f..3b635e2a4aa 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -239,24 +239,7 @@ impl *const T { /// # Safety /// /// When calling this method, you have to ensure that *either* the pointer is null *or* - /// all of the following is true: - /// - /// * The pointer must be properly aligned. - /// - /// * It must be "dereferenceable" in the sense defined in [the module documentation]. - /// - /// * The pointer must point to an initialized instance of `T`. - /// - /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is - /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. - /// In particular, while this reference exists, the memory the pointer points to must - /// not get mutated (except inside `UnsafeCell`). - /// - /// This applies even if the result of this method is unused! - /// (The part about being initialized is not yet fully decided, but until - /// it is, the only safe approach is to ensure that they are indeed initialized.) - /// - /// [the module documentation]: crate::ptr#safety + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). /// /// # Examples /// @@ -302,24 +285,8 @@ impl *const T { /// /// # Safety /// - /// When calling this method, you have to ensure that all of the following is true: - /// - /// * The pointer must be properly aligned. - /// - /// * It must be "dereferenceable" in the sense defined in [the module documentation]. - /// - /// * The pointer must point to an initialized instance of `T`. - /// - /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is - /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. - /// In particular, while this reference exists, the memory the pointer points to must - /// not get mutated (except inside `UnsafeCell`). - /// - /// This applies even if the result of this method is unused! - /// (The part about being initialized is not yet fully decided, but until - /// it is, the only safe approach is to ensure that they are indeed initialized.) - /// - /// [the module documentation]: crate::ptr#safety + /// When calling this method, you have to ensure that + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). /// /// # Examples /// @@ -350,20 +317,7 @@ impl *const T { /// # Safety /// /// When calling this method, you have to ensure that *either* the pointer is null *or* - /// all of the following is true: - /// - /// * The pointer must be properly aligned. - /// - /// * It must be "dereferenceable" in the sense defined in [the module documentation]. - /// - /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is - /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. - /// In particular, while this reference exists, the memory the pointer points to must - /// not get mutated (except inside `UnsafeCell`). - /// - /// This applies even if the result of this method is unused! - /// - /// [the module documentation]: crate::ptr#safety + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). /// /// # Examples /// diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 25d8f4a0adb..d7ed4edcc00 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -56,6 +56,44 @@ //! has size 0, i.e., even if memory is not actually touched. Consider using //! [`NonNull::dangling`] in such cases. //! +//! ## Pointer to reference conversion +//! +//! When converting a pointer to a reference (e.g. via `&*ptr` or `&mut *ptr`), +//! there are several rules that must be followed: +//! +//! * The pointer must be properly aligned. +//! +//! * It must be non-null. +//! +//! * It must be "dereferenceable" in the sense defined above. +//! +//! * The pointer must point to a [valid value] of type `T`. +//! +//! * You must enforce Rust's aliasing rules. The exact aliasing rules are not decided yet, so we +//! only give a rough overview here. The rules also depend on whether a mutable or a shared +//! reference is being created. +//! * When creating a mutable reference, then while this reference exists, the memory it points to +//! must not get accessed (read or written) through any other pointer or reference not derived +//! from this reference. +//! * When creating a shared reference, then while this reference exists, the memory it points to +//! must not get mutated (except inside `UnsafeCell`). +//! +//! If a pointer follows all of these rules, it is said to be +//! *convertible to a (mutable or shared) reference*. +// ^ we use this term instead of saying that the produced reference must +// be valid, as the validity of a reference is easily confused for the +// validity of the thing it refers to, and while the two concepts are +// closly related, they are not identical. +//! +//! These rules apply even if the result is unused! +//! (The part about being initialized is not yet fully decided, but until +//! it is, the only safe approach is to ensure that they are indeed initialized.) +//! +//! An example of the implications of the above rules is that an expression such +//! as `unsafe { &*(0 as *const u8) }` is Immediate Undefined Behavior. +//! +//! [valid value]: ../../reference/behavior-considered-undefined.html#invalid-values +//! //! ## Allocated object //! //! An *allocated object* is a subset of program memory which is addressable @@ -2130,6 +2168,33 @@ pub fn addr_eq(p: *const T, q: *const U) -> bool { (p as *const ()) == (q as *const ()) } +/// Compares the *addresses* of the two function pointers for equality. +/// +/// Function pointers comparisons can have surprising results since +/// they are never guaranteed to be unique and could vary between different +/// code generation units. Furthermore, different functions could have the +/// same address after being merged together. +/// +/// This is the same as `f == g` but using this function makes clear +/// that you are aware of these potentially surprising semantics. +/// +/// # Examples +/// +/// ``` +/// #![feature(ptr_fn_addr_eq)] +/// use std::ptr; +/// +/// fn a() { println!("a"); } +/// fn b() { println!("b"); } +/// assert!(!ptr::fn_addr_eq(a as fn(), b as fn())); +/// ``` +#[unstable(feature = "ptr_fn_addr_eq", issue = "129322")] +#[inline(always)] +#[must_use = "function pointer comparison produces a value"] +pub fn fn_addr_eq(f: T, g: U) -> bool { + f.addr() == g.addr() +} + /// Hash a raw pointer. /// /// This can be used to hash a `&T` reference (which coerces to `*const T` implicitly) @@ -2209,6 +2274,9 @@ impl fmt::Debug for F { /// Creates a `const` raw pointer to a place, without creating an intermediate reference. /// +/// `addr_of!(expr)` is equivalent to `&raw const expr`. The macro is *soft-deprecated*; +/// use `&raw const` instead. +/// /// Creating a reference with `&`/`&mut` is only allowed if the pointer is properly aligned /// and points to initialized data. For cases where those requirements do not hold, /// raw pointers should be used instead. However, `&expr as *const _` creates a reference @@ -2283,6 +2351,9 @@ pub macro addr_of($place:expr) { /// Creates a `mut` raw pointer to a place, without creating an intermediate reference. /// +/// `addr_of_mut!(expr)` is equivalent to `&raw mut expr`. The macro is *soft-deprecated*; +/// use `&raw mut` instead. +/// /// Creating a reference with `&`/`&mut` is only allowed if the pointer is properly aligned /// and points to initialized data. For cases where those requirements do not hold, /// raw pointers should be used instead. However, `&mut expr as *mut _` creates a reference diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index bcf9b889182..42975cc927b 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -247,24 +247,7 @@ impl *mut T { /// # Safety /// /// When calling this method, you have to ensure that *either* the pointer is null *or* - /// all of the following is true: - /// - /// * The pointer must be properly aligned. - /// - /// * It must be "dereferenceable" in the sense defined in [the module documentation]. - /// - /// * The pointer must point to an initialized instance of `T`. - /// - /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is - /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. - /// In particular, while this reference exists, the memory the pointer points to must - /// not get mutated (except inside `UnsafeCell`). - /// - /// This applies even if the result of this method is unused! - /// (The part about being initialized is not yet fully decided, but until - /// it is, the only safe approach is to ensure that they are indeed initialized.) - /// - /// [the module documentation]: crate::ptr#safety + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). /// /// # Examples /// @@ -313,24 +296,7 @@ impl *mut T { /// /// # Safety /// - /// When calling this method, you have to ensure that all of the following is true: - /// - /// * The pointer must be properly aligned. - /// - /// * It must be "dereferenceable" in the sense defined in [the module documentation]. - /// - /// * The pointer must point to an initialized instance of `T`. - /// - /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is - /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. - /// In particular, while this reference exists, the memory the pointer points to must - /// not get mutated (except inside `UnsafeCell`). - /// - /// This applies even if the result of this method is unused! - /// (The part about being initialized is not yet fully decided, but until - /// it is, the only safe approach is to ensure that they are indeed initialized.) - /// - /// [the module documentation]: crate::ptr#safety + /// When calling this method, you have to ensure that the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). /// /// # Examples /// @@ -364,20 +330,9 @@ impl *mut T { /// # Safety /// /// When calling this method, you have to ensure that *either* the pointer is null *or* - /// all of the following is true: - /// - /// * The pointer must be properly aligned. - /// - /// * It must be "dereferenceable" in the sense defined in [the module documentation]. - /// - /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is - /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. - /// In particular, while this reference exists, the memory the pointer points to must - /// not get mutated (except inside `UnsafeCell`). - /// - /// This applies even if the result of this method is unused! - /// - /// [the module documentation]: crate::ptr#safety + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). + /// Note that because the created reference is to `MaybeUninit`, the + /// source pointer can point to uninitialized memory. /// /// # Examples /// @@ -609,25 +564,10 @@ impl *mut T { /// /// # Safety /// - /// When calling this method, you have to ensure that *either* the pointer is null *or* - /// all of the following is true: + /// When calling this method, you have to ensure that *either* + /// the pointer is null *or* + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). /// - /// * The pointer must be properly aligned. - /// - /// * It must be "dereferenceable" in the sense defined in [the module documentation]. - /// - /// * The pointer must point to an initialized instance of `T`. - /// - /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is - /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. - /// In particular, while this reference exists, the memory the pointer points to must - /// not get accessed (read or written) through any other pointer. - /// - /// This applies even if the result of this method is unused! - /// (The part about being initialized is not yet fully decided, but until - /// it is, the only safe approach is to ensure that they are indeed initialized.) - /// - /// [the module documentation]: crate::ptr#safety /// /// # Examples /// @@ -675,24 +615,8 @@ impl *mut T { /// /// # Safety /// - /// When calling this method, you have to ensure that all of the following is true: - /// - /// * The pointer must be properly aligned. - /// - /// * It must be "dereferenceable" in the sense defined in [the module documentation]. - /// - /// * The pointer must point to an initialized instance of `T`. - /// - /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is - /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. - /// In particular, while this reference exists, the memory the pointer points to must - /// not get mutated (except inside `UnsafeCell`). - /// - /// This applies even if the result of this method is unused! - /// (The part about being initialized is not yet fully decided, but until - /// it is, the only safe approach is to ensure that they are indeed initialized.) - /// - /// [the module documentation]: crate::ptr#safety + /// When calling this method, you have to ensure that + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). /// /// # Examples /// @@ -727,20 +651,7 @@ impl *mut T { /// # Safety /// /// When calling this method, you have to ensure that *either* the pointer is null *or* - /// all of the following is true: - /// - /// * The pointer must be properly aligned. - /// - /// * It must be "dereferenceable" in the sense defined in [the module documentation]. - /// - /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is - /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. - /// In particular, while this reference exists, the memory the pointer points to must - /// not get accessed (read or written) through any other pointer. - /// - /// This applies even if the result of this method is unused! - /// - /// [the module documentation]: crate::ptr#safety + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index d6be37a76bb..b1429fff744 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -126,20 +126,10 @@ impl NonNull { /// /// # Safety /// - /// When calling this method, you have to ensure that all of the following is true: - /// - /// * The pointer must be properly aligned. - /// - /// * It must be "dereferenceable" in the sense defined in [the module documentation]. - /// - /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is - /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. - /// In particular, while this reference exists, the memory the pointer points to must - /// not get mutated (except inside `UnsafeCell`). - /// - /// This applies even if the result of this method is unused! - /// - /// [the module documentation]: crate::ptr#safety + /// When calling this method, you have to ensure that + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). + /// Note that because the created reference is to `MaybeUninit`, the + /// source pointer can point to uninitialized memory. #[inline] #[must_use] #[unstable(feature = "ptr_as_uninit", issue = "75402")] @@ -160,20 +150,10 @@ impl NonNull { /// /// # Safety /// - /// When calling this method, you have to ensure that all of the following is true: - /// - /// * The pointer must be properly aligned. - /// - /// * It must be "dereferenceable" in the sense defined in [the module documentation]. - /// - /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is - /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. - /// In particular, while this reference exists, the memory the pointer points to must - /// not get accessed (read or written) through any other pointer. - /// - /// This applies even if the result of this method is unused! - /// - /// [the module documentation]: crate::ptr#safety + /// When calling this method, you have to ensure that + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). + /// Note that because the created reference is to `MaybeUninit`, the + /// source pointer can point to uninitialized memory. #[inline] #[must_use] #[unstable(feature = "ptr_as_uninit", issue = "75402")] @@ -359,22 +339,8 @@ impl NonNull { /// /// # Safety /// - /// When calling this method, you have to ensure that all of the following is true: - /// - /// * The pointer must be properly aligned. - /// - /// * It must be "dereferenceable" in the sense defined in [the module documentation]. - /// - /// * The pointer must point to an initialized instance of `T`. - /// - /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is - /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. - /// In particular, while this reference exists, the memory the pointer points to must - /// not get mutated (except inside `UnsafeCell`). - /// - /// This applies even if the result of this method is unused! - /// (The part about being initialized is not yet fully decided, but until - /// it is, the only safe approach is to ensure that they are indeed initialized.) + /// When calling this method, you have to ensure that + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). /// /// # Examples /// @@ -410,22 +376,8 @@ impl NonNull { /// /// # Safety /// - /// When calling this method, you have to ensure that all of the following is true: - /// - /// * The pointer must be properly aligned. - /// - /// * It must be "dereferenceable" in the sense defined in [the module documentation]. - /// - /// * The pointer must point to an initialized instance of `T`. - /// - /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is - /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. - /// In particular, while this reference exists, the memory the pointer points to must - /// not get accessed (read or written) through any other pointer. - /// - /// This applies even if the result of this method is unused! - /// (The part about being initialized is not yet fully decided, but until - /// it is, the only safe approach is to ensure that they are indeed initialized.) + /// When calling this method, you have to ensure that + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). /// # Examples /// /// ``` diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 7f278296b7b..73b11f803d9 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1481,7 +1481,6 @@ impl Result { #[track_caller] #[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")] pub unsafe fn unwrap_unchecked(self) -> T { - debug_assert!(self.is_ok()); match self { Ok(t) => t, // SAFETY: the safety contract must be upheld by the caller. @@ -1513,7 +1512,6 @@ impl Result { #[track_caller] #[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")] pub unsafe fn unwrap_err_unchecked(self) -> E { - debug_assert!(self.is_err()); match self { // SAFETY: the safety contract must be upheld by the caller. Ok(_) => unsafe { hint::unreachable_unchecked() }, diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index c76157720b7..c7918499d4a 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -3667,8 +3667,8 @@ impl [T] { { // The panic code path was put into a cold function to not bloat the // call site. - #[inline(never)] - #[cold] + #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] + #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] fn len_mismatch_fail(dst_len: usize, src_len: usize) -> ! { panic!( diff --git a/library/core/src/slice/sort/shared/smallsort.rs b/library/core/src/slice/sort/shared/smallsort.rs index db0c5c72822..fae628a7c14 100644 --- a/library/core/src/slice/sort/shared/smallsort.rs +++ b/library/core/src/slice/sort/shared/smallsort.rs @@ -840,7 +840,8 @@ unsafe fn bidirectional_merge bool>( } } -#[inline(never)] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] +#[cfg_attr(feature = "panic_immediate_abort", inline)] fn panic_on_ord_violation() -> ! { // This is indicative of a logic bug in the user-provided comparison function or Ord // implementation. They are expected to implement a total order as explained in the Ord diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index 06f796f9f3a..681ec79c0b7 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -241,24 +241,35 @@ impl<'a> CharIndices<'a> { /// Returns the byte position of the next character, or the length /// of the underlying string if there are no more characters. /// + /// This means that, when the iterator has not been fully consumed, + /// the returned value will match the index that will be returned + /// by the next call to [`next()`](Self::next). + /// /// # Examples /// /// ``` - /// #![feature(char_indices_offset)] /// let mut chars = "a楽".char_indices(); /// + /// // `next()` has not been called yet, so `offset()` returns the byte + /// // index of the first character of the string, which is always 0. /// assert_eq!(chars.offset(), 0); + /// // As expected, the first call to `next()` also returns 0 as index. /// assert_eq!(chars.next(), Some((0, 'a'))); /// + /// // `next()` has been called once, so `offset()` returns the byte index + /// // of the second character ... /// assert_eq!(chars.offset(), 1); + /// // ... which matches the index returned by the next call to `next()`. /// assert_eq!(chars.next(), Some((1, '楽'))); /// + /// // Once the iterator has been consumed, `offset()` returns the length + /// // in bytes of the string. /// assert_eq!(chars.offset(), 4); /// assert_eq!(chars.next(), None); /// ``` #[inline] #[must_use] - #[unstable(feature = "char_indices_offset", issue = "83871")] + #[stable(feature = "char_indices_offset", since = "CURRENT_RUSTC_VERSION")] pub fn offset(&self) -> usize { self.front_offset } diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 56517348dc7..cf9f1bfc0eb 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -2818,5 +2818,5 @@ impl_fn_for_zst! { } // This is required to make `impl From<&str> for Box` and `impl From for Box` not overlap. -#[stable(feature = "rust1", since = "1.0.0")] +#[stable(feature = "error_in_core_neg_impl", since = "1.65.0")] impl !crate::error::Error for &str {} diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs index bfa1cf096e2..6aab22177ab 100644 --- a/library/core/src/task/poll.rs +++ b/library/core/src/task/poll.rs @@ -5,6 +5,8 @@ use crate::ops::{self, ControlFlow}; /// Indicates whether a value is available or if the current task has been /// scheduled to receive a wakeup instead. +/// +/// This is returned by [`Future::poll`](core::future::Future::poll). #[must_use = "this `Poll` may be a `Pending` variant, which should be handled"] #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] #[lang = "Poll"] diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 29932c0d1ff..7e5c1574f53 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -530,10 +530,18 @@ impl Waker { /// Returns a reference to a `Waker` that does nothing when used. /// + // Note! Much of the documentation for this method is duplicated + // in the docs for `LocalWaker::noop`. + // If you edit it, consider editing the other copy too. + // /// This is mostly useful for writing tests that need a [`Context`] to poll /// some futures, but are not expecting those futures to wake the waker or /// do not need to do anything specific if it happens. /// + /// More generally, using `Waker::noop()` to poll a future + /// means discarding the notification of when the future should be polled again. + /// So it should only be used when such a notification will not be needed to make progress. + /// /// If an owned `Waker` is needed, `clone()` this one. /// /// # Examples @@ -783,12 +791,22 @@ impl LocalWaker { Self { waker } } - /// Creates a new `LocalWaker` that does nothing when `wake` is called. + /// Returns a reference to a `LocalWaker` that does nothing when used. /// + // Note! Much of the documentation for this method is duplicated + // in the docs for `Waker::noop`. + // If you edit it, consider editing the other copy too. + // /// This is mostly useful for writing tests that need a [`Context`] to poll /// some futures, but are not expecting those futures to wake the waker or /// do not need to do anything specific if it happens. /// + /// More generally, using `LocalWaker::noop()` to poll a future + /// means discarding the notification of when the future should be polled again, + /// So it should only be used when such a notification will not be needed to make progress. + /// + /// If an owned `LocalWaker` is needed, `clone()` this one. + /// /// # Examples /// /// ``` diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs index 65d4d5cf2ce..9ec92e28450 100644 --- a/library/core/src/tuple.rs +++ b/library/core/src/tuple.rs @@ -122,23 +122,29 @@ macro_rules! tuple_impls { } } - #[stable(feature = "array_tuple_conv", since = "1.71.0")] - impl From<[T; ${count($T)}]> for ($(${ignore($T)} T,)+) { - #[inline] - #[allow(non_snake_case)] - fn from(array: [T; ${count($T)}]) -> Self { - let [$($T,)+] = array; - ($($T,)+) + maybe_tuple_doc! { + $($T)+ @ + #[stable(feature = "array_tuple_conv", since = "1.71.0")] + impl From<[T; ${count($T)}]> for ($(${ignore($T)} T,)+) { + #[inline] + #[allow(non_snake_case)] + fn from(array: [T; ${count($T)}]) -> Self { + let [$($T,)+] = array; + ($($T,)+) + } } } - #[stable(feature = "array_tuple_conv", since = "1.71.0")] - impl From<($(${ignore($T)} T,)+)> for [T; ${count($T)}] { - #[inline] - #[allow(non_snake_case)] - fn from(tuple: ($(${ignore($T)} T,)+)) -> Self { - let ($($T,)+) = tuple; - [$($T,)+] + maybe_tuple_doc! { + $($T)+ @ + #[stable(feature = "array_tuple_conv", since = "1.71.0")] + impl From<($(${ignore($T)} T,)+)> for [T; ${count($T)}] { + #[inline] + #[allow(non_snake_case)] + fn from(tuple: ($(${ignore($T)} T,)+)) -> Self { + let ($($T,)+) = tuple; + [$($T,)+] + } } } } @@ -148,7 +154,7 @@ macro_rules! tuple_impls { // Otherwise, it hides the docs entirely. macro_rules! maybe_tuple_doc { ($a:ident @ #[$meta:meta] $item:item) => { - #[doc(fake_variadic)] + #[cfg_attr(not(bootstrap), doc(fake_variadic))] #[doc = "This trait is implemented for tuples up to twelve items long."] #[$meta] $item diff --git a/library/core/src/ub_checks.rs b/library/core/src/ub_checks.rs index b65b48c162d..c1a8c34539e 100644 --- a/library/core/src/ub_checks.rs +++ b/library/core/src/ub_checks.rs @@ -10,7 +10,7 @@ use crate::intrinsics::{self, const_eval_select}; /// macro for language UB are always ignored. /// /// This macro should be called as -/// `assert_unsafe_precondition!(check_{library,lang}_ub, "message", (ident: type = expr, ident: type = expr) => check_expr)` +/// `assert_unsafe_precondition!(check_{library,language}_ub, "message", (ident: type = expr, ident: type = expr) => check_expr)` /// where each `expr` will be evaluated and passed in as function argument `ident: type`. Then all /// those arguments are passed to a function with the body `check_expr`. /// Pick `check_language_ub` when this is guarding a violation of language UB, i.e., immediate UB diff --git a/library/core/tests/clone.rs b/library/core/tests/clone.rs index b7130f16f87..71a328733b7 100644 --- a/library/core/tests/clone.rs +++ b/library/core/tests/clone.rs @@ -1,5 +1,7 @@ use core::clone::CloneToUninit; +use core::ffi::CStr; use core::mem::MaybeUninit; +use core::ptr; #[test] #[allow(suspicious_double_ref_op)] @@ -81,3 +83,41 @@ fn test_clone_to_uninit_slice_drops_on_panic() { drop(a); assert_eq!(COUNTER.load(Relaxed), 0); } + +#[test] +fn test_clone_to_uninit_str() { + let a = "hello"; + + let mut storage: MaybeUninit<[u8; 5]> = MaybeUninit::uninit(); + unsafe { a.clone_to_uninit(storage.as_mut_ptr() as *mut [u8] as *mut str) }; + assert_eq!(a.as_bytes(), unsafe { storage.assume_init() }.as_slice()); + + let mut b: Box = "world".into(); + assert_eq!(a.len(), b.len()); + assert_ne!(a, &*b); + unsafe { a.clone_to_uninit(ptr::from_mut::(&mut b)) }; + assert_eq!(a, &*b); +} + +#[test] +fn test_clone_to_uninit_cstr() { + let a = c"hello"; + + let mut storage: MaybeUninit<[u8; 6]> = MaybeUninit::uninit(); + unsafe { a.clone_to_uninit(storage.as_mut_ptr() as *mut [u8] as *mut CStr) }; + assert_eq!(a.to_bytes_with_nul(), unsafe { storage.assume_init() }.as_slice()); + + let mut b: Box = c"world".into(); + assert_eq!(a.count_bytes(), b.count_bytes()); + assert_ne!(a, &*b); + unsafe { a.clone_to_uninit(ptr::from_mut::(&mut b)) }; + assert_eq!(a, &*b); +} + +#[test] +fn cstr_metadata_is_length_with_nul() { + let s: &CStr = c"abcdef"; + let p: *const CStr = ptr::from_ref(s); + let bytes: *const [u8] = p as *const [u8]; + assert_eq!(s.to_bytes_with_nul().len(), bytes.len()); +} diff --git a/library/core/tests/fmt/builders.rs b/library/core/tests/fmt/builders.rs index 2bdc334b7c0..ba4801f5912 100644 --- a/library/core/tests/fmt/builders.rs +++ b/library/core/tests/fmt/builders.rs @@ -79,23 +79,23 @@ mod debug_struct { } assert_eq!( - "Bar { foo: Foo { bar: true, baz: 10/20 }, hello: \"world\" }", + r#"Bar { foo: Foo { bar: true, baz: 10/20 }, hello: "world" }"#, format!("{Bar:?}") ); assert_eq!( - "Bar { + r#"Bar { foo: Foo { bar: true, baz: 10/20, }, - hello: \"world\", -}", + hello: "world", +}"#, format!("{Bar:#?}") ); } #[test] - fn test_only_non_exhaustive() { + fn test_empty_non_exhaustive() { struct Foo; impl fmt::Debug for Foo { @@ -157,19 +157,19 @@ mod debug_struct { } assert_eq!( - "Bar { foo: Foo { bar: true, baz: 10/20, .. }, hello: \"world\", .. }", + r#"Bar { foo: Foo { bar: true, baz: 10/20, .. }, hello: "world", .. }"#, format!("{Bar:?}") ); assert_eq!( - "Bar { + r#"Bar { foo: Foo { bar: true, baz: 10/20, .. }, - hello: \"world\", + hello: "world", .. -}", +}"#, format!("{Bar:#?}") ); } @@ -249,15 +249,89 @@ mod debug_tuple { } } - assert_eq!("Bar(Foo(true, 10/20), \"world\")", format!("{Bar:?}")); + assert_eq!(r#"Bar(Foo(true, 10/20), "world")"#, format!("{Bar:?}")); assert_eq!( - "Bar( + r#"Bar( Foo( true, 10/20, ), - \"world\", + "world", +)"#, + format!("{Bar:#?}") + ); + } + + #[test] + fn test_empty_non_exhaustive() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_tuple("Foo").finish_non_exhaustive() + } + } + + assert_eq!("Foo(..)", format!("{Foo:?}")); + assert_eq!("Foo(..)", format!("{Foo:#?}")); + } + + #[test] + fn test_multiple_and_non_exhaustive() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_tuple("Foo") + .field(&true) + .field(&format_args!("{}/{}", 10, 20)) + .finish_non_exhaustive() + } + } + + assert_eq!("Foo(true, 10/20, ..)", format!("{Foo:?}")); + assert_eq!( + "Foo( + true, + 10/20, + .. )", + format!("{Foo:#?}") + ); + } + + #[test] + fn test_nested_non_exhaustive() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_tuple("Foo") + .field(&true) + .field(&format_args!("{}/{}", 10, 20)) + .finish_non_exhaustive() + } + } + + struct Bar; + + impl fmt::Debug for Bar { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_tuple("Bar").field(&Foo).field(&"world").finish_non_exhaustive() + } + } + + assert_eq!(r#"Bar(Foo(true, 10/20, ..), "world", ..)"#, format!("{Bar:?}")); + assert_eq!( + r#"Bar( + Foo( + true, + 10/20, + .. + ), + "world", + .. +)"#, format!("{Bar:#?}") ); } @@ -301,11 +375,11 @@ mod debug_map { assert_eq!(format!("{Entry:?}"), format!("{KeyValue:?}")); assert_eq!(format!("{Entry:#?}"), format!("{KeyValue:#?}")); - assert_eq!("{\"bar\": true}", format!("{Entry:?}")); + assert_eq!(r#"{"bar": true}"#, format!("{Entry:?}")); assert_eq!( - "{ - \"bar\": true, -}", + r#"{ + "bar": true, +}"#, format!("{Entry:#?}") ); } @@ -339,12 +413,12 @@ mod debug_map { assert_eq!(format!("{Entry:?}"), format!("{KeyValue:?}")); assert_eq!(format!("{Entry:#?}"), format!("{KeyValue:#?}")); - assert_eq!("{\"bar\": true, 10: 10/20}", format!("{Entry:?}")); + assert_eq!(r#"{"bar": true, 10: 10/20}"#, format!("{Entry:?}")); assert_eq!( - "{ - \"bar\": true, + r#"{ + "bar": true, 10: 10/20, -}", +}"#, format!("{Entry:#?}") ); } @@ -371,21 +445,20 @@ mod debug_map { } assert_eq!( - "{\"foo\": {\"bar\": true, 10: 10/20}, \ - {\"bar\": true, 10: 10/20}: \"world\"}", + r#"{"foo": {"bar": true, 10: 10/20}, {"bar": true, 10: 10/20}: "world"}"#, format!("{Bar:?}") ); assert_eq!( - "{ - \"foo\": { - \"bar\": true, + r#"{ + "foo": { + "bar": true, 10: 10/20, }, { - \"bar\": true, + "bar": true, 10: 10/20, - }: \"world\", -}", + }: "world", +}"#, format!("{Bar:#?}") ); } @@ -471,6 +544,103 @@ mod debug_map { let _ = format!("{Foo:?}"); } + + #[test] + fn test_empty_non_exhaustive() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_map().finish_non_exhaustive() + } + } + + assert_eq!("{..}", format!("{Foo:?}")); + assert_eq!("{..}", format!("{Foo:#?}")); + } + + #[test] + fn test_multiple_and_non_exhaustive() { + struct Entry; + + impl fmt::Debug for Entry { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_map() + .entry(&"bar", &true) + .entry(&10, &format_args!("{}/{}", 10, 20)) + .finish_non_exhaustive() + } + } + + struct KeyValue; + + impl fmt::Debug for KeyValue { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_map() + .key(&"bar") + .value(&true) + .key(&10) + .value(&format_args!("{}/{}", 10, 20)) + .finish_non_exhaustive() + } + } + + assert_eq!(format!("{Entry:?}"), format!("{KeyValue:?}")); + assert_eq!(format!("{Entry:#?}"), format!("{KeyValue:#?}")); + + assert_eq!(r#"{"bar": true, 10: 10/20, ..}"#, format!("{Entry:?}")); + assert_eq!( + r#"{ + "bar": true, + 10: 10/20, + .. +}"#, + format!("{Entry:#?}") + ); + } + + #[test] + fn test_nested_non_exhaustive() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_map() + .entry(&"bar", &true) + .entry(&10, &format_args!("{}/{}", 10, 20)) + .finish_non_exhaustive() + } + } + + struct Bar; + + impl fmt::Debug for Bar { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_map().entry(&"foo", &Foo).entry(&Foo, &"world").finish_non_exhaustive() + } + } + + assert_eq!( + r#"{"foo": {"bar": true, 10: 10/20, ..}, {"bar": true, 10: 10/20, ..}: "world", ..}"#, + format!("{Bar:?}") + ); + assert_eq!( + r#"{ + "foo": { + "bar": true, + 10: 10/20, + .. + }, + { + "bar": true, + 10: 10/20, + .. + }: "world", + .. +}"#, + format!("{Bar:#?}") + ); + } } mod debug_set { @@ -547,15 +717,89 @@ mod debug_set { } } - assert_eq!("{{true, 10/20}, \"world\"}", format!("{Bar:?}")); + assert_eq!(r#"{{true, 10/20}, "world"}"#, format!("{Bar:?}")); assert_eq!( - "{ + r#"{ { true, 10/20, }, - \"world\", + "world", +}"#, + format!("{Bar:#?}") + ); + } + + #[test] + fn test_empty_non_exhaustive() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_set().finish_non_exhaustive() + } + } + + assert_eq!("{..}", format!("{Foo:?}")); + assert_eq!("{..}", format!("{Foo:#?}")); + } + + #[test] + fn test_multiple_and_non_exhaustive() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_set() + .entry(&true) + .entry(&format_args!("{}/{}", 10, 20)) + .finish_non_exhaustive() + } + } + + assert_eq!("{true, 10/20, ..}", format!("{Foo:?}")); + assert_eq!( + "{ + true, + 10/20, + .. }", + format!("{Foo:#?}") + ); + } + + #[test] + fn test_nested_non_exhaustive() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_set() + .entry(&true) + .entry(&format_args!("{}/{}", 10, 20)) + .finish_non_exhaustive() + } + } + + struct Bar; + + impl fmt::Debug for Bar { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_set().entry(&Foo).entry(&"world").finish_non_exhaustive() + } + } + + assert_eq!(r#"{{true, 10/20, ..}, "world", ..}"#, format!("{Bar:?}")); + assert_eq!( + r#"{ + { + true, + 10/20, + .. + }, + "world", + .. +}"#, format!("{Bar:#?}") ); } @@ -635,15 +879,89 @@ mod debug_list { } } - assert_eq!("[[true, 10/20], \"world\"]", format!("{Bar:?}")); + assert_eq!(r#"[[true, 10/20], "world"]"#, format!("{Bar:?}")); assert_eq!( - "[ + r#"[ [ true, 10/20, ], - \"world\", + "world", +]"#, + format!("{Bar:#?}") + ); + } + + #[test] + fn test_empty_non_exhaustive() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_list().finish_non_exhaustive() + } + } + + assert_eq!("[..]", format!("{Foo:?}")); + assert_eq!("[..]", format!("{Foo:#?}")); + } + + #[test] + fn test_multiple_non_exhaustive() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_list() + .entry(&true) + .entry(&format_args!("{}/{}", 10, 20)) + .finish_non_exhaustive() + } + } + + assert_eq!("[true, 10/20, ..]", format!("{Foo:?}")); + assert_eq!( + "[ + true, + 10/20, + .. ]", + format!("{Foo:#?}") + ); + } + + #[test] + fn test_nested_non_exhaustive() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_list() + .entry(&true) + .entry(&format_args!("{}/{}", 10, 20)) + .finish_non_exhaustive() + } + } + + struct Bar; + + impl fmt::Debug for Bar { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_list().entry(&Foo).entry(&"world").finish_non_exhaustive() + } + } + + assert_eq!(r#"[[true, 10/20, ..], "world", ..]"#, format!("{Bar:?}")); + assert_eq!( + r#"[ + [ + true, + 10/20, + .. + ], + "world", + .. +]"#, format!("{Bar:#?}") ); } diff --git a/library/core/tests/iter/adapters/take.rs b/library/core/tests/iter/adapters/take.rs index 39afa2cbfca..65a8a93b4a9 100644 --- a/library/core/tests/iter/adapters/take.rs +++ b/library/core/tests/iter/adapters/take.rs @@ -170,3 +170,93 @@ fn test_byref_take_consumed_items() { assert_eq!(count, 70); assert_eq!(inner, 90..90); } + +#[test] +fn test_exact_size_take_repeat() { + let mut iter = core::iter::repeat(42).take(40); + assert_eq!((40, Some(40)), iter.size_hint()); + assert_eq!(40, iter.len()); + + assert_eq!(Some(42), iter.next()); + assert_eq!((39, Some(39)), iter.size_hint()); + assert_eq!(39, iter.len()); + + assert_eq!(Some(42), iter.next_back()); + assert_eq!((38, Some(38)), iter.size_hint()); + assert_eq!(38, iter.len()); + + assert_eq!(Some(42), iter.nth(3)); + assert_eq!((34, Some(34)), iter.size_hint()); + assert_eq!(34, iter.len()); + + assert_eq!(Some(42), iter.nth_back(3)); + assert_eq!((30, Some(30)), iter.size_hint()); + assert_eq!(30, iter.len()); + + assert_eq!(Ok(()), iter.advance_by(10)); + assert_eq!((20, Some(20)), iter.size_hint()); + assert_eq!(20, iter.len()); + + assert_eq!(Ok(()), iter.advance_back_by(10)); + assert_eq!((10, Some(10)), iter.size_hint()); + assert_eq!(10, iter.len()); +} + +#[test] +fn test_exact_size_take_repeat_with() { + let mut counter = 0; + let mut iter = core::iter::repeat_with(move || { + counter += 1; + counter + }) + .take(40); + assert_eq!((40, Some(40)), iter.size_hint()); + assert_eq!(40, iter.len()); + + assert_eq!(Some(1), iter.next()); + assert_eq!((39, Some(39)), iter.size_hint()); + assert_eq!(39, iter.len()); + + assert_eq!(Some(5), iter.nth(3)); + assert_eq!((35, Some(35)), iter.size_hint()); + assert_eq!(35, iter.len()); + + assert_eq!(Ok(()), iter.advance_by(10)); + assert_eq!((25, Some(25)), iter.size_hint()); + assert_eq!(25, iter.len()); + + assert_eq!(Some(16), iter.next()); + assert_eq!((24, Some(24)), iter.size_hint()); + assert_eq!(24, iter.len()); +} + +// This is https://github.com/rust-lang/rust/issues/104729 with all uses of +// repeat(0) were replaced by repeat(0).take(20). +#[test] +fn test_reverse_on_zip() { + let vec_1 = [1; 10]; + + let zipped_iter = vec_1.iter().copied().zip(core::iter::repeat(0).take(20)); + + // Forward + for (one, zero) in zipped_iter { + assert_eq!((1, 0), (one, zero)); + } + + let rev_vec_iter = vec_1.iter().rev(); + let rev_repeat_iter = std::iter::repeat(0).take(20).rev(); + + // Manual reversed zip + let rev_zipped_iter = rev_vec_iter.zip(rev_repeat_iter); + + for (&one, zero) in rev_zipped_iter { + assert_eq!((1, 0), (one, zero)); + } + + let zipped_iter = vec_1.iter().zip(core::iter::repeat(0).take(20)); + + // Cannot call rev here for automatic reversed zip constuction + for (&one, zero) in zipped_iter.rev() { + assert_eq!((1, 0), (one, zero)); + } +} diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 8872b4cbfd5..c205f028dd3 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -43,6 +43,7 @@ #![feature(core_io_borrowed_buf)] #![feature(core_private_bignum)] #![feature(core_private_diy_float)] +#![feature(debug_more_non_exhaustive)] #![feature(dec2flt)] #![feature(duration_constants)] #![feature(duration_constructors)] @@ -73,7 +74,6 @@ #![feature(iter_next_chunk)] #![feature(iter_order_by)] #![feature(iter_partition_in_place)] -#![feature(iter_repeat_n)] #![feature(iterator_try_collect)] #![feature(iterator_try_reduce)] #![feature(layout_for_ptr)] @@ -141,7 +141,6 @@ mod intrinsics; mod io; mod iter; mod lazy; -#[cfg(test)] mod macros; mod manually_drop; mod mem; diff --git a/library/core/tests/num/float_iter_sum_identity.rs b/library/core/tests/num/float_iter_sum_identity.rs new file mode 100644 index 00000000000..6d3224522a8 --- /dev/null +++ b/library/core/tests/num/float_iter_sum_identity.rs @@ -0,0 +1,27 @@ +#[test] +fn f32_ref() { + let x: f32 = -0.0; + let still_x: f32 = [x].iter().sum(); + assert_eq!(1. / x, 1. / still_x) +} + +#[test] +fn f32_own() { + let x: f32 = -0.0; + let still_x: f32 = [x].into_iter().sum(); + assert_eq!(1. / x, 1. / still_x) +} + +#[test] +fn f64_ref() { + let x: f64 = -0.0; + let still_x: f64 = [x].iter().sum(); + assert_eq!(1. / x, 1. / still_x) +} + +#[test] +fn f64_own() { + let x: f64 = -0.0; + let still_x: f64 = [x].into_iter().sum(); + assert_eq!(1. / x, 1. / still_x) +} diff --git a/library/core/tests/num/int_macros.rs b/library/core/tests/num/int_macros.rs index 165d9a29617..7cd3b54e3f3 100644 --- a/library/core/tests/num/int_macros.rs +++ b/library/core/tests/num/int_macros.rs @@ -1,427 +1,424 @@ macro_rules! int_module { ($T:ident) => { - #[cfg(test)] - mod tests { - use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr}; - use core::$T::*; + use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr}; + use core::$T::*; - use crate::num; + use crate::num; - #[test] - fn test_overflows() { - assert!(MAX > 0); - assert!(MIN <= 0); - assert_eq!(MIN + MAX + 1, 0); + #[test] + fn test_overflows() { + assert!(MAX > 0); + assert!(MIN <= 0); + assert_eq!(MIN + MAX + 1, 0); + } + + #[test] + fn test_num() { + num::test_num(10 as $T, 2 as $T); + } + + #[test] + fn test_rem_euclid() { + assert_eq!((-1 as $T).rem_euclid(MIN), MAX); + } + + #[test] + pub fn test_abs() { + assert_eq!((1 as $T).abs(), 1 as $T); + assert_eq!((0 as $T).abs(), 0 as $T); + assert_eq!((-1 as $T).abs(), 1 as $T); + } + + #[test] + fn test_signum() { + assert_eq!((1 as $T).signum(), 1 as $T); + assert_eq!((0 as $T).signum(), 0 as $T); + assert_eq!((-0 as $T).signum(), 0 as $T); + assert_eq!((-1 as $T).signum(), -1 as $T); + } + + #[test] + fn test_is_positive() { + assert!((1 as $T).is_positive()); + assert!(!(0 as $T).is_positive()); + assert!(!(-0 as $T).is_positive()); + assert!(!(-1 as $T).is_positive()); + } + + #[test] + fn test_is_negative() { + assert!(!(1 as $T).is_negative()); + assert!(!(0 as $T).is_negative()); + assert!(!(-0 as $T).is_negative()); + assert!((-1 as $T).is_negative()); + } + + #[test] + fn test_bitwise_operators() { + assert_eq!(0b1110 as $T, (0b1100 as $T).bitor(0b1010 as $T)); + assert_eq!(0b1000 as $T, (0b1100 as $T).bitand(0b1010 as $T)); + assert_eq!(0b0110 as $T, (0b1100 as $T).bitxor(0b1010 as $T)); + assert_eq!(0b1110 as $T, (0b0111 as $T).shl(1)); + assert_eq!(0b0111 as $T, (0b1110 as $T).shr(1)); + assert_eq!(-(0b11 as $T) - (1 as $T), (0b11 as $T).not()); + } + + const A: $T = 0b0101100; + const B: $T = 0b0100001; + const C: $T = 0b1111001; + + const _0: $T = 0; + const _1: $T = !0; + + #[test] + fn test_count_ones() { + assert_eq!(A.count_ones(), 3); + assert_eq!(B.count_ones(), 2); + assert_eq!(C.count_ones(), 5); + } + + #[test] + fn test_count_zeros() { + assert_eq!(A.count_zeros(), $T::BITS - 3); + assert_eq!(B.count_zeros(), $T::BITS - 2); + assert_eq!(C.count_zeros(), $T::BITS - 5); + } + + #[test] + fn test_leading_trailing_ones() { + let a: $T = 0b0101_1111; + assert_eq!(a.trailing_ones(), 5); + assert_eq!((!a).leading_ones(), $T::BITS - 7); + + assert_eq!(a.reverse_bits().leading_ones(), 5); + + assert_eq!(_1.leading_ones(), $T::BITS); + assert_eq!(_1.trailing_ones(), $T::BITS); + + assert_eq!((_1 << 1).trailing_ones(), 0); + assert_eq!(MAX.leading_ones(), 0); + + assert_eq!((_1 << 1).leading_ones(), $T::BITS - 1); + assert_eq!(MAX.trailing_ones(), $T::BITS - 1); + + assert_eq!(_0.leading_ones(), 0); + assert_eq!(_0.trailing_ones(), 0); + + let x: $T = 0b0010_1100; + assert_eq!(x.leading_ones(), 0); + assert_eq!(x.trailing_ones(), 0); + } + + #[test] + fn test_rotate() { + assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A); + assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B); + assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C); + + // Rotating these should make no difference + // + // We test using 124 bits because to ensure that overlong bit shifts do + // not cause undefined behaviour. See #10183. + assert_eq!(_0.rotate_left(124), _0); + assert_eq!(_1.rotate_left(124), _1); + assert_eq!(_0.rotate_right(124), _0); + assert_eq!(_1.rotate_right(124), _1); + + // Rotating by 0 should have no effect + assert_eq!(A.rotate_left(0), A); + assert_eq!(B.rotate_left(0), B); + assert_eq!(C.rotate_left(0), C); + // Rotating by a multiple of word size should also have no effect + assert_eq!(A.rotate_left(128), A); + assert_eq!(B.rotate_left(128), B); + assert_eq!(C.rotate_left(128), C); + } + + #[test] + fn test_swap_bytes() { + assert_eq!(A.swap_bytes().swap_bytes(), A); + assert_eq!(B.swap_bytes().swap_bytes(), B); + assert_eq!(C.swap_bytes().swap_bytes(), C); + + // Swapping these should make no difference + assert_eq!(_0.swap_bytes(), _0); + assert_eq!(_1.swap_bytes(), _1); + } + + #[test] + fn test_le() { + assert_eq!($T::from_le(A.to_le()), A); + assert_eq!($T::from_le(B.to_le()), B); + assert_eq!($T::from_le(C.to_le()), C); + assert_eq!($T::from_le(_0), _0); + assert_eq!($T::from_le(_1), _1); + assert_eq!(_0.to_le(), _0); + assert_eq!(_1.to_le(), _1); + } + + #[test] + fn test_be() { + assert_eq!($T::from_be(A.to_be()), A); + assert_eq!($T::from_be(B.to_be()), B); + assert_eq!($T::from_be(C.to_be()), C); + assert_eq!($T::from_be(_0), _0); + assert_eq!($T::from_be(_1), _1); + assert_eq!(_0.to_be(), _0); + assert_eq!(_1.to_be(), _1); + } + + #[test] + fn test_signed_checked_div() { + assert_eq!((10 as $T).checked_div(2), Some(5)); + assert_eq!((5 as $T).checked_div(0), None); + assert_eq!(isize::MIN.checked_div(-1), None); + } + + #[test] + fn test_saturating_abs() { + assert_eq!((0 as $T).saturating_abs(), 0); + assert_eq!((123 as $T).saturating_abs(), 123); + assert_eq!((-123 as $T).saturating_abs(), 123); + assert_eq!((MAX - 2).saturating_abs(), MAX - 2); + assert_eq!((MAX - 1).saturating_abs(), MAX - 1); + assert_eq!(MAX.saturating_abs(), MAX); + assert_eq!((MIN + 2).saturating_abs(), MAX - 1); + assert_eq!((MIN + 1).saturating_abs(), MAX); + assert_eq!(MIN.saturating_abs(), MAX); + } + + #[test] + fn test_saturating_neg() { + assert_eq!((0 as $T).saturating_neg(), 0); + assert_eq!((123 as $T).saturating_neg(), -123); + assert_eq!((-123 as $T).saturating_neg(), 123); + assert_eq!((MAX - 2).saturating_neg(), MIN + 3); + assert_eq!((MAX - 1).saturating_neg(), MIN + 2); + assert_eq!(MAX.saturating_neg(), MIN + 1); + assert_eq!((MIN + 2).saturating_neg(), MAX - 1); + assert_eq!((MIN + 1).saturating_neg(), MAX); + assert_eq!(MIN.saturating_neg(), MAX); + } + + #[test] + fn test_from_str() { + fn from_str(t: &str) -> Option { + std::str::FromStr::from_str(t).ok() + } + assert_eq!(from_str::<$T>("0"), Some(0 as $T)); + assert_eq!(from_str::<$T>("3"), Some(3 as $T)); + assert_eq!(from_str::<$T>("10"), Some(10 as $T)); + assert_eq!(from_str::("123456789"), Some(123456789 as i32)); + assert_eq!(from_str::<$T>("00100"), Some(100 as $T)); + + assert_eq!(from_str::<$T>("-1"), Some(-1 as $T)); + assert_eq!(from_str::<$T>("-3"), Some(-3 as $T)); + assert_eq!(from_str::<$T>("-10"), Some(-10 as $T)); + assert_eq!(from_str::("-123456789"), Some(-123456789 as i32)); + assert_eq!(from_str::<$T>("-00100"), Some(-100 as $T)); + + assert_eq!(from_str::<$T>(""), None); + assert_eq!(from_str::<$T>(" "), None); + assert_eq!(from_str::<$T>("x"), None); + } + + #[test] + fn test_from_str_radix() { + assert_eq!($T::from_str_radix("123", 10), Ok(123 as $T)); + assert_eq!($T::from_str_radix("1001", 2), Ok(9 as $T)); + assert_eq!($T::from_str_radix("123", 8), Ok(83 as $T)); + assert_eq!(i32::from_str_radix("123", 16), Ok(291 as i32)); + assert_eq!(i32::from_str_radix("ffff", 16), Ok(65535 as i32)); + assert_eq!(i32::from_str_radix("FFFF", 16), Ok(65535 as i32)); + assert_eq!($T::from_str_radix("z", 36), Ok(35 as $T)); + assert_eq!($T::from_str_radix("Z", 36), Ok(35 as $T)); + + assert_eq!($T::from_str_radix("-123", 10), Ok(-123 as $T)); + assert_eq!($T::from_str_radix("-1001", 2), Ok(-9 as $T)); + assert_eq!($T::from_str_radix("-123", 8), Ok(-83 as $T)); + assert_eq!(i32::from_str_radix("-123", 16), Ok(-291 as i32)); + assert_eq!(i32::from_str_radix("-ffff", 16), Ok(-65535 as i32)); + assert_eq!(i32::from_str_radix("-FFFF", 16), Ok(-65535 as i32)); + assert_eq!($T::from_str_radix("-z", 36), Ok(-35 as $T)); + assert_eq!($T::from_str_radix("-Z", 36), Ok(-35 as $T)); + + assert_eq!($T::from_str_radix("Z", 35).ok(), None::<$T>); + assert_eq!($T::from_str_radix("-9", 2).ok(), None::<$T>); + } + + #[test] + fn test_pow() { + let mut r = 2 as $T; + assert_eq!(r.pow(2), 4 as $T); + assert_eq!(r.pow(0), 1 as $T); + assert_eq!(r.wrapping_pow(2), 4 as $T); + assert_eq!(r.wrapping_pow(0), 1 as $T); + assert_eq!(r.checked_pow(2), Some(4 as $T)); + assert_eq!(r.checked_pow(0), Some(1 as $T)); + assert_eq!(r.overflowing_pow(2), (4 as $T, false)); + assert_eq!(r.overflowing_pow(0), (1 as $T, false)); + assert_eq!(r.saturating_pow(2), 4 as $T); + assert_eq!(r.saturating_pow(0), 1 as $T); + + r = MAX; + // use `^` to represent .pow() with no overflow. + // if itest::MAX == 2^j-1, then itest is a `j` bit int, + // so that `itest::MAX*itest::MAX == 2^(2*j)-2^(j+1)+1`, + // thussaturating_pow the overflowing result is exactly 1. + assert_eq!(r.wrapping_pow(2), 1 as $T); + assert_eq!(r.checked_pow(2), None); + assert_eq!(r.overflowing_pow(2), (1 as $T, true)); + assert_eq!(r.saturating_pow(2), MAX); + //test for negative exponent. + r = -2 as $T; + assert_eq!(r.pow(2), 4 as $T); + assert_eq!(r.pow(3), -8 as $T); + assert_eq!(r.pow(0), 1 as $T); + assert_eq!(r.wrapping_pow(2), 4 as $T); + assert_eq!(r.wrapping_pow(3), -8 as $T); + assert_eq!(r.wrapping_pow(0), 1 as $T); + assert_eq!(r.checked_pow(2), Some(4 as $T)); + assert_eq!(r.checked_pow(3), Some(-8 as $T)); + assert_eq!(r.checked_pow(0), Some(1 as $T)); + assert_eq!(r.overflowing_pow(2), (4 as $T, false)); + assert_eq!(r.overflowing_pow(3), (-8 as $T, false)); + assert_eq!(r.overflowing_pow(0), (1 as $T, false)); + assert_eq!(r.saturating_pow(2), 4 as $T); + assert_eq!(r.saturating_pow(3), -8 as $T); + assert_eq!(r.saturating_pow(0), 1 as $T); + } + + #[test] + fn test_isqrt() { + assert_eq!($T::MIN.checked_isqrt(), None); + assert_eq!((-1 as $T).checked_isqrt(), None); + assert_eq!((0 as $T).isqrt(), 0 as $T); + assert_eq!((1 as $T).isqrt(), 1 as $T); + assert_eq!((2 as $T).isqrt(), 1 as $T); + assert_eq!((99 as $T).isqrt(), 9 as $T); + assert_eq!((100 as $T).isqrt(), 10 as $T); + } + + #[cfg(not(miri))] // Miri is too slow + #[test] + fn test_lots_of_isqrt() { + let n_max: $T = (1024 * 1024).min($T::MAX as u128) as $T; + for n in 0..=n_max { + let isqrt: $T = n.isqrt(); + + assert!(isqrt.pow(2) <= n); + let (square, overflow) = (isqrt + 1).overflowing_pow(2); + assert!(overflow || square > n); } - #[test] - fn test_num() { - num::test_num(10 as $T, 2 as $T); + for n in ($T::MAX - 127)..=$T::MAX { + let isqrt: $T = n.isqrt(); + + assert!(isqrt.pow(2) <= n); + let (square, overflow) = (isqrt + 1).overflowing_pow(2); + assert!(overflow || square > n); } + } - #[test] - fn test_rem_euclid() { - assert_eq!((-1 as $T).rem_euclid(MIN), MAX); - } + #[test] + fn test_div_floor() { + let a: $T = 8; + let b = 3; + assert_eq!(a.div_floor(b), 2); + assert_eq!(a.div_floor(-b), -3); + assert_eq!((-a).div_floor(b), -3); + assert_eq!((-a).div_floor(-b), 2); + } - #[test] - pub fn test_abs() { - assert_eq!((1 as $T).abs(), 1 as $T); - assert_eq!((0 as $T).abs(), 0 as $T); - assert_eq!((-1 as $T).abs(), 1 as $T); - } + #[test] + fn test_div_ceil() { + let a: $T = 8; + let b = 3; + assert_eq!(a.div_ceil(b), 3); + assert_eq!(a.div_ceil(-b), -2); + assert_eq!((-a).div_ceil(b), -2); + assert_eq!((-a).div_ceil(-b), 3); + } - #[test] - fn test_signum() { - assert_eq!((1 as $T).signum(), 1 as $T); - assert_eq!((0 as $T).signum(), 0 as $T); - assert_eq!((-0 as $T).signum(), 0 as $T); - assert_eq!((-1 as $T).signum(), -1 as $T); - } + #[test] + fn test_next_multiple_of() { + assert_eq!((16 as $T).next_multiple_of(8), 16); + assert_eq!((23 as $T).next_multiple_of(8), 24); + assert_eq!((16 as $T).next_multiple_of(-8), 16); + assert_eq!((23 as $T).next_multiple_of(-8), 16); + assert_eq!((-16 as $T).next_multiple_of(8), -16); + assert_eq!((-23 as $T).next_multiple_of(8), -16); + assert_eq!((-16 as $T).next_multiple_of(-8), -16); + assert_eq!((-23 as $T).next_multiple_of(-8), -24); + assert_eq!(MIN.next_multiple_of(-1), MIN); + } - #[test] - fn test_is_positive() { - assert!((1 as $T).is_positive()); - assert!(!(0 as $T).is_positive()); - assert!(!(-0 as $T).is_positive()); - assert!(!(-1 as $T).is_positive()); - } + #[test] + fn test_checked_next_multiple_of() { + assert_eq!((16 as $T).checked_next_multiple_of(8), Some(16)); + assert_eq!((23 as $T).checked_next_multiple_of(8), Some(24)); + assert_eq!((16 as $T).checked_next_multiple_of(-8), Some(16)); + assert_eq!((23 as $T).checked_next_multiple_of(-8), Some(16)); + assert_eq!((-16 as $T).checked_next_multiple_of(8), Some(-16)); + assert_eq!((-23 as $T).checked_next_multiple_of(8), Some(-16)); + assert_eq!((-16 as $T).checked_next_multiple_of(-8), Some(-16)); + assert_eq!((-23 as $T).checked_next_multiple_of(-8), Some(-24)); + assert_eq!((1 as $T).checked_next_multiple_of(0), None); + assert_eq!(MAX.checked_next_multiple_of(2), None); + assert_eq!(MIN.checked_next_multiple_of(-3), None); + assert_eq!(MIN.checked_next_multiple_of(-1), Some(MIN)); + } - #[test] - fn test_is_negative() { - assert!(!(1 as $T).is_negative()); - assert!(!(0 as $T).is_negative()); - assert!(!(-0 as $T).is_negative()); - assert!((-1 as $T).is_negative()); - } + #[test] + fn test_carrying_add() { + assert_eq!($T::MAX.carrying_add(1, false), ($T::MIN, true)); + assert_eq!($T::MAX.carrying_add(0, true), ($T::MIN, true)); + assert_eq!($T::MAX.carrying_add(1, true), ($T::MIN + 1, true)); + assert_eq!($T::MAX.carrying_add(-1, false), ($T::MAX - 1, false)); + assert_eq!($T::MAX.carrying_add(-1, true), ($T::MAX, false)); // no intermediate overflow + assert_eq!($T::MIN.carrying_add(-1, false), ($T::MAX, true)); + assert_eq!($T::MIN.carrying_add(-1, true), ($T::MIN, false)); // no intermediate overflow + assert_eq!((0 as $T).carrying_add($T::MAX, true), ($T::MIN, true)); + assert_eq!((0 as $T).carrying_add($T::MIN, true), ($T::MIN + 1, false)); + } - #[test] - fn test_bitwise_operators() { - assert_eq!(0b1110 as $T, (0b1100 as $T).bitor(0b1010 as $T)); - assert_eq!(0b1000 as $T, (0b1100 as $T).bitand(0b1010 as $T)); - assert_eq!(0b0110 as $T, (0b1100 as $T).bitxor(0b1010 as $T)); - assert_eq!(0b1110 as $T, (0b0111 as $T).shl(1)); - assert_eq!(0b0111 as $T, (0b1110 as $T).shr(1)); - assert_eq!(-(0b11 as $T) - (1 as $T), (0b11 as $T).not()); - } + #[test] + fn test_borrowing_sub() { + assert_eq!($T::MIN.borrowing_sub(1, false), ($T::MAX, true)); + assert_eq!($T::MIN.borrowing_sub(0, true), ($T::MAX, true)); + assert_eq!($T::MIN.borrowing_sub(1, true), ($T::MAX - 1, true)); + assert_eq!($T::MIN.borrowing_sub(-1, false), ($T::MIN + 1, false)); + assert_eq!($T::MIN.borrowing_sub(-1, true), ($T::MIN, false)); // no intermediate overflow + assert_eq!($T::MAX.borrowing_sub(-1, false), ($T::MIN, true)); + assert_eq!($T::MAX.borrowing_sub(-1, true), ($T::MAX, false)); // no intermediate overflow + assert_eq!((0 as $T).borrowing_sub($T::MIN, false), ($T::MIN, true)); + assert_eq!((0 as $T).borrowing_sub($T::MIN, true), ($T::MAX, false)); + } - const A: $T = 0b0101100; - const B: $T = 0b0100001; - const C: $T = 0b1111001; + #[test] + fn test_midpoint() { + assert_eq!(<$T>::midpoint(1, 3), 2); + assert_eq!(<$T>::midpoint(3, 1), 2); - const _0: $T = 0; - const _1: $T = !0; + assert_eq!(<$T>::midpoint(0, 0), 0); + assert_eq!(<$T>::midpoint(0, 2), 1); + assert_eq!(<$T>::midpoint(2, 0), 1); + assert_eq!(<$T>::midpoint(2, 2), 2); - #[test] - fn test_count_ones() { - assert_eq!(A.count_ones(), 3); - assert_eq!(B.count_ones(), 2); - assert_eq!(C.count_ones(), 5); - } + assert_eq!(<$T>::midpoint(1, 4), 2); + assert_eq!(<$T>::midpoint(4, 1), 2); + assert_eq!(<$T>::midpoint(3, 4), 3); + assert_eq!(<$T>::midpoint(4, 3), 3); - #[test] - fn test_count_zeros() { - assert_eq!(A.count_zeros(), $T::BITS - 3); - assert_eq!(B.count_zeros(), $T::BITS - 2); - assert_eq!(C.count_zeros(), $T::BITS - 5); - } + assert_eq!(<$T>::midpoint(<$T>::MIN, <$T>::MAX), -1); + assert_eq!(<$T>::midpoint(<$T>::MAX, <$T>::MIN), -1); + assert_eq!(<$T>::midpoint(<$T>::MIN, <$T>::MIN), <$T>::MIN); + assert_eq!(<$T>::midpoint(<$T>::MAX, <$T>::MAX), <$T>::MAX); - #[test] - fn test_leading_trailing_ones() { - let a: $T = 0b0101_1111; - assert_eq!(a.trailing_ones(), 5); - assert_eq!((!a).leading_ones(), $T::BITS - 7); - - assert_eq!(a.reverse_bits().leading_ones(), 5); - - assert_eq!(_1.leading_ones(), $T::BITS); - assert_eq!(_1.trailing_ones(), $T::BITS); - - assert_eq!((_1 << 1).trailing_ones(), 0); - assert_eq!(MAX.leading_ones(), 0); - - assert_eq!((_1 << 1).leading_ones(), $T::BITS - 1); - assert_eq!(MAX.trailing_ones(), $T::BITS - 1); - - assert_eq!(_0.leading_ones(), 0); - assert_eq!(_0.trailing_ones(), 0); - - let x: $T = 0b0010_1100; - assert_eq!(x.leading_ones(), 0); - assert_eq!(x.trailing_ones(), 0); - } - - #[test] - fn test_rotate() { - assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A); - assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B); - assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C); - - // Rotating these should make no difference - // - // We test using 124 bits because to ensure that overlong bit shifts do - // not cause undefined behaviour. See #10183. - assert_eq!(_0.rotate_left(124), _0); - assert_eq!(_1.rotate_left(124), _1); - assert_eq!(_0.rotate_right(124), _0); - assert_eq!(_1.rotate_right(124), _1); - - // Rotating by 0 should have no effect - assert_eq!(A.rotate_left(0), A); - assert_eq!(B.rotate_left(0), B); - assert_eq!(C.rotate_left(0), C); - // Rotating by a multiple of word size should also have no effect - assert_eq!(A.rotate_left(128), A); - assert_eq!(B.rotate_left(128), B); - assert_eq!(C.rotate_left(128), C); - } - - #[test] - fn test_swap_bytes() { - assert_eq!(A.swap_bytes().swap_bytes(), A); - assert_eq!(B.swap_bytes().swap_bytes(), B); - assert_eq!(C.swap_bytes().swap_bytes(), C); - - // Swapping these should make no difference - assert_eq!(_0.swap_bytes(), _0); - assert_eq!(_1.swap_bytes(), _1); - } - - #[test] - fn test_le() { - assert_eq!($T::from_le(A.to_le()), A); - assert_eq!($T::from_le(B.to_le()), B); - assert_eq!($T::from_le(C.to_le()), C); - assert_eq!($T::from_le(_0), _0); - assert_eq!($T::from_le(_1), _1); - assert_eq!(_0.to_le(), _0); - assert_eq!(_1.to_le(), _1); - } - - #[test] - fn test_be() { - assert_eq!($T::from_be(A.to_be()), A); - assert_eq!($T::from_be(B.to_be()), B); - assert_eq!($T::from_be(C.to_be()), C); - assert_eq!($T::from_be(_0), _0); - assert_eq!($T::from_be(_1), _1); - assert_eq!(_0.to_be(), _0); - assert_eq!(_1.to_be(), _1); - } - - #[test] - fn test_signed_checked_div() { - assert_eq!((10 as $T).checked_div(2), Some(5)); - assert_eq!((5 as $T).checked_div(0), None); - assert_eq!(isize::MIN.checked_div(-1), None); - } - - #[test] - fn test_saturating_abs() { - assert_eq!((0 as $T).saturating_abs(), 0); - assert_eq!((123 as $T).saturating_abs(), 123); - assert_eq!((-123 as $T).saturating_abs(), 123); - assert_eq!((MAX - 2).saturating_abs(), MAX - 2); - assert_eq!((MAX - 1).saturating_abs(), MAX - 1); - assert_eq!(MAX.saturating_abs(), MAX); - assert_eq!((MIN + 2).saturating_abs(), MAX - 1); - assert_eq!((MIN + 1).saturating_abs(), MAX); - assert_eq!(MIN.saturating_abs(), MAX); - } - - #[test] - fn test_saturating_neg() { - assert_eq!((0 as $T).saturating_neg(), 0); - assert_eq!((123 as $T).saturating_neg(), -123); - assert_eq!((-123 as $T).saturating_neg(), 123); - assert_eq!((MAX - 2).saturating_neg(), MIN + 3); - assert_eq!((MAX - 1).saturating_neg(), MIN + 2); - assert_eq!(MAX.saturating_neg(), MIN + 1); - assert_eq!((MIN + 2).saturating_neg(), MAX - 1); - assert_eq!((MIN + 1).saturating_neg(), MAX); - assert_eq!(MIN.saturating_neg(), MAX); - } - - #[test] - fn test_from_str() { - fn from_str(t: &str) -> Option { - std::str::FromStr::from_str(t).ok() - } - assert_eq!(from_str::<$T>("0"), Some(0 as $T)); - assert_eq!(from_str::<$T>("3"), Some(3 as $T)); - assert_eq!(from_str::<$T>("10"), Some(10 as $T)); - assert_eq!(from_str::("123456789"), Some(123456789 as i32)); - assert_eq!(from_str::<$T>("00100"), Some(100 as $T)); - - assert_eq!(from_str::<$T>("-1"), Some(-1 as $T)); - assert_eq!(from_str::<$T>("-3"), Some(-3 as $T)); - assert_eq!(from_str::<$T>("-10"), Some(-10 as $T)); - assert_eq!(from_str::("-123456789"), Some(-123456789 as i32)); - assert_eq!(from_str::<$T>("-00100"), Some(-100 as $T)); - - assert_eq!(from_str::<$T>(""), None); - assert_eq!(from_str::<$T>(" "), None); - assert_eq!(from_str::<$T>("x"), None); - } - - #[test] - fn test_from_str_radix() { - assert_eq!($T::from_str_radix("123", 10), Ok(123 as $T)); - assert_eq!($T::from_str_radix("1001", 2), Ok(9 as $T)); - assert_eq!($T::from_str_radix("123", 8), Ok(83 as $T)); - assert_eq!(i32::from_str_radix("123", 16), Ok(291 as i32)); - assert_eq!(i32::from_str_radix("ffff", 16), Ok(65535 as i32)); - assert_eq!(i32::from_str_radix("FFFF", 16), Ok(65535 as i32)); - assert_eq!($T::from_str_radix("z", 36), Ok(35 as $T)); - assert_eq!($T::from_str_radix("Z", 36), Ok(35 as $T)); - - assert_eq!($T::from_str_radix("-123", 10), Ok(-123 as $T)); - assert_eq!($T::from_str_radix("-1001", 2), Ok(-9 as $T)); - assert_eq!($T::from_str_radix("-123", 8), Ok(-83 as $T)); - assert_eq!(i32::from_str_radix("-123", 16), Ok(-291 as i32)); - assert_eq!(i32::from_str_radix("-ffff", 16), Ok(-65535 as i32)); - assert_eq!(i32::from_str_radix("-FFFF", 16), Ok(-65535 as i32)); - assert_eq!($T::from_str_radix("-z", 36), Ok(-35 as $T)); - assert_eq!($T::from_str_radix("-Z", 36), Ok(-35 as $T)); - - assert_eq!($T::from_str_radix("Z", 35).ok(), None::<$T>); - assert_eq!($T::from_str_radix("-9", 2).ok(), None::<$T>); - } - - #[test] - fn test_pow() { - let mut r = 2 as $T; - assert_eq!(r.pow(2), 4 as $T); - assert_eq!(r.pow(0), 1 as $T); - assert_eq!(r.wrapping_pow(2), 4 as $T); - assert_eq!(r.wrapping_pow(0), 1 as $T); - assert_eq!(r.checked_pow(2), Some(4 as $T)); - assert_eq!(r.checked_pow(0), Some(1 as $T)); - assert_eq!(r.overflowing_pow(2), (4 as $T, false)); - assert_eq!(r.overflowing_pow(0), (1 as $T, false)); - assert_eq!(r.saturating_pow(2), 4 as $T); - assert_eq!(r.saturating_pow(0), 1 as $T); - - r = MAX; - // use `^` to represent .pow() with no overflow. - // if itest::MAX == 2^j-1, then itest is a `j` bit int, - // so that `itest::MAX*itest::MAX == 2^(2*j)-2^(j+1)+1`, - // thussaturating_pow the overflowing result is exactly 1. - assert_eq!(r.wrapping_pow(2), 1 as $T); - assert_eq!(r.checked_pow(2), None); - assert_eq!(r.overflowing_pow(2), (1 as $T, true)); - assert_eq!(r.saturating_pow(2), MAX); - //test for negative exponent. - r = -2 as $T; - assert_eq!(r.pow(2), 4 as $T); - assert_eq!(r.pow(3), -8 as $T); - assert_eq!(r.pow(0), 1 as $T); - assert_eq!(r.wrapping_pow(2), 4 as $T); - assert_eq!(r.wrapping_pow(3), -8 as $T); - assert_eq!(r.wrapping_pow(0), 1 as $T); - assert_eq!(r.checked_pow(2), Some(4 as $T)); - assert_eq!(r.checked_pow(3), Some(-8 as $T)); - assert_eq!(r.checked_pow(0), Some(1 as $T)); - assert_eq!(r.overflowing_pow(2), (4 as $T, false)); - assert_eq!(r.overflowing_pow(3), (-8 as $T, false)); - assert_eq!(r.overflowing_pow(0), (1 as $T, false)); - assert_eq!(r.saturating_pow(2), 4 as $T); - assert_eq!(r.saturating_pow(3), -8 as $T); - assert_eq!(r.saturating_pow(0), 1 as $T); - } - - #[test] - fn test_isqrt() { - assert_eq!($T::MIN.checked_isqrt(), None); - assert_eq!((-1 as $T).checked_isqrt(), None); - assert_eq!((0 as $T).isqrt(), 0 as $T); - assert_eq!((1 as $T).isqrt(), 1 as $T); - assert_eq!((2 as $T).isqrt(), 1 as $T); - assert_eq!((99 as $T).isqrt(), 9 as $T); - assert_eq!((100 as $T).isqrt(), 10 as $T); - } - - #[cfg(not(miri))] // Miri is too slow - #[test] - fn test_lots_of_isqrt() { - let n_max: $T = (1024 * 1024).min($T::MAX as u128) as $T; - for n in 0..=n_max { - let isqrt: $T = n.isqrt(); - - assert!(isqrt.pow(2) <= n); - let (square, overflow) = (isqrt + 1).overflowing_pow(2); - assert!(overflow || square > n); - } - - for n in ($T::MAX - 127)..=$T::MAX { - let isqrt: $T = n.isqrt(); - - assert!(isqrt.pow(2) <= n); - let (square, overflow) = (isqrt + 1).overflowing_pow(2); - assert!(overflow || square > n); - } - } - - #[test] - fn test_div_floor() { - let a: $T = 8; - let b = 3; - assert_eq!(a.div_floor(b), 2); - assert_eq!(a.div_floor(-b), -3); - assert_eq!((-a).div_floor(b), -3); - assert_eq!((-a).div_floor(-b), 2); - } - - #[test] - fn test_div_ceil() { - let a: $T = 8; - let b = 3; - assert_eq!(a.div_ceil(b), 3); - assert_eq!(a.div_ceil(-b), -2); - assert_eq!((-a).div_ceil(b), -2); - assert_eq!((-a).div_ceil(-b), 3); - } - - #[test] - fn test_next_multiple_of() { - assert_eq!((16 as $T).next_multiple_of(8), 16); - assert_eq!((23 as $T).next_multiple_of(8), 24); - assert_eq!((16 as $T).next_multiple_of(-8), 16); - assert_eq!((23 as $T).next_multiple_of(-8), 16); - assert_eq!((-16 as $T).next_multiple_of(8), -16); - assert_eq!((-23 as $T).next_multiple_of(8), -16); - assert_eq!((-16 as $T).next_multiple_of(-8), -16); - assert_eq!((-23 as $T).next_multiple_of(-8), -24); - assert_eq!(MIN.next_multiple_of(-1), MIN); - } - - #[test] - fn test_checked_next_multiple_of() { - assert_eq!((16 as $T).checked_next_multiple_of(8), Some(16)); - assert_eq!((23 as $T).checked_next_multiple_of(8), Some(24)); - assert_eq!((16 as $T).checked_next_multiple_of(-8), Some(16)); - assert_eq!((23 as $T).checked_next_multiple_of(-8), Some(16)); - assert_eq!((-16 as $T).checked_next_multiple_of(8), Some(-16)); - assert_eq!((-23 as $T).checked_next_multiple_of(8), Some(-16)); - assert_eq!((-16 as $T).checked_next_multiple_of(-8), Some(-16)); - assert_eq!((-23 as $T).checked_next_multiple_of(-8), Some(-24)); - assert_eq!((1 as $T).checked_next_multiple_of(0), None); - assert_eq!(MAX.checked_next_multiple_of(2), None); - assert_eq!(MIN.checked_next_multiple_of(-3), None); - assert_eq!(MIN.checked_next_multiple_of(-1), Some(MIN)); - } - - #[test] - fn test_carrying_add() { - assert_eq!($T::MAX.carrying_add(1, false), ($T::MIN, true)); - assert_eq!($T::MAX.carrying_add(0, true), ($T::MIN, true)); - assert_eq!($T::MAX.carrying_add(1, true), ($T::MIN + 1, true)); - assert_eq!($T::MAX.carrying_add(-1, false), ($T::MAX - 1, false)); - assert_eq!($T::MAX.carrying_add(-1, true), ($T::MAX, false)); // no intermediate overflow - assert_eq!($T::MIN.carrying_add(-1, false), ($T::MAX, true)); - assert_eq!($T::MIN.carrying_add(-1, true), ($T::MIN, false)); // no intermediate overflow - assert_eq!((0 as $T).carrying_add($T::MAX, true), ($T::MIN, true)); - assert_eq!((0 as $T).carrying_add($T::MIN, true), ($T::MIN + 1, false)); - } - - #[test] - fn test_borrowing_sub() { - assert_eq!($T::MIN.borrowing_sub(1, false), ($T::MAX, true)); - assert_eq!($T::MIN.borrowing_sub(0, true), ($T::MAX, true)); - assert_eq!($T::MIN.borrowing_sub(1, true), ($T::MAX - 1, true)); - assert_eq!($T::MIN.borrowing_sub(-1, false), ($T::MIN + 1, false)); - assert_eq!($T::MIN.borrowing_sub(-1, true), ($T::MIN, false)); // no intermediate overflow - assert_eq!($T::MAX.borrowing_sub(-1, false), ($T::MIN, true)); - assert_eq!($T::MAX.borrowing_sub(-1, true), ($T::MAX, false)); // no intermediate overflow - assert_eq!((0 as $T).borrowing_sub($T::MIN, false), ($T::MIN, true)); - assert_eq!((0 as $T).borrowing_sub($T::MIN, true), ($T::MAX, false)); - } - - #[test] - fn test_midpoint() { - assert_eq!(<$T>::midpoint(1, 3), 2); - assert_eq!(<$T>::midpoint(3, 1), 2); - - assert_eq!(<$T>::midpoint(0, 0), 0); - assert_eq!(<$T>::midpoint(0, 2), 1); - assert_eq!(<$T>::midpoint(2, 0), 1); - assert_eq!(<$T>::midpoint(2, 2), 2); - - assert_eq!(<$T>::midpoint(1, 4), 2); - assert_eq!(<$T>::midpoint(4, 1), 2); - assert_eq!(<$T>::midpoint(3, 4), 3); - assert_eq!(<$T>::midpoint(4, 3), 3); - - assert_eq!(<$T>::midpoint(<$T>::MIN, <$T>::MAX), -1); - assert_eq!(<$T>::midpoint(<$T>::MAX, <$T>::MIN), -1); - assert_eq!(<$T>::midpoint(<$T>::MIN, <$T>::MIN), <$T>::MIN); - assert_eq!(<$T>::midpoint(<$T>::MAX, <$T>::MAX), <$T>::MAX); - - assert_eq!(<$T>::midpoint(<$T>::MIN, 6), <$T>::MIN / 2 + 3); - assert_eq!(<$T>::midpoint(6, <$T>::MIN), <$T>::MIN / 2 + 3); - assert_eq!(<$T>::midpoint(<$T>::MAX, 6), <$T>::MAX / 2 + 3); - assert_eq!(<$T>::midpoint(6, <$T>::MAX), <$T>::MAX / 2 + 3); - } + assert_eq!(<$T>::midpoint(<$T>::MIN, 6), <$T>::MIN / 2 + 3); + assert_eq!(<$T>::midpoint(6, <$T>::MIN), <$T>::MIN / 2 + 3); + assert_eq!(<$T>::midpoint(<$T>::MAX, 6), <$T>::MAX / 2 + 3); + assert_eq!(<$T>::midpoint(6, <$T>::MAX), <$T>::MAX / 2 + 3); } }; } diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs index 9d2912c4b22..dad46ad88fe 100644 --- a/library/core/tests/num/mod.rs +++ b/library/core/tests/num/mod.rs @@ -30,6 +30,7 @@ mod int_log; mod ops; mod wrapping; +mod float_iter_sum_identity; mod ieee754; mod nan; @@ -177,7 +178,7 @@ fn test_can_not_overflow() { // Check u128 separately: for base in 2..=36 { - let num = u128::MAX as u128; + let num = ::MAX; let max_len_string = format_radix(num, base as u128); // base 16 fits perfectly for u128 and won't overflow: assert_eq!(can_overflow::(base, &max_len_string), base != 16); diff --git a/library/core/tests/num/uint_macros.rs b/library/core/tests/num/uint_macros.rs index d009ad89d5c..f4fa789461e 100644 --- a/library/core/tests/num/uint_macros.rs +++ b/library/core/tests/num/uint_macros.rs @@ -1,320 +1,317 @@ macro_rules! uint_module { ($T:ident) => { - #[cfg(test)] - mod tests { - use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr}; - use core::$T::*; - use std::str::FromStr; + use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr}; + use core::$T::*; + use std::str::FromStr; - use crate::num; + use crate::num; - #[test] - fn test_overflows() { - assert!(MAX > 0); - assert!(MIN <= 0); - assert!((MIN + MAX).wrapping_add(1) == 0); + #[test] + fn test_overflows() { + assert!(MAX > 0); + assert!(MIN <= 0); + assert!((MIN + MAX).wrapping_add(1) == 0); + } + + #[test] + fn test_num() { + num::test_num(10 as $T, 2 as $T); + } + + #[test] + fn test_bitwise_operators() { + assert!(0b1110 as $T == (0b1100 as $T).bitor(0b1010 as $T)); + assert!(0b1000 as $T == (0b1100 as $T).bitand(0b1010 as $T)); + assert!(0b0110 as $T == (0b1100 as $T).bitxor(0b1010 as $T)); + assert!(0b1110 as $T == (0b0111 as $T).shl(1)); + assert!(0b0111 as $T == (0b1110 as $T).shr(1)); + assert!(MAX - (0b1011 as $T) == (0b1011 as $T).not()); + } + + const A: $T = 0b0101100; + const B: $T = 0b0100001; + const C: $T = 0b1111001; + + const _0: $T = 0; + const _1: $T = !0; + + #[test] + fn test_count_ones() { + assert!(A.count_ones() == 3); + assert!(B.count_ones() == 2); + assert!(C.count_ones() == 5); + } + + #[test] + fn test_count_zeros() { + assert!(A.count_zeros() == $T::BITS - 3); + assert!(B.count_zeros() == $T::BITS - 2); + assert!(C.count_zeros() == $T::BITS - 5); + } + + #[test] + fn test_leading_trailing_ones() { + let a: $T = 0b0101_1111; + assert_eq!(a.trailing_ones(), 5); + assert_eq!((!a).leading_ones(), $T::BITS - 7); + + assert_eq!(a.reverse_bits().leading_ones(), 5); + + assert_eq!(_1.leading_ones(), $T::BITS); + assert_eq!(_1.trailing_ones(), $T::BITS); + + assert_eq!((_1 << 1).trailing_ones(), 0); + assert_eq!((_1 >> 1).leading_ones(), 0); + + assert_eq!((_1 << 1).leading_ones(), $T::BITS - 1); + assert_eq!((_1 >> 1).trailing_ones(), $T::BITS - 1); + + assert_eq!(_0.leading_ones(), 0); + assert_eq!(_0.trailing_ones(), 0); + + let x: $T = 0b0010_1100; + assert_eq!(x.leading_ones(), 0); + assert_eq!(x.trailing_ones(), 0); + } + + #[test] + fn test_rotate() { + assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A); + assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B); + assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C); + + // Rotating these should make no difference + // + // We test using 124 bits because to ensure that overlong bit shifts do + // not cause undefined behaviour. See #10183. + assert_eq!(_0.rotate_left(124), _0); + assert_eq!(_1.rotate_left(124), _1); + assert_eq!(_0.rotate_right(124), _0); + assert_eq!(_1.rotate_right(124), _1); + + // Rotating by 0 should have no effect + assert_eq!(A.rotate_left(0), A); + assert_eq!(B.rotate_left(0), B); + assert_eq!(C.rotate_left(0), C); + // Rotating by a multiple of word size should also have no effect + assert_eq!(A.rotate_left(128), A); + assert_eq!(B.rotate_left(128), B); + assert_eq!(C.rotate_left(128), C); + } + + #[test] + fn test_swap_bytes() { + assert_eq!(A.swap_bytes().swap_bytes(), A); + assert_eq!(B.swap_bytes().swap_bytes(), B); + assert_eq!(C.swap_bytes().swap_bytes(), C); + + // Swapping these should make no difference + assert_eq!(_0.swap_bytes(), _0); + assert_eq!(_1.swap_bytes(), _1); + } + + #[test] + fn test_reverse_bits() { + assert_eq!(A.reverse_bits().reverse_bits(), A); + assert_eq!(B.reverse_bits().reverse_bits(), B); + assert_eq!(C.reverse_bits().reverse_bits(), C); + + // Swapping these should make no difference + assert_eq!(_0.reverse_bits(), _0); + assert_eq!(_1.reverse_bits(), _1); + } + + #[test] + fn test_le() { + assert_eq!($T::from_le(A.to_le()), A); + assert_eq!($T::from_le(B.to_le()), B); + assert_eq!($T::from_le(C.to_le()), C); + assert_eq!($T::from_le(_0), _0); + assert_eq!($T::from_le(_1), _1); + assert_eq!(_0.to_le(), _0); + assert_eq!(_1.to_le(), _1); + } + + #[test] + fn test_be() { + assert_eq!($T::from_be(A.to_be()), A); + assert_eq!($T::from_be(B.to_be()), B); + assert_eq!($T::from_be(C.to_be()), C); + assert_eq!($T::from_be(_0), _0); + assert_eq!($T::from_be(_1), _1); + assert_eq!(_0.to_be(), _0); + assert_eq!(_1.to_be(), _1); + } + + #[test] + fn test_unsigned_checked_div() { + assert!((10 as $T).checked_div(2) == Some(5)); + assert!((5 as $T).checked_div(0) == None); + } + + fn from_str(t: &str) -> Option { + FromStr::from_str(t).ok() + } + + #[test] + pub fn test_from_str() { + assert_eq!(from_str::<$T>("0"), Some(0 as $T)); + assert_eq!(from_str::<$T>("3"), Some(3 as $T)); + assert_eq!(from_str::<$T>("10"), Some(10 as $T)); + assert_eq!(from_str::("123456789"), Some(123456789 as u32)); + assert_eq!(from_str::<$T>("00100"), Some(100 as $T)); + + assert_eq!(from_str::<$T>(""), None); + assert_eq!(from_str::<$T>(" "), None); + assert_eq!(from_str::<$T>("x"), None); + } + + #[test] + pub fn test_parse_bytes() { + assert_eq!($T::from_str_radix("123", 10), Ok(123 as $T)); + assert_eq!($T::from_str_radix("1001", 2), Ok(9 as $T)); + assert_eq!($T::from_str_radix("123", 8), Ok(83 as $T)); + assert_eq!(u16::from_str_radix("123", 16), Ok(291 as u16)); + assert_eq!(u16::from_str_radix("ffff", 16), Ok(65535 as u16)); + assert_eq!($T::from_str_radix("z", 36), Ok(35 as $T)); + + assert_eq!($T::from_str_radix("Z", 10).ok(), None::<$T>); + assert_eq!($T::from_str_radix("_", 2).ok(), None::<$T>); + } + + #[test] + fn test_pow() { + let mut r = 2 as $T; + assert_eq!(r.pow(2), 4 as $T); + assert_eq!(r.pow(0), 1 as $T); + assert_eq!(r.wrapping_pow(2), 4 as $T); + assert_eq!(r.wrapping_pow(0), 1 as $T); + assert_eq!(r.checked_pow(2), Some(4 as $T)); + assert_eq!(r.checked_pow(0), Some(1 as $T)); + assert_eq!(r.overflowing_pow(2), (4 as $T, false)); + assert_eq!(r.overflowing_pow(0), (1 as $T, false)); + assert_eq!(r.saturating_pow(2), 4 as $T); + assert_eq!(r.saturating_pow(0), 1 as $T); + + r = MAX; + // use `^` to represent .pow() with no overflow. + // if itest::MAX == 2^j-1, then itest is a `j` bit int, + // so that `itest::MAX*itest::MAX == 2^(2*j)-2^(j+1)+1`, + // thussaturating_pow the overflowing result is exactly 1. + assert_eq!(r.wrapping_pow(2), 1 as $T); + assert_eq!(r.checked_pow(2), None); + assert_eq!(r.overflowing_pow(2), (1 as $T, true)); + assert_eq!(r.saturating_pow(2), MAX); + } + + #[test] + fn test_isqrt() { + assert_eq!((0 as $T).isqrt(), 0 as $T); + assert_eq!((1 as $T).isqrt(), 1 as $T); + assert_eq!((2 as $T).isqrt(), 1 as $T); + assert_eq!((99 as $T).isqrt(), 9 as $T); + assert_eq!((100 as $T).isqrt(), 10 as $T); + assert_eq!($T::MAX.isqrt(), (1 << ($T::BITS / 2)) - 1); + } + + #[cfg(not(miri))] // Miri is too slow + #[test] + fn test_lots_of_isqrt() { + let n_max: $T = (1024 * 1024).min($T::MAX as u128) as $T; + for n in 0..=n_max { + let isqrt: $T = n.isqrt(); + + assert!(isqrt.pow(2) <= n); + assert!(isqrt + 1 == (1 as $T) << ($T::BITS / 2) || (isqrt + 1).pow(2) > n); } - #[test] - fn test_num() { - num::test_num(10 as $T, 2 as $T); + for n in ($T::MAX - 255)..=$T::MAX { + let isqrt: $T = n.isqrt(); + + assert!(isqrt.pow(2) <= n); + assert!(isqrt + 1 == (1 as $T) << ($T::BITS / 2) || (isqrt + 1).pow(2) > n); } + } - #[test] - fn test_bitwise_operators() { - assert!(0b1110 as $T == (0b1100 as $T).bitor(0b1010 as $T)); - assert!(0b1000 as $T == (0b1100 as $T).bitand(0b1010 as $T)); - assert!(0b0110 as $T == (0b1100 as $T).bitxor(0b1010 as $T)); - assert!(0b1110 as $T == (0b0111 as $T).shl(1)); - assert!(0b0111 as $T == (0b1110 as $T).shr(1)); - assert!(MAX - (0b1011 as $T) == (0b1011 as $T).not()); - } + #[test] + fn test_div_floor() { + assert_eq!((8 as $T).div_floor(3), 2); + } - const A: $T = 0b0101100; - const B: $T = 0b0100001; - const C: $T = 0b1111001; + #[test] + fn test_div_ceil() { + assert_eq!((8 as $T).div_ceil(3), 3); + } - const _0: $T = 0; - const _1: $T = !0; + #[test] + fn test_next_multiple_of() { + assert_eq!((16 as $T).next_multiple_of(8), 16); + assert_eq!((23 as $T).next_multiple_of(8), 24); + assert_eq!(MAX.next_multiple_of(1), MAX); + } - #[test] - fn test_count_ones() { - assert!(A.count_ones() == 3); - assert!(B.count_ones() == 2); - assert!(C.count_ones() == 5); - } + #[test] + fn test_checked_next_multiple_of() { + assert_eq!((16 as $T).checked_next_multiple_of(8), Some(16)); + assert_eq!((23 as $T).checked_next_multiple_of(8), Some(24)); + assert_eq!((1 as $T).checked_next_multiple_of(0), None); + assert_eq!(MAX.checked_next_multiple_of(2), None); + } - #[test] - fn test_count_zeros() { - assert!(A.count_zeros() == $T::BITS - 3); - assert!(B.count_zeros() == $T::BITS - 2); - assert!(C.count_zeros() == $T::BITS - 5); - } + #[test] + fn test_is_next_multiple_of() { + assert!((12 as $T).is_multiple_of(4)); + assert!(!(12 as $T).is_multiple_of(5)); + assert!((0 as $T).is_multiple_of(0)); + assert!(!(12 as $T).is_multiple_of(0)); + } - #[test] - fn test_leading_trailing_ones() { - let a: $T = 0b0101_1111; - assert_eq!(a.trailing_ones(), 5); - assert_eq!((!a).leading_ones(), $T::BITS - 7); + #[test] + fn test_carrying_add() { + assert_eq!($T::MAX.carrying_add(1, false), (0, true)); + assert_eq!($T::MAX.carrying_add(0, true), (0, true)); + assert_eq!($T::MAX.carrying_add(1, true), (1, true)); - assert_eq!(a.reverse_bits().leading_ones(), 5); + assert_eq!($T::MIN.carrying_add($T::MAX, false), ($T::MAX, false)); + assert_eq!($T::MIN.carrying_add(0, true), (1, false)); + assert_eq!($T::MIN.carrying_add($T::MAX, true), (0, true)); + } - assert_eq!(_1.leading_ones(), $T::BITS); - assert_eq!(_1.trailing_ones(), $T::BITS); + #[test] + fn test_borrowing_sub() { + assert_eq!($T::MIN.borrowing_sub(1, false), ($T::MAX, true)); + assert_eq!($T::MIN.borrowing_sub(0, true), ($T::MAX, true)); + assert_eq!($T::MIN.borrowing_sub(1, true), ($T::MAX - 1, true)); - assert_eq!((_1 << 1).trailing_ones(), 0); - assert_eq!((_1 >> 1).leading_ones(), 0); + assert_eq!($T::MAX.borrowing_sub($T::MAX, false), (0, false)); + assert_eq!($T::MAX.borrowing_sub(0, true), ($T::MAX - 1, false)); + assert_eq!($T::MAX.borrowing_sub($T::MAX, true), ($T::MAX, true)); + } - assert_eq!((_1 << 1).leading_ones(), $T::BITS - 1); - assert_eq!((_1 >> 1).trailing_ones(), $T::BITS - 1); + #[test] + fn test_midpoint() { + assert_eq!(<$T>::midpoint(1, 3), 2); + assert_eq!(<$T>::midpoint(3, 1), 2); - assert_eq!(_0.leading_ones(), 0); - assert_eq!(_0.trailing_ones(), 0); + assert_eq!(<$T>::midpoint(0, 0), 0); + assert_eq!(<$T>::midpoint(0, 2), 1); + assert_eq!(<$T>::midpoint(2, 0), 1); + assert_eq!(<$T>::midpoint(2, 2), 2); - let x: $T = 0b0010_1100; - assert_eq!(x.leading_ones(), 0); - assert_eq!(x.trailing_ones(), 0); - } + assert_eq!(<$T>::midpoint(1, 4), 2); + assert_eq!(<$T>::midpoint(4, 1), 2); + assert_eq!(<$T>::midpoint(3, 4), 3); + assert_eq!(<$T>::midpoint(4, 3), 3); - #[test] - fn test_rotate() { - assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A); - assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B); - assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C); + assert_eq!(<$T>::midpoint(<$T>::MIN, <$T>::MAX), (<$T>::MAX - <$T>::MIN) / 2); + assert_eq!(<$T>::midpoint(<$T>::MAX, <$T>::MIN), (<$T>::MAX - <$T>::MIN) / 2); + assert_eq!(<$T>::midpoint(<$T>::MIN, <$T>::MIN), <$T>::MIN); + assert_eq!(<$T>::midpoint(<$T>::MAX, <$T>::MAX), <$T>::MAX); - // Rotating these should make no difference - // - // We test using 124 bits because to ensure that overlong bit shifts do - // not cause undefined behaviour. See #10183. - assert_eq!(_0.rotate_left(124), _0); - assert_eq!(_1.rotate_left(124), _1); - assert_eq!(_0.rotate_right(124), _0); - assert_eq!(_1.rotate_right(124), _1); - - // Rotating by 0 should have no effect - assert_eq!(A.rotate_left(0), A); - assert_eq!(B.rotate_left(0), B); - assert_eq!(C.rotate_left(0), C); - // Rotating by a multiple of word size should also have no effect - assert_eq!(A.rotate_left(128), A); - assert_eq!(B.rotate_left(128), B); - assert_eq!(C.rotate_left(128), C); - } - - #[test] - fn test_swap_bytes() { - assert_eq!(A.swap_bytes().swap_bytes(), A); - assert_eq!(B.swap_bytes().swap_bytes(), B); - assert_eq!(C.swap_bytes().swap_bytes(), C); - - // Swapping these should make no difference - assert_eq!(_0.swap_bytes(), _0); - assert_eq!(_1.swap_bytes(), _1); - } - - #[test] - fn test_reverse_bits() { - assert_eq!(A.reverse_bits().reverse_bits(), A); - assert_eq!(B.reverse_bits().reverse_bits(), B); - assert_eq!(C.reverse_bits().reverse_bits(), C); - - // Swapping these should make no difference - assert_eq!(_0.reverse_bits(), _0); - assert_eq!(_1.reverse_bits(), _1); - } - - #[test] - fn test_le() { - assert_eq!($T::from_le(A.to_le()), A); - assert_eq!($T::from_le(B.to_le()), B); - assert_eq!($T::from_le(C.to_le()), C); - assert_eq!($T::from_le(_0), _0); - assert_eq!($T::from_le(_1), _1); - assert_eq!(_0.to_le(), _0); - assert_eq!(_1.to_le(), _1); - } - - #[test] - fn test_be() { - assert_eq!($T::from_be(A.to_be()), A); - assert_eq!($T::from_be(B.to_be()), B); - assert_eq!($T::from_be(C.to_be()), C); - assert_eq!($T::from_be(_0), _0); - assert_eq!($T::from_be(_1), _1); - assert_eq!(_0.to_be(), _0); - assert_eq!(_1.to_be(), _1); - } - - #[test] - fn test_unsigned_checked_div() { - assert!((10 as $T).checked_div(2) == Some(5)); - assert!((5 as $T).checked_div(0) == None); - } - - fn from_str(t: &str) -> Option { - FromStr::from_str(t).ok() - } - - #[test] - pub fn test_from_str() { - assert_eq!(from_str::<$T>("0"), Some(0 as $T)); - assert_eq!(from_str::<$T>("3"), Some(3 as $T)); - assert_eq!(from_str::<$T>("10"), Some(10 as $T)); - assert_eq!(from_str::("123456789"), Some(123456789 as u32)); - assert_eq!(from_str::<$T>("00100"), Some(100 as $T)); - - assert_eq!(from_str::<$T>(""), None); - assert_eq!(from_str::<$T>(" "), None); - assert_eq!(from_str::<$T>("x"), None); - } - - #[test] - pub fn test_parse_bytes() { - assert_eq!($T::from_str_radix("123", 10), Ok(123 as $T)); - assert_eq!($T::from_str_radix("1001", 2), Ok(9 as $T)); - assert_eq!($T::from_str_radix("123", 8), Ok(83 as $T)); - assert_eq!(u16::from_str_radix("123", 16), Ok(291 as u16)); - assert_eq!(u16::from_str_radix("ffff", 16), Ok(65535 as u16)); - assert_eq!($T::from_str_radix("z", 36), Ok(35 as $T)); - - assert_eq!($T::from_str_radix("Z", 10).ok(), None::<$T>); - assert_eq!($T::from_str_radix("_", 2).ok(), None::<$T>); - } - - #[test] - fn test_pow() { - let mut r = 2 as $T; - assert_eq!(r.pow(2), 4 as $T); - assert_eq!(r.pow(0), 1 as $T); - assert_eq!(r.wrapping_pow(2), 4 as $T); - assert_eq!(r.wrapping_pow(0), 1 as $T); - assert_eq!(r.checked_pow(2), Some(4 as $T)); - assert_eq!(r.checked_pow(0), Some(1 as $T)); - assert_eq!(r.overflowing_pow(2), (4 as $T, false)); - assert_eq!(r.overflowing_pow(0), (1 as $T, false)); - assert_eq!(r.saturating_pow(2), 4 as $T); - assert_eq!(r.saturating_pow(0), 1 as $T); - - r = MAX; - // use `^` to represent .pow() with no overflow. - // if itest::MAX == 2^j-1, then itest is a `j` bit int, - // so that `itest::MAX*itest::MAX == 2^(2*j)-2^(j+1)+1`, - // thussaturating_pow the overflowing result is exactly 1. - assert_eq!(r.wrapping_pow(2), 1 as $T); - assert_eq!(r.checked_pow(2), None); - assert_eq!(r.overflowing_pow(2), (1 as $T, true)); - assert_eq!(r.saturating_pow(2), MAX); - } - - #[test] - fn test_isqrt() { - assert_eq!((0 as $T).isqrt(), 0 as $T); - assert_eq!((1 as $T).isqrt(), 1 as $T); - assert_eq!((2 as $T).isqrt(), 1 as $T); - assert_eq!((99 as $T).isqrt(), 9 as $T); - assert_eq!((100 as $T).isqrt(), 10 as $T); - assert_eq!($T::MAX.isqrt(), (1 << ($T::BITS / 2)) - 1); - } - - #[cfg(not(miri))] // Miri is too slow - #[test] - fn test_lots_of_isqrt() { - let n_max: $T = (1024 * 1024).min($T::MAX as u128) as $T; - for n in 0..=n_max { - let isqrt: $T = n.isqrt(); - - assert!(isqrt.pow(2) <= n); - assert!(isqrt + 1 == (1 as $T) << ($T::BITS / 2) || (isqrt + 1).pow(2) > n); - } - - for n in ($T::MAX - 255)..=$T::MAX { - let isqrt: $T = n.isqrt(); - - assert!(isqrt.pow(2) <= n); - assert!(isqrt + 1 == (1 as $T) << ($T::BITS / 2) || (isqrt + 1).pow(2) > n); - } - } - - #[test] - fn test_div_floor() { - assert_eq!((8 as $T).div_floor(3), 2); - } - - #[test] - fn test_div_ceil() { - assert_eq!((8 as $T).div_ceil(3), 3); - } - - #[test] - fn test_next_multiple_of() { - assert_eq!((16 as $T).next_multiple_of(8), 16); - assert_eq!((23 as $T).next_multiple_of(8), 24); - assert_eq!(MAX.next_multiple_of(1), MAX); - } - - #[test] - fn test_checked_next_multiple_of() { - assert_eq!((16 as $T).checked_next_multiple_of(8), Some(16)); - assert_eq!((23 as $T).checked_next_multiple_of(8), Some(24)); - assert_eq!((1 as $T).checked_next_multiple_of(0), None); - assert_eq!(MAX.checked_next_multiple_of(2), None); - } - - #[test] - fn test_is_next_multiple_of() { - assert!((12 as $T).is_multiple_of(4)); - assert!(!(12 as $T).is_multiple_of(5)); - assert!((0 as $T).is_multiple_of(0)); - assert!(!(12 as $T).is_multiple_of(0)); - } - - #[test] - fn test_carrying_add() { - assert_eq!($T::MAX.carrying_add(1, false), (0, true)); - assert_eq!($T::MAX.carrying_add(0, true), (0, true)); - assert_eq!($T::MAX.carrying_add(1, true), (1, true)); - - assert_eq!($T::MIN.carrying_add($T::MAX, false), ($T::MAX, false)); - assert_eq!($T::MIN.carrying_add(0, true), (1, false)); - assert_eq!($T::MIN.carrying_add($T::MAX, true), (0, true)); - } - - #[test] - fn test_borrowing_sub() { - assert_eq!($T::MIN.borrowing_sub(1, false), ($T::MAX, true)); - assert_eq!($T::MIN.borrowing_sub(0, true), ($T::MAX, true)); - assert_eq!($T::MIN.borrowing_sub(1, true), ($T::MAX - 1, true)); - - assert_eq!($T::MAX.borrowing_sub($T::MAX, false), (0, false)); - assert_eq!($T::MAX.borrowing_sub(0, true), ($T::MAX - 1, false)); - assert_eq!($T::MAX.borrowing_sub($T::MAX, true), ($T::MAX, true)); - } - - #[test] - fn test_midpoint() { - assert_eq!(<$T>::midpoint(1, 3), 2); - assert_eq!(<$T>::midpoint(3, 1), 2); - - assert_eq!(<$T>::midpoint(0, 0), 0); - assert_eq!(<$T>::midpoint(0, 2), 1); - assert_eq!(<$T>::midpoint(2, 0), 1); - assert_eq!(<$T>::midpoint(2, 2), 2); - - assert_eq!(<$T>::midpoint(1, 4), 2); - assert_eq!(<$T>::midpoint(4, 1), 2); - assert_eq!(<$T>::midpoint(3, 4), 3); - assert_eq!(<$T>::midpoint(4, 3), 3); - - assert_eq!(<$T>::midpoint(<$T>::MIN, <$T>::MAX), (<$T>::MAX - <$T>::MIN) / 2); - assert_eq!(<$T>::midpoint(<$T>::MAX, <$T>::MIN), (<$T>::MAX - <$T>::MIN) / 2); - assert_eq!(<$T>::midpoint(<$T>::MIN, <$T>::MIN), <$T>::MIN); - assert_eq!(<$T>::midpoint(<$T>::MAX, <$T>::MAX), <$T>::MAX); - - assert_eq!(<$T>::midpoint(<$T>::MIN, 6), <$T>::MIN / 2 + 3); - assert_eq!(<$T>::midpoint(6, <$T>::MIN), <$T>::MIN / 2 + 3); - assert_eq!(<$T>::midpoint(<$T>::MAX, 6), (<$T>::MAX - <$T>::MIN) / 2 + 3); - assert_eq!(<$T>::midpoint(6, <$T>::MAX), (<$T>::MAX - <$T>::MIN) / 2 + 3); - } + assert_eq!(<$T>::midpoint(<$T>::MIN, 6), <$T>::MIN / 2 + 3); + assert_eq!(<$T>::midpoint(6, <$T>::MIN), <$T>::MIN / 2 + 3); + assert_eq!(<$T>::midpoint(<$T>::MAX, 6), (<$T>::MAX - <$T>::MIN) / 2 + 3); + assert_eq!(<$T>::midpoint(6, <$T>::MAX), (<$T>::MAX - <$T>::MIN) / 2 + 3); } }; } diff --git a/library/core/tests/ops.rs b/library/core/tests/ops.rs index 2ee0abd399b..501e0f33fe4 100644 --- a/library/core/tests/ops.rs +++ b/library/core/tests/ops.rs @@ -1,4 +1,5 @@ mod control_flow; +mod from_residual; use core::ops::{ Bound, Deref, DerefMut, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive, diff --git a/library/core/tests/ops/from_residual.rs b/library/core/tests/ops/from_residual.rs new file mode 100644 index 00000000000..d5c86ccbcd3 --- /dev/null +++ b/library/core/tests/ops/from_residual.rs @@ -0,0 +1,26 @@ +//! Regression test that Option and ControlFlow can have downstream FromResidual impls. +//! cc https://github.com/rust-lang/rust/issues/99940, +//! This does NOT test that issue in general; Option and ControlFlow's FromResidual +//! impls in core were changed to not be affected by that issue. + +use core::ops::{ControlFlow, FromResidual}; + +struct Local; + +impl FromResidual for Option { + fn from_residual(_: Local) -> Option { + unimplemented!() + } +} + +impl FromResidual for ControlFlow { + fn from_residual(_: Local) -> ControlFlow { + unimplemented!() + } +} + +impl FromResidual for Result { + fn from_residual(_: Local) -> Result { + unimplemented!() + } +} diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index c271ac18706..72b53c60f74 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -28,7 +28,6 @@ #![feature(decl_macro)] #![feature(maybe_uninit_write_slice)] #![feature(negative_impls)] -#![feature(new_uninit)] #![feature(panic_can_unwind)] #![feature(restricted_std)] #![feature(rustc_attrs)] diff --git a/library/profiler_builtins/build.rs b/library/profiler_builtins/build.rs index 9d1c1ba305b..c1e0e5c1c89 100644 --- a/library/profiler_builtins/build.rs +++ b/library/profiler_builtins/build.rs @@ -3,7 +3,7 @@ //! See the build.rs for libcompiler_builtins crate for details. use std::env; -use std::path::Path; +use std::path::PathBuf; fn main() { println!("cargo:rerun-if-env-changed=LLVM_PROFILER_RT_LIB"); @@ -79,17 +79,25 @@ fn main() { cfg.define("COMPILER_RT_HAS_ATOMICS", Some("1")); } - // Note that this should exist if we're going to run (otherwise we just - // don't build profiler builtins at all). - let root = Path::new("../../src/llvm-project/compiler-rt"); + // Get the LLVM `compiler-rt` directory from bootstrap. + println!("cargo:rerun-if-env-changed=RUST_COMPILER_RT_FOR_PROFILER"); + let root = PathBuf::from(env::var("RUST_COMPILER_RT_FOR_PROFILER").unwrap_or_else(|_| { + let path = "../../src/llvm-project/compiler-rt"; + println!("RUST_COMPILER_RT_FOR_PROFILER was not set; falling back to {path:?}"); + path.to_owned() + })); let src_root = root.join("lib").join("profile"); + assert!(src_root.exists(), "profiler runtime source directory not found: {src_root:?}"); + let mut n_sources_found = 0u32; for src in profile_sources { let path = src_root.join(src); if path.exists() { cfg.file(path); + n_sources_found += 1; } } + assert!(n_sources_found > 0, "couldn't find any profiler runtime source files in {src_root:?}"); cfg.include(root.join("include")); cfg.warnings(false); diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 2ce284c85e2..5f0144922ca 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -17,7 +17,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core", public = true } -compiler_builtins = { version = "0.1.118" } +compiler_builtins = { version = "0.1.123" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } hashbrown = { version = "0.14", default-features = false, features = [ @@ -57,6 +57,9 @@ object = { version = "0.36.0", default-features = false, optional = true, featur 'archive', ] } +[target.'cfg(windows)'.dependencies.windows-targets] +path = "../windows_targets" + [dev-dependencies] rand = { version = "0.8.5", default-features = false, features = ["alloc"] } rand_xorshift = "0.3.0" @@ -116,7 +119,7 @@ std_detect_env_override = ["std_detect/std_detect_env_override"] # Enable using raw-dylib for Windows imports. # This will eventually be the default. -windows_raw_dylib = [] +windows_raw_dylib = ["windows-targets/windows_raw_dylib"] [package.metadata.fortanix-sgx] # Maximum possible number of threads when testing diff --git a/library/std/build.rs b/library/std/build.rs index 35a5977b6eb..fecdf2c3e1f 100644 --- a/library/std/build.rs +++ b/library/std/build.rs @@ -103,9 +103,9 @@ fn main() { ("arm64ec", _) => false, // MinGW ABI bugs ("x86_64", "windows") => false, - // x86 has ABI bugs that show up with optimizations. This should be partially fixed with - // the compiler-builtins update. - ("x86" | "x86_64", _) => false, + // Apple has a special ABI for `f16` that we do not yet support + // FIXME(builtins): fixed by + ("x86" | "x86_64", _) if target_vendor == "apple" => false, // Missing `__gnu_h2f_ieee` and `__gnu_f2h_ieee` ("powerpc" | "powerpc64", _) => false, // Missing `__gnu_h2f_ieee` and `__gnu_f2h_ieee` @@ -140,17 +140,17 @@ fn main() { _ => false, }; - // These are currently empty, but will fill up as some platforms move from completely - // unreliable to reliable basics but unreliable math. + // Configure platforms that have reliable basics but may have unreliable math. // LLVM is currenlty adding missing routines, let has_reliable_f16_math = has_reliable_f16 && match (target_arch.as_str(), target_os.as_str()) { // FIXME: Disabled on Miri as the intrinsics are not implemented yet. _ if is_miri => false, - // Currently nothing special. Hooray! - // This will change as platforms gain better better support for standard ops but math - // lags behind. + // x86 has a crash for `powi`: + ("x86" | "x86_64", _) => false, + // Assume that working `f16` means working `f16` math for most platforms, since + // operations just go through `f32`. _ => true, }; diff --git a/library/std/src/env.rs b/library/std/src/env.rs index 50ae83090c7..e06a851658c 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -198,13 +198,12 @@ impl fmt::Debug for VarsOs { /// /// # Errors /// -/// This function will return an error if the environment variable isn't set. +/// Returns [`VarError::NotPresent`] if: +/// - The variable is not set. +/// - The variable's name contains an equal sign or NUL (`'='` or `'\0'`). /// -/// This function may return an error if the environment variable's name contains -/// the equal sign character (`=`) or the NUL character. -/// -/// This function will return an error if the environment variable's value is -/// not valid Unicode. If this is not desired, consider using [`var_os`]. +/// Returns [`VarError::NotUnicode`] if the variable's value is not valid +/// Unicode. If this is not desired, consider using [`var_os`]. /// /// # Examples /// @@ -355,7 +354,13 @@ impl Error for VarError { /// } /// assert_eq!(env::var(key), Ok("VALUE".to_string())); /// ``` -#[rustc_deprecated_safe_2024] +#[cfg_attr(bootstrap, rustc_deprecated_safe_2024)] +#[cfg_attr( + not(bootstrap), + rustc_deprecated_safe_2024( + audit_that = "the environment access only happens in single-threaded code" + ) +)] #[stable(feature = "env", since = "1.0.0")] pub unsafe fn set_var, V: AsRef>(key: K, value: V) { let (key, value) = (key.as_ref(), value.as_ref()); @@ -419,7 +424,13 @@ pub unsafe fn set_var, V: AsRef>(key: K, value: V) { /// } /// assert!(env::var(key).is_err()); /// ``` -#[rustc_deprecated_safe_2024] +#[cfg_attr(bootstrap, rustc_deprecated_safe_2024)] +#[cfg_attr( + not(bootstrap), + rustc_deprecated_safe_2024( + audit_that = "the environment access only happens in single-threaded code" + ) +)] #[stable(feature = "env", since = "1.0.0")] pub unsafe fn remove_var>(key: K) { let key = key.as_ref(); diff --git a/library/std/src/f128.rs b/library/std/src/f128.rs index f6df6259137..b436fe9929c 100644 --- a/library/std/src/f128.rs +++ b/library/std/src/f128.rs @@ -248,11 +248,16 @@ impl f128 { /// Returns a number composed of the magnitude of `self` and the sign of /// `sign`. /// - /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise - /// equal to `-self`. If `self` is a NaN, then a NaN with the sign bit of - /// `sign` is returned. Note, however, that conserving the sign bit on NaN - /// across arithmetical operations is not generally guaranteed. - /// See [explanation of NaN as a special value](primitive@f128) for more info. + /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise equal to `-self`. + /// If `self` is a NaN, then a NaN with the same payload as `self` and the sign bit of `sign` is + /// returned. + /// + /// If `sign` is a NaN, then this operation will still carry over its sign into the result. Note + /// that IEEE 754 doesn't assign any meaning to the sign bit in case of a NaN, and as Rust + /// doesn't guarantee that the bit pattern of NaNs are conserved over arithmetic operations, the + /// result of `copysign` with `sign` being a NaN might produce an unexpected or non-portable + /// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more + /// info. /// /// # Examples /// diff --git a/library/std/src/f16.rs b/library/std/src/f16.rs index 10908332762..b2cd5fae9d0 100644 --- a/library/std/src/f16.rs +++ b/library/std/src/f16.rs @@ -247,11 +247,16 @@ impl f16 { /// Returns a number composed of the magnitude of `self` and the sign of /// `sign`. /// - /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise - /// equal to `-self`. If `self` is a NaN, then a NaN with the sign bit of - /// `sign` is returned. Note, however, that conserving the sign bit on NaN - /// across arithmetical operations is not generally guaranteed. - /// See [explanation of NaN as a special value](primitive@f16) for more info. + /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise equal to `-self`. + /// If `self` is a NaN, then a NaN with the same payload as `self` and the sign bit of `sign` is + /// returned. + /// + /// If `sign` is a NaN, then this operation will still carry over its sign into the result. Note + /// that IEEE 754 doesn't assign any meaning to the sign bit in case of a NaN, and as Rust + /// doesn't guarantee that the bit pattern of NaNs are conserved over arithmetic operations, the + /// result of `copysign` with `sign` being a NaN might produce an unexpected or non-portable + /// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more + /// info. /// /// # Examples /// diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index 12433d25bfa..cafbe9761da 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -226,11 +226,16 @@ impl f32 { /// Returns a number composed of the magnitude of `self` and the sign of /// `sign`. /// - /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise - /// equal to `-self`. If `self` is a NaN, then a NaN with the sign bit of - /// `sign` is returned. Note, however, that conserving the sign bit on NaN - /// across arithmetical operations is not generally guaranteed. - /// See [explanation of NaN as a special value](primitive@f32) for more info. + /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise equal to `-self`. + /// If `self` is a NaN, then a NaN with the same payload as `self` and the sign bit of `sign` is + /// returned. + /// + /// If `sign` is a NaN, then this operation will still carry over its sign into the result. Note + /// that IEEE 754 doesn't assign any meaning to the sign bit in case of a NaN, and as Rust + /// doesn't guarantee that the bit pattern of NaNs are conserved over arithmetic operations, the + /// result of `copysign` with `sign` being a NaN might produce an unexpected or non-portable + /// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more + /// info. /// /// # Examples /// diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index a343e19173e..fba283e3a44 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -226,11 +226,16 @@ impl f64 { /// Returns a number composed of the magnitude of `self` and the sign of /// `sign`. /// - /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise - /// equal to `-self`. If `self` is a NaN, then a NaN with the sign bit of - /// `sign` is returned. Note, however, that conserving the sign bit on NaN - /// across arithmetical operations is not generally guaranteed. - /// See [explanation of NaN as a special value](primitive@f32) for more info. + /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise equal to `-self`. + /// If `self` is a NaN, then a NaN with the same payload as `self` and the sign bit of `sign` is + /// returned. + /// + /// If `sign` is a NaN, then this operation will still carry over its sign into the result. Note + /// that IEEE 754 doesn't assign any meaning to the sign bit in case of a NaN, and as Rust + /// doesn't guarantee that the bit pattern of NaNs are conserved over arithmetic operations, the + /// result of `copysign` with `sign` being a NaN might produce an unexpected or non-portable + /// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more + /// info. /// /// # Examples /// diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index a501bcc98cf..918eec2d0d8 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -3,10 +3,13 @@ #[cfg(test)] mod tests; +use core::clone::CloneToUninit; + use crate::borrow::{Borrow, Cow}; use crate::collections::TryReserveError; use crate::hash::{Hash, Hasher}; use crate::ops::{self, Range}; +use crate::ptr::addr_of_mut; use crate::rc::Rc; use crate::str::FromStr; use crate::sync::Arc; @@ -1261,6 +1264,16 @@ impl Clone for Box { } } +#[unstable(feature = "clone_to_uninit", issue = "126799")] +unsafe impl CloneToUninit for OsStr { + #[inline] + #[cfg_attr(debug_assertions, track_caller)] + unsafe fn clone_to_uninit(&self, dst: *mut Self) { + // SAFETY: we're just a wrapper around a platform-specific Slice + unsafe { self.inner.clone_to_uninit(addr_of_mut!((*dst).inner)) } + } +} + #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From for Arc { /// Converts an [`OsString`] into an [Arc]<[OsStr]> by moving the [`OsString`] diff --git a/library/std/src/ffi/os_str/tests.rs b/library/std/src/ffi/os_str/tests.rs index 5b39b9e34d8..67147934b4d 100644 --- a/library/std/src/ffi/os_str/tests.rs +++ b/library/std/src/ffi/os_str/tests.rs @@ -1,4 +1,6 @@ use super::*; +use crate::mem::MaybeUninit; +use crate::ptr; #[test] fn test_os_string_with_capacity() { @@ -286,3 +288,18 @@ fn slice_surrogate_edge() { assert_eq!(post_crab.slice_encoded_bytes(..4), "🦀"); assert_eq!(post_crab.slice_encoded_bytes(4..), surrogate); } + +#[test] +fn clone_to_uninit() { + let a = OsStr::new("hello.txt"); + + let mut storage = vec![MaybeUninit::::uninit(); size_of_val::(a)]; + unsafe { a.clone_to_uninit(ptr::from_mut::<[_]>(storage.as_mut_slice()) as *mut OsStr) }; + assert_eq!(a.as_encoded_bytes(), unsafe { MaybeUninit::slice_assume_init_ref(&storage) }); + + let mut b: Box = OsStr::new("world.exe").into(); + assert_eq!(size_of_val::(a), size_of_val::(&b)); + assert_ne!(a, &*b); + unsafe { a.clone_to_uninit(ptr::from_mut::(&mut b)) }; + assert_eq!(a, &*b); +} diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index c5edb03bb08..6a0d9f47960 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -2491,6 +2491,8 @@ pub fn remove_dir>(path: P) -> io::Result<()> { /// /// Consider ignoring the error if validating the removal is not required for your use case. /// +/// [`io::ErrorKind::NotFound`] is only returned if no removal occurs. +/// /// [`fs::remove_file`]: remove_file /// [`fs::remove_dir`]: remove_dir /// diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 93a74ef739b..bea8eda2619 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -319,6 +319,7 @@ // tidy-alphabetical-start #![feature(c_str_module)] #![feature(char_internals)] +#![feature(clone_to_uninit)] #![feature(core_intrinsics)] #![feature(core_io_borrowed_buf)] #![feature(duration_constants)] @@ -361,7 +362,7 @@ #![feature(allocator_api)] #![feature(get_mut_unchecked)] #![feature(map_try_insert)] -#![feature(new_uninit)] +#![feature(new_zeroed_alloc)] #![feature(slice_concat_trait)] #![feature(thin_box)] #![feature(try_reserve_kind)] diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs index c53423675bd..46202441d4e 100644 --- a/library/std/src/os/unix/process.rs +++ b/library/std/src/os/unix/process.rs @@ -109,13 +109,21 @@ pub trait CommandExt: Sealed { /// Schedules a closure to be run just before the `exec` function is /// invoked. /// - /// This method is stable and usable, but it should be unsafe. To fix - /// that, it got deprecated in favor of the unsafe [`pre_exec`]. + /// `before_exec` used to be a safe method, but it needs to be unsafe since the closure may only + /// perform operations that are *async-signal-safe*. Hence it got deprecated in favor of the + /// unsafe [`pre_exec`]. Meanwhile, Rust gained the ability to make an existing safe method + /// fully unsafe in a new edition, which is how `before_exec` became `unsafe`. It still also + /// remains deprecated; `pre_exec` should be used instead. /// /// [`pre_exec`]: CommandExt::pre_exec #[stable(feature = "process_exec", since = "1.15.0")] #[deprecated(since = "1.37.0", note = "should be unsafe, use `pre_exec` instead")] - fn before_exec(&mut self, f: F) -> &mut process::Command + #[cfg_attr(bootstrap, rustc_deprecated_safe_2024)] + #[cfg_attr( + not(bootstrap), + rustc_deprecated_safe_2024(audit_that = "the closure is async-signal-safe") + )] + unsafe fn before_exec(&mut self, f: F) -> &mut process::Command where F: FnMut() -> io::Result<()> + Send + Sync + 'static, { diff --git a/library/std/src/os/wasi/fs.rs b/library/std/src/os/wasi/fs.rs index a58ca543d67..9ec3e387e2b 100644 --- a/library/std/src/os/wasi/fs.rs +++ b/library/std/src/os/wasi/fs.rs @@ -2,7 +2,6 @@ //! //! [`std::fs`]: crate::fs -#![deny(unsafe_op_in_unsafe_fn)] #![unstable(feature = "wasi_ext", issue = "71213")] // Used for `File::read` on intra-doc links diff --git a/library/std/src/os/wasi/mod.rs b/library/std/src/os/wasi/mod.rs index e36b93e60ea..33b50c9e53b 100644 --- a/library/std/src/os/wasi/mod.rs +++ b/library/std/src/os/wasi/mod.rs @@ -30,7 +30,7 @@ #![cfg_attr(not(target_env = "p2"), stable(feature = "rust1", since = "1.0.0"))] #![cfg_attr(target_env = "p2", unstable(feature = "wasip2", issue = "none"))] -#![deny(unsafe_op_in_unsafe_fn)] +#![forbid(unsafe_op_in_unsafe_fn)] #![doc(cfg(target_os = "wasi"))] pub mod ffi; diff --git a/library/std/src/os/wasip2/mod.rs b/library/std/src/os/wasip2/mod.rs index 1d44dd72814..809a288f20d 100644 --- a/library/std/src/os/wasip2/mod.rs +++ b/library/std/src/os/wasip2/mod.rs @@ -2,4 +2,5 @@ //! //! This module is currently empty, but will be filled over time as wasi-libc support for WASI Preview 2 is stabilized. +#![forbid(unsafe_op_in_unsafe_fn)] #![stable(feature = "raw_ext", since = "1.1.0")] diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index e818b448270..190eed94555 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -275,7 +275,7 @@ fn default_hook(info: &PanicHookInfo<'_>) { if cfg!(miri) { let _ = writeln!( err, - "note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` \ + "note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` \ for the environment variable to have an effect" ); } diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 80163667636..9eaa0e01c2c 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -70,6 +70,8 @@ #[cfg(test)] mod tests; +use core::clone::CloneToUninit; + use crate::borrow::{Borrow, Cow}; use crate::collections::TryReserveError; use crate::error::Error; @@ -3109,6 +3111,16 @@ impl Path { } } +#[unstable(feature = "clone_to_uninit", issue = "126799")] +unsafe impl CloneToUninit for Path { + #[inline] + #[cfg_attr(debug_assertions, track_caller)] + unsafe fn clone_to_uninit(&self, dst: *mut Self) { + // SAFETY: Path is just a wrapper around OsStr + unsafe { self.inner.clone_to_uninit(core::ptr::addr_of_mut!((*dst).inner)) } + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl AsRef for Path { #[inline] diff --git a/library/std/src/path/tests.rs b/library/std/src/path/tests.rs index a12e42cba0c..6436872087d 100644 --- a/library/std/src/path/tests.rs +++ b/library/std/src/path/tests.rs @@ -3,6 +3,8 @@ use core::hint::black_box; use super::*; use crate::collections::{BTreeSet, HashSet}; use crate::hash::DefaultHasher; +use crate::mem::MaybeUninit; +use crate::ptr; #[allow(unknown_lints, unused_macro_rules)] macro_rules! t ( @@ -2054,3 +2056,20 @@ fn bench_hash_path_long(b: &mut test::Bencher) { black_box(hasher.finish()); } + +#[test] +fn clone_to_uninit() { + let a = Path::new("hello.txt"); + + let mut storage = vec![MaybeUninit::::uninit(); size_of_val::(a)]; + unsafe { a.clone_to_uninit(ptr::from_mut::<[_]>(storage.as_mut_slice()) as *mut Path) }; + assert_eq!(a.as_os_str().as_encoded_bytes(), unsafe { + MaybeUninit::slice_assume_init_ref(&storage) + }); + + let mut b: Box = Path::new("world.exe").into(); + assert_eq!(size_of_val::(a), size_of_val::(&b)); + assert_ne!(a, &*b); + unsafe { a.clone_to_uninit(ptr::from_mut::(&mut b)) }; + assert_eq!(a, &*b); +} diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 9ffdebe1b6f..bbea27ebc10 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -2296,6 +2296,15 @@ impl Child { /// } /// ``` /// +/// In its current implementation, this function will execute exit handlers registered with `atexit` +/// as well as other platform-specific exit handlers (e.g. `fini` sections of ELF shared objects). +/// This means that Rust requires that all exit handlers are safe to execute at any time. In +/// particular, if an exit handler cleans up some state that might be concurrently accessed by other +/// threads, it is required that the exit handler performs suitable synchronization with those +/// threads. (The alternative to this requirement would be to not run exit handlers at all, which is +/// considered undesirable. Note that returning from `main` also calls `exit`, so making `exit` an +/// unsafe operation is not an option.) +/// /// ## Platform-specific behavior /// /// **Unix**: On Unix-like platforms, it is unlikely that all 32 bits of `exit` diff --git a/library/std/src/sys/pal/hermit/alloc.rs b/library/std/src/sys/alloc/hermit.rs similarity index 97% rename from library/std/src/sys/pal/hermit/alloc.rs rename to library/std/src/sys/alloc/hermit.rs index f10d5f9227e..77f8200a70a 100644 --- a/library/std/src/sys/pal/hermit/alloc.rs +++ b/library/std/src/sys/alloc/hermit.rs @@ -1,4 +1,3 @@ -use super::hermit_abi; use crate::alloc::{GlobalAlloc, Layout, System}; #[stable(feature = "alloc_system_type", since = "1.28.0")] diff --git a/library/std/src/sys/pal/common/alloc.rs b/library/std/src/sys/alloc/mod.rs similarity index 55% rename from library/std/src/sys/pal/common/alloc.rs rename to library/std/src/sys/alloc/mod.rs index 1b465f95d1b..2c0b533a570 100644 --- a/library/std/src/sys/pal/common/alloc.rs +++ b/library/std/src/sys/alloc/mod.rs @@ -1,10 +1,18 @@ #![forbid(unsafe_op_in_unsafe_fn)] + use crate::alloc::{GlobalAlloc, Layout, System}; -use crate::{cmp, ptr}; +use crate::ptr; // The minimum alignment guaranteed by the architecture. This value is used to // add fast paths for low alignment values. -#[cfg(any( +#[allow(dead_code)] +const MIN_ALIGN: usize = if cfg!(any( + all(target_arch = "riscv32", any(target_os = "espidf", target_os = "zkvm")), + all(target_arch = "xtensa", target_os = "espidf"), +)) { + // The allocator on the esp-idf and zkvm platforms guarantees 4 byte alignment. + 4 +} else if cfg!(any( target_arch = "x86", target_arch = "arm", target_arch = "m68k", @@ -16,11 +24,11 @@ use crate::{cmp, ptr}; target_arch = "sparc", target_arch = "wasm32", target_arch = "hexagon", - all(target_arch = "riscv32", not(any(target_os = "espidf", target_os = "zkvm"))), - all(target_arch = "xtensa", not(target_os = "espidf")), -))] -pub const MIN_ALIGN: usize = 8; -#[cfg(any( + target_arch = "riscv32", + target_arch = "xtensa", +)) { + 8 +} else if cfg!(any( target_arch = "x86_64", target_arch = "aarch64", target_arch = "arm64ec", @@ -31,16 +39,14 @@ pub const MIN_ALIGN: usize = 8; target_arch = "sparc64", target_arch = "riscv64", target_arch = "wasm64", -))] -pub const MIN_ALIGN: usize = 16; -// The allocator on the esp-idf and zkvm platforms guarantee 4 byte alignment. -#[cfg(all(any( - all(target_arch = "riscv32", any(target_os = "espidf", target_os = "zkvm")), - all(target_arch = "xtensa", target_os = "espidf"), -)))] -pub const MIN_ALIGN: usize = 4; +)) { + 16 +} else { + panic!("add a value for MIN_ALIGN") +}; -pub unsafe fn realloc_fallback( +#[allow(dead_code)] +unsafe fn realloc_fallback( alloc: &System, ptr: *mut u8, old_layout: Layout, @@ -52,10 +58,37 @@ pub unsafe fn realloc_fallback( let new_ptr = GlobalAlloc::alloc(alloc, new_layout); if !new_ptr.is_null() { - let size = cmp::min(old_layout.size(), new_size); + let size = usize::min(old_layout.size(), new_size); ptr::copy_nonoverlapping(ptr, new_ptr, size); GlobalAlloc::dealloc(alloc, ptr, old_layout); } + new_ptr } } + +cfg_if::cfg_if! { + if #[cfg(any( + target_family = "unix", + target_os = "wasi", + target_os = "teeos", + ))] { + mod unix; + } else if #[cfg(target_os = "windows")] { + mod windows; + } else if #[cfg(target_os = "hermit")] { + mod hermit; + } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] { + mod sgx; + } else if #[cfg(target_os = "solid_asp3")] { + mod solid; + } else if #[cfg(target_os = "uefi")] { + mod uefi; + } else if #[cfg(target_family = "wasm")] { + mod wasm; + } else if #[cfg(target_os = "xous")] { + mod xous; + } else if #[cfg(target_os = "zkvm")] { + mod zkvm; + } +} diff --git a/library/std/src/sys/pal/sgx/alloc.rs b/library/std/src/sys/alloc/sgx.rs similarity index 95% rename from library/std/src/sys/pal/sgx/alloc.rs rename to library/std/src/sys/alloc/sgx.rs index f68ede9fcf0..fca9d087e5b 100644 --- a/library/std/src/sys/pal/sgx/alloc.rs +++ b/library/std/src/sys/alloc/sgx.rs @@ -1,9 +1,8 @@ -use core::sync::atomic::{AtomicBool, Ordering}; - -use super::abi::mem as sgx_mem; -use super::waitqueue::SpinMutex; use crate::alloc::{GlobalAlloc, Layout, System}; use crate::ptr; +use crate::sync::atomic::{AtomicBool, Ordering}; +use crate::sys::pal::abi::mem as sgx_mem; +use crate::sys::pal::waitqueue::SpinMutex; // Using a SpinMutex because we never want to exit the enclave waiting for the // allocator. diff --git a/library/std/src/sys/pal/solid/alloc.rs b/library/std/src/sys/alloc/solid.rs similarity index 94% rename from library/std/src/sys/pal/solid/alloc.rs rename to library/std/src/sys/alloc/solid.rs index 4cf60ac9b2e..abb534a1c5c 100644 --- a/library/std/src/sys/pal/solid/alloc.rs +++ b/library/std/src/sys/alloc/solid.rs @@ -1,5 +1,5 @@ +use super::{realloc_fallback, MIN_ALIGN}; use crate::alloc::{GlobalAlloc, Layout, System}; -use crate::sys::common::alloc::{realloc_fallback, MIN_ALIGN}; #[stable(feature = "alloc_system_type", since = "1.28.0")] unsafe impl GlobalAlloc for System { diff --git a/library/std/src/sys/pal/uefi/alloc.rs b/library/std/src/sys/alloc/uefi.rs similarity index 98% rename from library/std/src/sys/pal/uefi/alloc.rs rename to library/std/src/sys/alloc/uefi.rs index 15404ac3ea6..5221876e908 100644 --- a/library/std/src/sys/pal/uefi/alloc.rs +++ b/library/std/src/sys/alloc/uefi.rs @@ -3,9 +3,9 @@ use r_efi::protocols::loaded_image; -use super::helpers; use crate::alloc::{GlobalAlloc, Layout, System}; use crate::sync::OnceLock; +use crate::sys::pal::helpers; #[stable(feature = "alloc_system_type", since = "1.28.0")] unsafe impl GlobalAlloc for System { diff --git a/library/std/src/sys/pal/unix/alloc.rs b/library/std/src/sys/alloc/unix.rs similarity index 83% rename from library/std/src/sys/pal/unix/alloc.rs rename to library/std/src/sys/alloc/unix.rs index 625ba5247f1..46ed7de7162 100644 --- a/library/std/src/sys/pal/unix/alloc.rs +++ b/library/std/src/sys/alloc/unix.rs @@ -1,6 +1,6 @@ +use super::{realloc_fallback, MIN_ALIGN}; use crate::alloc::{GlobalAlloc, Layout, System}; use crate::ptr; -use crate::sys::common::alloc::{realloc_fallback, MIN_ALIGN}; #[stable(feature = "alloc_system_type", since = "1.28.0")] unsafe impl GlobalAlloc for System { @@ -11,7 +11,7 @@ unsafe impl GlobalAlloc for System { // Also see and // . if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { - libc::malloc(layout.size()) as *mut u8 + unsafe { libc::malloc(layout.size()) as *mut u8 } } else { // `posix_memalign` returns a non-aligned value if supplied a very // large alignment on older versions of Apple's platforms (unknown @@ -25,7 +25,7 @@ unsafe impl GlobalAlloc for System { return ptr::null_mut(); } } - aligned_malloc(&layout) + unsafe { aligned_malloc(&layout) } } } @@ -33,11 +33,11 @@ unsafe impl GlobalAlloc for System { unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { // See the comment above in `alloc` for why this check looks the way it does. if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { - libc::calloc(layout.size(), 1) as *mut u8 + unsafe { libc::calloc(layout.size(), 1) as *mut u8 } } else { - let ptr = self.alloc(layout); + let ptr = unsafe { self.alloc(layout) }; if !ptr.is_null() { - ptr::write_bytes(ptr, 0, layout.size()); + unsafe { ptr::write_bytes(ptr, 0, layout.size()) }; } ptr } @@ -45,15 +45,15 @@ unsafe impl GlobalAlloc for System { #[inline] unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) { - libc::free(ptr as *mut libc::c_void) + unsafe { libc::free(ptr as *mut libc::c_void) } } #[inline] unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { if layout.align() <= MIN_ALIGN && layout.align() <= new_size { - libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8 + unsafe { libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8 } } else { - realloc_fallback(self, ptr, layout, new_size) + unsafe { realloc_fallback(self, ptr, layout, new_size) } } } } @@ -81,7 +81,7 @@ cfg_if::cfg_if! { // posix_memalign only has one, clear requirement: that the alignment be a multiple of // `sizeof(void*)`. Since these are all powers of 2, we can just use max. let align = layout.align().max(crate::mem::size_of::()); - let ret = libc::posix_memalign(&mut out, align, layout.size()); + let ret = unsafe { libc::posix_memalign(&mut out, align, layout.size()) }; if ret != 0 { ptr::null_mut() } else { out as *mut u8 } } } diff --git a/library/std/src/sys/pal/wasm/alloc.rs b/library/std/src/sys/alloc/wasm.rs similarity index 100% rename from library/std/src/sys/pal/wasm/alloc.rs rename to library/std/src/sys/alloc/wasm.rs diff --git a/library/std/src/sys/pal/windows/alloc.rs b/library/std/src/sys/alloc/windows.rs similarity index 97% rename from library/std/src/sys/pal/windows/alloc.rs rename to library/std/src/sys/alloc/windows.rs index 92b68b26032..e91956966aa 100644 --- a/library/std/src/sys/pal/windows/alloc.rs +++ b/library/std/src/sys/alloc/windows.rs @@ -1,11 +1,10 @@ -use core::mem::MaybeUninit; - +use super::{realloc_fallback, MIN_ALIGN}; use crate::alloc::{GlobalAlloc, Layout, System}; use crate::ffi::c_void; +use crate::mem::MaybeUninit; use crate::ptr; use crate::sync::atomic::{AtomicPtr, Ordering}; -use crate::sys::c::{self, windows_targets}; -use crate::sys::common::alloc::{realloc_fallback, MIN_ALIGN}; +use crate::sys::c; #[cfg(test)] mod tests; @@ -113,28 +112,28 @@ fn init_or_get_process_heap() -> c::HANDLE { extern "C" fn process_heap_init_and_alloc( _heap: MaybeUninit, // We pass this argument to match the ABI of `HeapAlloc` flags: u32, - dwBytes: usize, + bytes: usize, ) -> *mut c_void { let heap = init_or_get_process_heap(); if core::intrinsics::unlikely(heap.is_null()) { return ptr::null_mut(); } // SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`. - unsafe { HeapAlloc(heap, flags, dwBytes) } + unsafe { HeapAlloc(heap, flags, bytes) } } #[inline(never)] fn process_heap_alloc( _heap: MaybeUninit, // We pass this argument to match the ABI of `HeapAlloc`, flags: u32, - dwBytes: usize, + bytes: usize, ) -> *mut c_void { let heap = HEAP.load(Ordering::Relaxed); if core::intrinsics::likely(!heap.is_null()) { // SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`. - unsafe { HeapAlloc(heap, flags, dwBytes) } + unsafe { HeapAlloc(heap, flags, bytes) } } else { - process_heap_init_and_alloc(MaybeUninit::uninit(), flags, dwBytes) + process_heap_init_and_alloc(MaybeUninit::uninit(), flags, bytes) } } diff --git a/library/std/src/sys/pal/windows/alloc/tests.rs b/library/std/src/sys/alloc/windows/tests.rs similarity index 100% rename from library/std/src/sys/pal/windows/alloc/tests.rs rename to library/std/src/sys/alloc/windows/tests.rs diff --git a/library/std/src/sys/pal/xous/alloc.rs b/library/std/src/sys/alloc/xous.rs similarity index 100% rename from library/std/src/sys/pal/xous/alloc.rs rename to library/std/src/sys/alloc/xous.rs diff --git a/library/std/src/sys/pal/zkvm/alloc.rs b/library/std/src/sys/alloc/zkvm.rs similarity index 94% rename from library/std/src/sys/pal/zkvm/alloc.rs rename to library/std/src/sys/alloc/zkvm.rs index 2fdca223524..a600cfa2220 100644 --- a/library/std/src/sys/pal/zkvm/alloc.rs +++ b/library/std/src/sys/alloc/zkvm.rs @@ -1,5 +1,5 @@ -use super::abi; use crate::alloc::{GlobalAlloc, Layout, System}; +use crate::sys::pal::abi; #[stable(feature = "alloc_system_type", since = "1.28.0")] unsafe impl GlobalAlloc for System { diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index a86b3628f24..1ef17dd530f 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -5,6 +5,7 @@ /// descriptors. mod pal; +mod alloc; mod personality; pub mod anonymous_pipe; diff --git a/library/std/src/sys/os_str/bytes.rs b/library/std/src/sys/os_str/bytes.rs index 0f8bd645352..992767211d0 100644 --- a/library/std/src/sys/os_str/bytes.rs +++ b/library/std/src/sys/os_str/bytes.rs @@ -1,6 +1,9 @@ //! The underlying OsString/OsStr implementation on Unix and many other //! systems: just a `Vec`/`[u8]`. +use core::clone::CloneToUninit; +use core::ptr::addr_of_mut; + use crate::borrow::Cow; use crate::collections::TryReserveError; use crate::fmt::Write; @@ -345,3 +348,13 @@ impl Slice { self.inner.eq_ignore_ascii_case(&other.inner) } } + +#[unstable(feature = "clone_to_uninit", issue = "126799")] +unsafe impl CloneToUninit for Slice { + #[inline] + #[cfg_attr(debug_assertions, track_caller)] + unsafe fn clone_to_uninit(&self, dst: *mut Self) { + // SAFETY: we're just a wrapper around [u8] + unsafe { self.inner.clone_to_uninit(addr_of_mut!((*dst).inner)) } + } +} diff --git a/library/std/src/sys/os_str/wtf8.rs b/library/std/src/sys/os_str/wtf8.rs index ed975ba58b5..433237aa6e7 100644 --- a/library/std/src/sys/os_str/wtf8.rs +++ b/library/std/src/sys/os_str/wtf8.rs @@ -1,5 +1,8 @@ //! The underlying OsString/OsStr implementation on Windows is a //! wrapper around the "WTF-8" encoding; see the `wtf8` module for more. +use core::clone::CloneToUninit; +use core::ptr::addr_of_mut; + use crate::borrow::Cow; use crate::collections::TryReserveError; use crate::rc::Rc; @@ -268,3 +271,13 @@ impl Slice { self.inner.eq_ignore_ascii_case(&other.inner) } } + +#[unstable(feature = "clone_to_uninit", issue = "126799")] +unsafe impl CloneToUninit for Slice { + #[inline] + #[cfg_attr(debug_assertions, track_caller)] + unsafe fn clone_to_uninit(&self, dst: *mut Self) { + // SAFETY: we're just a wrapper around Wtf8 + unsafe { self.inner.clone_to_uninit(addr_of_mut!((*dst).inner)) } + } +} diff --git a/library/std/src/sys/pal/common/mod.rs b/library/std/src/sys/pal/common/mod.rs index 29fc0835d76..9af4dee401c 100644 --- a/library/std/src/sys/pal/common/mod.rs +++ b/library/std/src/sys/pal/common/mod.rs @@ -10,7 +10,6 @@ #![allow(dead_code)] -pub mod alloc; pub mod small_c_string; #[cfg(test)] diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs index ef406b9ec7f..1f2e5d9469f 100644 --- a/library/std/src/sys/pal/hermit/mod.rs +++ b/library/std/src/sys/pal/hermit/mod.rs @@ -18,7 +18,6 @@ use crate::os::raw::c_char; -pub mod alloc; pub mod args; pub mod env; pub mod fd; diff --git a/library/std/src/sys/pal/hermit/thread.rs b/library/std/src/sys/pal/hermit/thread.rs index 6321f92e3d9..4c0c0919f47 100644 --- a/library/std/src/sys/pal/hermit/thread.rs +++ b/library/std/src/sys/pal/hermit/thread.rs @@ -77,8 +77,11 @@ impl Thread { #[inline] pub fn sleep(dur: Duration) { + let micros = dur.as_micros() + if dur.subsec_nanos() % 1_000 > 0 { 1 } else { 0 }; + let micros = u64::try_from(micros).unwrap_or(u64::MAX); + unsafe { - hermit_abi::usleep(dur.as_micros() as u64); + hermit_abi::usleep(micros); } } diff --git a/library/std/src/sys/pal/sgx/mod.rs b/library/std/src/sys/pal/sgx/mod.rs index 851ab9b9f97..8d29b2ec619 100644 --- a/library/std/src/sys/pal/sgx/mod.rs +++ b/library/std/src/sys/pal/sgx/mod.rs @@ -9,7 +9,6 @@ use crate::io::ErrorKind; use crate::sync::atomic::{AtomicBool, Ordering}; pub mod abi; -pub mod alloc; pub mod args; pub mod env; pub mod fd; diff --git a/library/std/src/sys/pal/solid/fs.rs b/library/std/src/sys/pal/solid/fs.rs index 8179ec8821a..591be66fcb4 100644 --- a/library/std/src/sys/pal/solid/fs.rs +++ b/library/std/src/sys/pal/solid/fs.rs @@ -10,6 +10,7 @@ use crate::sync::Arc; use crate::sys::time::SystemTime; use crate::sys::unsupported; pub use crate::sys_common::fs::exists; +use crate::sys_common::ignore_notfound; /// A file descriptor. #[derive(Clone, Copy)] @@ -527,15 +528,23 @@ pub fn rmdir(p: &Path) -> io::Result<()> { pub fn remove_dir_all(path: &Path) -> io::Result<()> { for child in readdir(path)? { - let child = child?; - let child_type = child.file_type()?; - if child_type.is_dir() { - remove_dir_all(&child.path())?; - } else { - unlink(&child.path())?; + let result: io::Result<()> = try { + let child = child?; + let child_type = child.file_type()?; + if child_type.is_dir() { + remove_dir_all(&child.path())?; + } else { + unlink(&child.path())?; + } + }; + // ignore internal NotFound errors + if let Err(err) = result + && err.kind() != io::ErrorKind::NotFound + { + return result; } } - rmdir(path) + ignore_notfound(rmdir(path)) } pub fn readlink(p: &Path) -> io::Result { diff --git a/library/std/src/sys/pal/solid/mod.rs b/library/std/src/sys/pal/solid/mod.rs index cbf34286878..6ebcf5b7c48 100644 --- a/library/std/src/sys/pal/solid/mod.rs +++ b/library/std/src/sys/pal/solid/mod.rs @@ -16,7 +16,6 @@ pub mod itron { use super::unsupported; } -pub mod alloc; #[path = "../unsupported/args.rs"] pub mod args; pub mod env; diff --git a/library/std/src/sys/pal/teeos/alloc.rs b/library/std/src/sys/pal/teeos/alloc.rs deleted file mode 100644 index b280d1dd76f..00000000000 --- a/library/std/src/sys/pal/teeos/alloc.rs +++ /dev/null @@ -1,57 +0,0 @@ -use crate::alloc::{GlobalAlloc, Layout, System}; -use crate::ptr; -use crate::sys::common::alloc::{realloc_fallback, MIN_ALIGN}; - -#[stable(feature = "alloc_system_type", since = "1.28.0")] -unsafe impl GlobalAlloc for System { - #[inline] - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - // jemalloc provides alignment less than MIN_ALIGN for small allocations. - // So only rely on MIN_ALIGN if size >= align. - // Also see and - // . - if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { - unsafe { libc::malloc(layout.size()) as *mut u8 } - } else { - unsafe { aligned_malloc(&layout) } - } - } - - #[inline] - unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { - // See the comment above in `alloc` for why this check looks the way it does. - if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { - unsafe { libc::calloc(layout.size(), 1) as *mut u8 } - } else { - let ptr = unsafe { self.alloc(layout) }; - if !ptr.is_null() { - unsafe { ptr::write_bytes(ptr, 0, layout.size()) }; - } - ptr - } - } - - #[inline] - unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) { - unsafe { libc::free(ptr as *mut libc::c_void) } - } - - #[inline] - unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { - if layout.align() <= MIN_ALIGN && layout.align() <= new_size { - unsafe { libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8 } - } else { - unsafe { realloc_fallback(self, ptr, layout, new_size) } - } - } -} - -#[inline] -unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { - let mut out = ptr::null_mut(); - // posix_memalign requires that the alignment be a multiple of `sizeof(void*)`. - // Since these are all powers of 2, we can just use max. - let align = layout.align().max(crate::mem::size_of::()); - let ret = unsafe { libc::posix_memalign(&mut out, align, layout.size()) }; - if ret != 0 { ptr::null_mut() } else { out as *mut u8 } -} diff --git a/library/std/src/sys/pal/teeos/mod.rs b/library/std/src/sys/pal/teeos/mod.rs index adefd1bb42c..00e38604240 100644 --- a/library/std/src/sys/pal/teeos/mod.rs +++ b/library/std/src/sys/pal/teeos/mod.rs @@ -8,7 +8,6 @@ pub use self::rand::hashmap_random_keys; -pub mod alloc; #[path = "../unsupported/args.rs"] pub mod args; #[path = "../unsupported/env.rs"] diff --git a/library/std/src/sys/pal/uefi/mod.rs b/library/std/src/sys/pal/uefi/mod.rs index 851bcea4c1e..ac22f4ded88 100644 --- a/library/std/src/sys/pal/uefi/mod.rs +++ b/library/std/src/sys/pal/uefi/mod.rs @@ -13,11 +13,11 @@ //! [`OsString`]: crate::ffi::OsString #![forbid(unsafe_op_in_unsafe_fn)] -pub mod alloc; pub mod args; pub mod env; #[path = "../unsupported/fs.rs"] pub mod fs; +pub mod helpers; #[path = "../unsupported/io.rs"] pub mod io; #[path = "../unsupported/net.rs"] @@ -30,8 +30,6 @@ pub mod stdio; pub mod thread; pub mod time; -mod helpers; - #[cfg(test)] mod tests; diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs index be13e1ae9b3..fc9d7e98883 100644 --- a/library/std/src/sys/pal/unix/fs.rs +++ b/library/std/src/sys/pal/unix/fs.rs @@ -2002,6 +2002,7 @@ mod remove_dir_impl { use crate::path::{Path, PathBuf}; use crate::sys::common::small_c_string::run_path_with_cstr; use crate::sys::{cvt, cvt_r}; + use crate::sys_common::ignore_notfound; pub fn openat_nofollow_dironly(parent_fd: Option, p: &CStr) -> io::Result { let fd = cvt_r(|| unsafe { @@ -2055,6 +2056,16 @@ mod remove_dir_impl { } } + fn is_enoent(result: &io::Result<()>) -> bool { + if let Err(err) = result + && matches!(err.raw_os_error(), Some(libc::ENOENT)) + { + true + } else { + false + } + } + fn remove_dir_all_recursive(parent_fd: Option, path: &CStr) -> io::Result<()> { // try opening as directory let fd = match openat_nofollow_dironly(parent_fd, &path) { @@ -2078,27 +2089,35 @@ mod remove_dir_impl { for child in dir { let child = child?; let child_name = child.name_cstr(); - match is_dir(&child) { - Some(true) => { - remove_dir_all_recursive(Some(fd), child_name)?; - } - Some(false) => { - cvt(unsafe { unlinkat(fd, child_name.as_ptr(), 0) })?; - } - None => { - // POSIX specifies that calling unlink()/unlinkat(..., 0) on a directory can succeed - // if the process has the appropriate privileges. This however can causing orphaned - // directories requiring an fsck e.g. on Solaris and Illumos. So we try recursing - // into it first instead of trying to unlink() it. - remove_dir_all_recursive(Some(fd), child_name)?; + // we need an inner try block, because if one of these + // directories has already been deleted, then we need to + // continue the loop, not return ok. + let result: io::Result<()> = try { + match is_dir(&child) { + Some(true) => { + remove_dir_all_recursive(Some(fd), child_name)?; + } + Some(false) => { + cvt(unsafe { unlinkat(fd, child_name.as_ptr(), 0) })?; + } + None => { + // POSIX specifies that calling unlink()/unlinkat(..., 0) on a directory can succeed + // if the process has the appropriate privileges. This however can causing orphaned + // directories requiring an fsck e.g. on Solaris and Illumos. So we try recursing + // into it first instead of trying to unlink() it. + remove_dir_all_recursive(Some(fd), child_name)?; + } } + }; + if result.is_err() && !is_enoent(&result) { + return result; } } // unlink the directory after removing its contents - cvt(unsafe { + ignore_notfound(cvt(unsafe { unlinkat(parent_fd.unwrap_or(libc::AT_FDCWD), path.as_ptr(), libc::AT_REMOVEDIR) - })?; + }))?; Ok(()) } diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index b62129f4cdd..ba2f58f9c10 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -7,7 +7,6 @@ use crate::io::ErrorKind; #[macro_use] pub mod weak; -pub mod alloc; pub mod args; pub mod env; pub mod fd; @@ -116,7 +115,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { if pfd.revents & libc::POLLNVAL == 0 { continue; } - if open64(c"/dev/null".as_ptr().cast(), libc::O_RDWR, 0) == -1 { + if open64(c"/dev/null".as_ptr(), libc::O_RDWR, 0) == -1 { // If the stream is closed but we failed to reopen it, abort the // process. Otherwise we wouldn't preserve the safety of // operations on the corresponding Rust object Stdin, Stdout, or @@ -147,7 +146,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { use crate::sys::os::errno; for fd in 0..3 { if libc::fcntl(fd, libc::F_GETFD) == -1 && errno() == libc::EBADF { - if open64(c"/dev/null".as_ptr().cast(), libc::O_RDWR, 0) == -1 { + if open64(c"/dev/null".as_ptr(), libc::O_RDWR, 0) == -1 { // If the stream is closed but we failed to reopen it, abort the // process. Otherwise we wouldn't preserve the safety of // operations on the corresponding Rust object Stdin, Stdout, or diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs index 0fa610eebb4..c9dcc5ad97a 100644 --- a/library/std/src/sys/pal/unix/thread.rs +++ b/library/std/src/sys/pal/unix/thread.rs @@ -267,14 +267,32 @@ impl Thread { #[cfg(target_os = "espidf")] pub fn sleep(dur: Duration) { - let mut micros = dur.as_micros(); - unsafe { - while micros > 0 { - let st = if micros > u32::MAX as u128 { u32::MAX } else { micros as u32 }; - libc::usleep(st); + // ESP-IDF does not have `nanosleep`, so we use `usleep` instead. + // As per the documentation of `usleep`, it is expected to support + // sleep times as big as at least up to 1 second. + // + // ESP-IDF does support almost up to `u32::MAX`, but due to a potential integer overflow in its + // `usleep` implementation + // (https://github.com/espressif/esp-idf/blob/d7ca8b94c852052e3bc33292287ef4dd62c9eeb1/components/newlib/time.c#L210), + // we limit the sleep time to the maximum one that would not cause the underlying `usleep` implementation to overflow + // (`portTICK_PERIOD_MS` can be anything between 1 to 1000, and is 10 by default). + const MAX_MICROS: u32 = u32::MAX - 1_000_000 - 1; - micros -= st as u128; + // Add any nanoseconds smaller than a microsecond as an extra microsecond + // so as to comply with the `std::thread::sleep` contract which mandates + // implementations to sleep for _at least_ the provided `dur`. + // We can't overflow `micros` as it is a `u128`, while `Duration` is a pair of + // (`u64` secs, `u32` nanos), where the nanos are strictly smaller than 1 second + // (i.e. < 1_000_000_000) + let mut micros = dur.as_micros() + if dur.subsec_nanos() % 1_000 > 0 { 1 } else { 0 }; + + while micros > 0 { + let st = if micros > MAX_MICROS as u128 { MAX_MICROS } else { micros as u32 }; + unsafe { + libc::usleep(st); } + + micros -= st as u128; } } diff --git a/library/std/src/sys/pal/unsupported/alloc.rs b/library/std/src/sys/pal/unsupported/alloc.rs deleted file mode 100644 index d715ae45401..00000000000 --- a/library/std/src/sys/pal/unsupported/alloc.rs +++ /dev/null @@ -1,23 +0,0 @@ -use crate::alloc::{GlobalAlloc, Layout, System}; -use crate::ptr::null_mut; - -#[stable(feature = "alloc_system_type", since = "1.28.0")] -unsafe impl GlobalAlloc for System { - #[inline] - unsafe fn alloc(&self, _layout: Layout) -> *mut u8 { - null_mut() - } - - #[inline] - unsafe fn alloc_zeroed(&self, _layout: Layout) -> *mut u8 { - null_mut() - } - - #[inline] - unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {} - - #[inline] - unsafe fn realloc(&self, _ptr: *mut u8, _layout: Layout, _new_size: usize) -> *mut u8 { - null_mut() - } -} diff --git a/library/std/src/sys/pal/unsupported/mod.rs b/library/std/src/sys/pal/unsupported/mod.rs index 442e6042ad5..01d516f7568 100644 --- a/library/std/src/sys/pal/unsupported/mod.rs +++ b/library/std/src/sys/pal/unsupported/mod.rs @@ -1,6 +1,5 @@ #![deny(unsafe_op_in_unsafe_fn)] -pub mod alloc; pub mod args; pub mod env; pub mod fs; diff --git a/library/std/src/sys/pal/wasi/args.rs b/library/std/src/sys/pal/wasi/args.rs index 6b6d1b8ff4e..52cfa202af8 100644 --- a/library/std/src/sys/pal/wasi/args.rs +++ b/library/std/src/sys/pal/wasi/args.rs @@ -1,4 +1,4 @@ -#![deny(unsafe_op_in_unsafe_fn)] +#![forbid(unsafe_op_in_unsafe_fn)] use crate::ffi::{CStr, OsStr, OsString}; use crate::os::wasi::ffi::OsStrExt; diff --git a/library/std/src/sys/pal/wasi/env.rs b/library/std/src/sys/pal/wasi/env.rs index 730e356d7fe..8d444982673 100644 --- a/library/std/src/sys/pal/wasi/env.rs +++ b/library/std/src/sys/pal/wasi/env.rs @@ -1,3 +1,5 @@ +#![forbid(unsafe_op_in_unsafe_fn)] + pub mod os { pub const FAMILY: &str = ""; pub const OS: &str = ""; diff --git a/library/std/src/sys/pal/wasi/fd.rs b/library/std/src/sys/pal/wasi/fd.rs index 8966e4b80ad..19b60157e2e 100644 --- a/library/std/src/sys/pal/wasi/fd.rs +++ b/library/std/src/sys/pal/wasi/fd.rs @@ -1,4 +1,4 @@ -#![deny(unsafe_op_in_unsafe_fn)] +#![forbid(unsafe_op_in_unsafe_fn)] #![allow(dead_code)] use super::err2io; diff --git a/library/std/src/sys/pal/wasi/fs.rs b/library/std/src/sys/pal/wasi/fs.rs index 11900886f0b..88b1e543ec7 100644 --- a/library/std/src/sys/pal/wasi/fs.rs +++ b/library/std/src/sys/pal/wasi/fs.rs @@ -1,4 +1,4 @@ -#![deny(unsafe_op_in_unsafe_fn)] +#![forbid(unsafe_op_in_unsafe_fn)] use super::fd::WasiFd; use crate::ffi::{CStr, OsStr, OsString}; @@ -13,7 +13,7 @@ use crate::sys::common::small_c_string::run_path_with_cstr; use crate::sys::time::SystemTime; use crate::sys::unsupported; pub use crate::sys_common::fs::exists; -use crate::sys_common::{AsInner, FromInner, IntoInner}; +use crate::sys_common::{ignore_notfound, AsInner, FromInner, IntoInner}; use crate::{fmt, iter, ptr}; pub struct File { @@ -794,14 +794,22 @@ fn remove_dir_all_recursive(parent: &WasiFd, path: &Path) -> io::Result<()> { io::const_io_error!(io::ErrorKind::Uncategorized, "invalid utf-8 file name found") })?; - if entry.file_type()?.is_dir() { - remove_dir_all_recursive(&entry.inner.dir.fd, path.as_ref())?; - } else { - entry.inner.dir.fd.unlink_file(path)?; + let result: io::Result<()> = try { + if entry.file_type()?.is_dir() { + remove_dir_all_recursive(&entry.inner.dir.fd, path.as_ref())?; + } else { + entry.inner.dir.fd.unlink_file(path)?; + } + }; + // ignore internal NotFound errors + if let Err(err) = &result + && err.kind() != io::ErrorKind::NotFound + { + return result; } } // Once all this directory's contents are deleted it should be safe to // delete the directory tiself. - parent.remove_directory(osstr2str(path.as_ref())?) + ignore_notfound(parent.remove_directory(osstr2str(path.as_ref())?)) } diff --git a/library/std/src/sys/pal/wasi/helpers.rs b/library/std/src/sys/pal/wasi/helpers.rs index 4b770ee23bc..d047bf2fce8 100644 --- a/library/std/src/sys/pal/wasi/helpers.rs +++ b/library/std/src/sys/pal/wasi/helpers.rs @@ -1,3 +1,5 @@ +#![forbid(unsafe_op_in_unsafe_fn)] + use crate::{io as std_io, mem}; #[inline] diff --git a/library/std/src/sys/pal/wasi/io.rs b/library/std/src/sys/pal/wasi/io.rs index 2cd45df88fa..b7c2f03daa0 100644 --- a/library/std/src/sys/pal/wasi/io.rs +++ b/library/std/src/sys/pal/wasi/io.rs @@ -1,4 +1,4 @@ -#![deny(unsafe_op_in_unsafe_fn)] +#![forbid(unsafe_op_in_unsafe_fn)] use crate::marker::PhantomData; use crate::os::fd::{AsFd, AsRawFd}; diff --git a/library/std/src/sys/pal/wasi/mod.rs b/library/std/src/sys/pal/wasi/mod.rs index f4dc3ebd414..8051021a588 100644 --- a/library/std/src/sys/pal/wasi/mod.rs +++ b/library/std/src/sys/pal/wasi/mod.rs @@ -14,8 +14,6 @@ //! compiling for wasm. That way it's a compile time error for something that's //! guaranteed to be a runtime error! -#[path = "../unix/alloc.rs"] -pub mod alloc; pub mod args; pub mod env; pub mod fd; diff --git a/library/std/src/sys/pal/wasi/net.rs b/library/std/src/sys/pal/wasi/net.rs index b4cf94c8781..a6486799828 100644 --- a/library/std/src/sys/pal/wasi/net.rs +++ b/library/std/src/sys/pal/wasi/net.rs @@ -1,4 +1,4 @@ -#![deny(unsafe_op_in_unsafe_fn)] +#![forbid(unsafe_op_in_unsafe_fn)] use super::err2io; use super::fd::WasiFd; diff --git a/library/std/src/sys/pal/wasi/os.rs b/library/std/src/sys/pal/wasi/os.rs index f5b17d9df94..f7701360f5a 100644 --- a/library/std/src/sys/pal/wasi/os.rs +++ b/library/std/src/sys/pal/wasi/os.rs @@ -1,4 +1,4 @@ -#![deny(unsafe_op_in_unsafe_fn)] +#![forbid(unsafe_op_in_unsafe_fn)] use core::slice::memchr; diff --git a/library/std/src/sys/pal/wasi/stdio.rs b/library/std/src/sys/pal/wasi/stdio.rs index 4cc0e4ed5a4..ca49f871e19 100644 --- a/library/std/src/sys/pal/wasi/stdio.rs +++ b/library/std/src/sys/pal/wasi/stdio.rs @@ -1,4 +1,4 @@ -#![deny(unsafe_op_in_unsafe_fn)] +#![forbid(unsafe_op_in_unsafe_fn)] use super::fd::WasiFd; use crate::io::{self, IoSlice, IoSliceMut}; diff --git a/library/std/src/sys/pal/wasi/thread.rs b/library/std/src/sys/pal/wasi/thread.rs index c37acd8dfee..31c9cbd4699 100644 --- a/library/std/src/sys/pal/wasi/thread.rs +++ b/library/std/src/sys/pal/wasi/thread.rs @@ -1,3 +1,5 @@ +#![forbid(unsafe_op_in_unsafe_fn)] + use crate::ffi::CStr; use crate::num::NonZero; use crate::sys::unsupported; @@ -73,13 +75,13 @@ impl Thread { if #[cfg(target_feature = "atomics")] { pub unsafe fn new(stack: usize, p: Box) -> io::Result { let p = Box::into_raw(Box::new(p)); - let mut native: libc::pthread_t = mem::zeroed(); - let mut attr: libc::pthread_attr_t = mem::zeroed(); - assert_eq!(libc::pthread_attr_init(&mut attr), 0); + let mut native: libc::pthread_t = unsafe { mem::zeroed() }; + let mut attr: libc::pthread_attr_t = unsafe { mem::zeroed() }; + assert_eq!(unsafe { libc::pthread_attr_init(&mut attr) }, 0); let stack_size = cmp::max(stack, DEFAULT_MIN_STACK_SIZE); - match libc::pthread_attr_setstacksize(&mut attr, stack_size) { + match unsafe { libc::pthread_attr_setstacksize(&mut attr, stack_size) } { 0 => {} n => { assert_eq!(n, libc::EINVAL); @@ -90,20 +92,20 @@ impl Thread { let page_size = os::page_size(); let stack_size = (stack_size + page_size - 1) & (-(page_size as isize - 1) as usize - 1); - assert_eq!(libc::pthread_attr_setstacksize(&mut attr, stack_size), 0); + assert_eq!(unsafe { libc::pthread_attr_setstacksize(&mut attr, stack_size) }, 0); } }; - let ret = libc::pthread_create(&mut native, &attr, thread_start, p as *mut _); + let ret = unsafe { libc::pthread_create(&mut native, &attr, thread_start, p as *mut _) }; // Note: if the thread creation fails and this assert fails, then p will // be leaked. However, an alternative design could cause double-free // which is clearly worse. - assert_eq!(libc::pthread_attr_destroy(&mut attr), 0); + assert_eq!(unsafe {libc::pthread_attr_destroy(&mut attr) }, 0); return if ret != 0 { // The thread failed to start and as a result p was not consumed. Therefore, it is // safe to reconstruct the box so that it gets deallocated. - drop(Box::from_raw(p)); + unsafe { drop(Box::from_raw(p)); } Err(io::Error::from_raw_os_error(ret)) } else { Ok(Thread { id: native }) diff --git a/library/std/src/sys/pal/wasi/time.rs b/library/std/src/sys/pal/wasi/time.rs index 016b06efbdc..0d8d0b59ac1 100644 --- a/library/std/src/sys/pal/wasi/time.rs +++ b/library/std/src/sys/pal/wasi/time.rs @@ -1,4 +1,4 @@ -#![deny(unsafe_op_in_unsafe_fn)] +#![forbid(unsafe_op_in_unsafe_fn)] use crate::time::Duration; diff --git a/library/std/src/sys/pal/wasip2/mod.rs b/library/std/src/sys/pal/wasip2/mod.rs index f20630e10cf..546fadbe501 100644 --- a/library/std/src/sys/pal/wasip2/mod.rs +++ b/library/std/src/sys/pal/wasip2/mod.rs @@ -6,8 +6,6 @@ //! To begin with, this target mirrors the wasi target 1 to 1, but over //! time this will change significantly. -#[path = "../unix/alloc.rs"] -pub mod alloc; #[path = "../wasi/args.rs"] pub mod args; #[path = "../wasi/env.rs"] diff --git a/library/std/src/sys/pal/wasm/mod.rs b/library/std/src/sys/pal/wasm/mod.rs index 4c34859e918..8141bfac49a 100644 --- a/library/std/src/sys/pal/wasm/mod.rs +++ b/library/std/src/sys/pal/wasm/mod.rs @@ -16,7 +16,6 @@ #![deny(unsafe_op_in_unsafe_fn)] -pub mod alloc; #[path = "../unsupported/args.rs"] pub mod args; pub mod env; diff --git a/library/std/src/sys/pal/windows/c.rs b/library/std/src/sys/pal/windows/c.rs index 08b75186aef..b888eb7d95c 100644 --- a/library/std/src/sys/pal/windows/c.rs +++ b/library/std/src/sys/pal/windows/c.rs @@ -8,8 +8,6 @@ use core::ffi::{c_uint, c_ulong, c_ushort, c_void, CStr}; use core::{mem, ptr}; -pub(super) mod windows_targets; - mod windows_sys; pub use windows_sys::*; @@ -111,19 +109,15 @@ if #[cfg(not(target_vendor = "uwp"))] { } // Use raw-dylib to import ProcessPrng as we can't rely on there being an import library. -cfg_if::cfg_if! { -if #[cfg(not(target_vendor = "win7"))] { - #[cfg(target_arch = "x86")] - #[link(name = "bcryptprimitives", kind = "raw-dylib", import_name_type = "undecorated")] - extern "system" { - pub fn ProcessPrng(pbdata: *mut u8, cbdata: usize) -> BOOL; - } - #[cfg(not(target_arch = "x86"))] - #[link(name = "bcryptprimitives", kind = "raw-dylib")] - extern "system" { - pub fn ProcessPrng(pbdata: *mut u8, cbdata: usize) -> BOOL; - } -}} +#[cfg(not(target_vendor = "win7"))] +#[cfg_attr( + target_arch = "x86", + link(name = "bcryptprimitives", kind = "raw-dylib", import_name_type = "undecorated") +)] +#[cfg_attr(not(target_arch = "x86"), link(name = "bcryptprimitives", kind = "raw-dylib"))] +extern "system" { + pub fn ProcessPrng(pbdata: *mut u8, cbdata: usize) -> BOOL; +} // Functions that aren't available on every version of Windows that we support, // but we still use them and just provide some form of a fallback implementation. diff --git a/library/std/src/sys/pal/windows/c/windows_sys.rs b/library/std/src/sys/pal/windows/c/windows_sys.rs index 9f22f548195..529c96a0e1e 100644 --- a/library/std/src/sys/pal/windows/c/windows_sys.rs +++ b/library/std/src/sys/pal/windows/c/windows_sys.rs @@ -3317,4 +3317,3 @@ pub struct WSADATA { #[cfg(target_arch = "arm")] pub enum CONTEXT {} // ignore-tidy-filelength -use super::windows_targets; diff --git a/library/std/src/sys/pal/windows/fs.rs b/library/std/src/sys/pal/windows/fs.rs index d99d4931de4..2134152ea93 100644 --- a/library/std/src/sys/pal/windows/fs.rs +++ b/library/std/src/sys/pal/windows/fs.rs @@ -14,7 +14,7 @@ use crate::sys::handle::Handle; use crate::sys::path::maybe_verbatim; use crate::sys::time::SystemTime; use crate::sys::{c, cvt, Align8}; -use crate::sys_common::{AsInner, FromInner, IntoInner}; +use crate::sys_common::{ignore_notfound, AsInner, FromInner, IntoInner}; use crate::{fmt, ptr, slice, thread}; pub struct File { @@ -1160,7 +1160,7 @@ pub fn remove_dir_all(path: &Path) -> io::Result<()> { return Err(io::Error::from_raw_os_error(c::ERROR_DIRECTORY as _)); } - match remove_dir_all_iterative(&file, File::posix_delete) { + match ignore_notfound(remove_dir_all_iterative(&file, File::posix_delete)) { Err(e) => { if let Some(code) = e.raw_os_error() { match code as u32 { diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs index 6ed77fbc3d4..272fadd9150 100644 --- a/library/std/src/sys/pal/windows/mod.rs +++ b/library/std/src/sys/pal/windows/mod.rs @@ -15,7 +15,6 @@ pub mod compat; mod api; -pub mod alloc; pub mod args; pub mod c; pub mod env; diff --git a/library/std/src/sys/pal/xous/mod.rs b/library/std/src/sys/pal/xous/mod.rs index 961d45c5e83..b211e94db65 100644 --- a/library/std/src/sys/pal/xous/mod.rs +++ b/library/std/src/sys/pal/xous/mod.rs @@ -1,6 +1,5 @@ #![forbid(unsafe_op_in_unsafe_fn)] -pub mod alloc; #[path = "../unsupported/args.rs"] pub mod args; #[path = "../unsupported/env.rs"] diff --git a/library/std/src/sys/pal/zkvm/mod.rs b/library/std/src/sys/pal/zkvm/mod.rs index 651f25d6623..20fdb7468a4 100644 --- a/library/std/src/sys/pal/zkvm/mod.rs +++ b/library/std/src/sys/pal/zkvm/mod.rs @@ -10,7 +10,7 @@ const WORD_SIZE: usize = core::mem::size_of::(); -pub mod alloc; +pub mod abi; #[path = "../zkvm/args.rs"] pub mod args; pub mod env; @@ -26,13 +26,10 @@ pub mod pipe; #[path = "../unsupported/process.rs"] pub mod process; pub mod stdio; -#[path = "../unsupported/time.rs"] -pub mod time; - #[path = "../unsupported/thread.rs"] pub mod thread; - -mod abi; +#[path = "../unsupported/time.rs"] +pub mod time; use crate::io as std_io; diff --git a/library/std/src/sys_common/fs.rs b/library/std/src/sys_common/fs.rs index acb6713cf1b..a25a7244660 100644 --- a/library/std/src/sys_common/fs.rs +++ b/library/std/src/sys_common/fs.rs @@ -3,6 +3,7 @@ use crate::fs; use crate::io::{self, Error, ErrorKind}; use crate::path::Path; +use crate::sys_common::ignore_notfound; pub(crate) const NOT_FILE_ERROR: Error = io::const_io_error!( ErrorKind::InvalidInput, @@ -32,14 +33,22 @@ pub fn remove_dir_all(path: &Path) -> io::Result<()> { fn remove_dir_all_recursive(path: &Path) -> io::Result<()> { for child in fs::read_dir(path)? { - let child = child?; - if child.file_type()?.is_dir() { - remove_dir_all_recursive(&child.path())?; - } else { - fs::remove_file(&child.path())?; + let result: io::Result<()> = try { + let child = child?; + if child.file_type()?.is_dir() { + remove_dir_all_recursive(&child.path())?; + } else { + fs::remove_file(&child.path())?; + } + }; + // ignore internal NotFound errors to prevent race conditions + if let Err(err) = &result + && err.kind() != io::ErrorKind::NotFound + { + return result; } } - fs::remove_dir(path) + ignore_notfound(fs::remove_dir(path)) } pub fn exists(path: &Path) -> io::Result { diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs index 60ee405ecaa..1c884f107be 100644 --- a/library/std/src/sys_common/mod.rs +++ b/library/std/src/sys_common/mod.rs @@ -80,3 +80,11 @@ pub fn mul_div_u64(value: u64, numer: u64, denom: u64) -> u64 { // r < denom, so (denom*numer) is the upper bound of (r*numer) q * numer + r * numer / denom } + +pub fn ignore_notfound(result: crate::io::Result) -> crate::io::Result<()> { + match result { + Err(err) if err.kind() == crate::io::ErrorKind::NotFound => Ok(()), + Ok(_) => Ok(()), + Err(err) => Err(err), + } +} diff --git a/library/std/src/sys_common/wtf8.rs b/library/std/src/sys_common/wtf8.rs index 277c9506feb..063451ad54e 100644 --- a/library/std/src/sys_common/wtf8.rs +++ b/library/std/src/sys_common/wtf8.rs @@ -19,12 +19,14 @@ mod tests; use core::char::{encode_utf16_raw, encode_utf8_raw}; +use core::clone::CloneToUninit; use core::str::next_code_point; use crate::borrow::Cow; use crate::collections::TryReserveError; use crate::hash::{Hash, Hasher}; use crate::iter::FusedIterator; +use crate::ptr::addr_of_mut; use crate::rc::Rc; use crate::sync::Arc; use crate::sys_common::AsInner; @@ -1046,3 +1048,13 @@ impl Hash for Wtf8 { 0xfeu8.hash(state) } } + +#[unstable(feature = "clone_to_uninit", issue = "126799")] +unsafe impl CloneToUninit for Wtf8 { + #[inline] + #[cfg_attr(debug_assertions, track_caller)] + unsafe fn clone_to_uninit(&self, dst: *mut Self) { + // SAFETY: we're just a wrapper around [u8] + unsafe { self.bytes.clone_to_uninit(addr_of_mut!((*dst).bytes)) } + } +} diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 88b31cd78a6..e29c28f3c7e 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -412,7 +412,6 @@ impl Builder { /// # Examples /// /// ``` - /// #![feature(thread_spawn_unchecked)] /// use std::thread; /// /// let builder = thread::Builder::new(); @@ -433,7 +432,7 @@ impl Builder { /// ``` /// /// [`io::Result`]: crate::io::Result - #[unstable(feature = "thread_spawn_unchecked", issue = "55132")] + #[stable(feature = "thread_spawn_unchecked", since = "CURRENT_RUSTC_VERSION")] pub unsafe fn spawn_unchecked(self, f: F) -> io::Result> where F: FnOnce() -> T, diff --git a/library/std/tests/run-time-detect.rs b/library/std/tests/run-time-detect.rs index 69486705656..dcd5cd7f6b9 100644 --- a/library/std/tests/run-time-detect.rs +++ b/library/std/tests/run-time-detect.rs @@ -4,6 +4,10 @@ all(target_arch = "arm", any(target_os = "linux", target_os = "android")), feature(stdarch_arm_feature_detection) )] +#![cfg_attr( + all(target_arch = "aarch64", any(target_os = "linux", target_os = "android")), + feature(stdarch_aarch64_feature_detection) +)] #![cfg_attr( all(target_arch = "powerpc", target_os = "linux"), feature(stdarch_powerpc_feature_detection) @@ -36,21 +40,34 @@ fn aarch64_linux() { println!("bf16: {}", is_aarch64_feature_detected!("bf16")); println!("bti: {}", is_aarch64_feature_detected!("bti")); println!("crc: {}", is_aarch64_feature_detected!("crc")); + println!("cssc: {}", is_aarch64_feature_detected!("cssc")); println!("dit: {}", is_aarch64_feature_detected!("dit")); println!("dotprod: {}", is_aarch64_feature_detected!("dotprod")); println!("dpb2: {}", is_aarch64_feature_detected!("dpb2")); println!("dpb: {}", is_aarch64_feature_detected!("dpb")); + println!("ecv: {}", is_aarch64_feature_detected!("ecv")); println!("f32mm: {}", is_aarch64_feature_detected!("f32mm")); println!("f64mm: {}", is_aarch64_feature_detected!("f64mm")); + println!("faminmax: {}", is_aarch64_feature_detected!("faminmax")); println!("fcma: {}", is_aarch64_feature_detected!("fcma")); println!("fhm: {}", is_aarch64_feature_detected!("fhm")); + println!("flagm2: {}", is_aarch64_feature_detected!("flagm2")); println!("flagm: {}", is_aarch64_feature_detected!("flagm")); println!("fp16: {}", is_aarch64_feature_detected!("fp16")); + println!("fp8: {}", is_aarch64_feature_detected!("fp8")); + println!("fp8dot2: {}", is_aarch64_feature_detected!("fp8dot2")); + println!("fp8dot4: {}", is_aarch64_feature_detected!("fp8dot4")); + println!("fp8fma: {}", is_aarch64_feature_detected!("fp8fma")); + println!("fpmr: {}", is_aarch64_feature_detected!("fpmr")); println!("frintts: {}", is_aarch64_feature_detected!("frintts")); + println!("hbc: {}", is_aarch64_feature_detected!("hbc")); println!("i8mm: {}", is_aarch64_feature_detected!("i8mm")); println!("jsconv: {}", is_aarch64_feature_detected!("jsconv")); + println!("lse128: {}", is_aarch64_feature_detected!("lse128")); println!("lse2: {}", is_aarch64_feature_detected!("lse2")); println!("lse: {}", is_aarch64_feature_detected!("lse")); + println!("lut: {}", is_aarch64_feature_detected!("lut")); + println!("mops: {}", is_aarch64_feature_detected!("mops")); println!("mte: {}", is_aarch64_feature_detected!("mte")); println!("neon: {}", is_aarch64_feature_detected!("neon")); println!("paca: {}", is_aarch64_feature_detected!("paca")); @@ -58,20 +75,37 @@ fn aarch64_linux() { println!("pmull: {}", is_aarch64_feature_detected!("pmull")); println!("rand: {}", is_aarch64_feature_detected!("rand")); println!("rcpc2: {}", is_aarch64_feature_detected!("rcpc2")); + println!("rcpc3: {}", is_aarch64_feature_detected!("rcpc3")); println!("rcpc: {}", is_aarch64_feature_detected!("rcpc")); println!("rdm: {}", is_aarch64_feature_detected!("rdm")); println!("sb: {}", is_aarch64_feature_detected!("sb")); println!("sha2: {}", is_aarch64_feature_detected!("sha2")); println!("sha3: {}", is_aarch64_feature_detected!("sha3")); println!("sm4: {}", is_aarch64_feature_detected!("sm4")); + println!("sme-f16f16: {}", is_aarch64_feature_detected!("sme-f16f16")); + println!("sme-f64f64: {}", is_aarch64_feature_detected!("sme-f64f64")); + println!("sme-f8f16: {}", is_aarch64_feature_detected!("sme-f8f16")); + println!("sme-f8f32: {}", is_aarch64_feature_detected!("sme-f8f32")); + println!("sme-fa64: {}", is_aarch64_feature_detected!("sme-fa64")); + println!("sme-i16i64: {}", is_aarch64_feature_detected!("sme-i16i64")); + println!("sme-lutv2: {}", is_aarch64_feature_detected!("sme-lutv2")); + println!("sme2: {}", is_aarch64_feature_detected!("sme2")); + println!("sme2p1: {}", is_aarch64_feature_detected!("sme2p1")); + println!("sme: {}", is_aarch64_feature_detected!("sme")); println!("ssbs: {}", is_aarch64_feature_detected!("ssbs")); + println!("ssve-fp8dot2: {}", is_aarch64_feature_detected!("ssve-fp8dot2")); + println!("ssve-fp8dot4: {}", is_aarch64_feature_detected!("ssve-fp8dot4")); + println!("ssve-fp8fma: {}", is_aarch64_feature_detected!("ssve-fp8fma")); + println!("sve-b16b16: {}", is_aarch64_feature_detected!("sve-b16b16")); println!("sve2-aes: {}", is_aarch64_feature_detected!("sve2-aes")); println!("sve2-bitperm: {}", is_aarch64_feature_detected!("sve2-bitperm")); println!("sve2-sha3: {}", is_aarch64_feature_detected!("sve2-sha3")); println!("sve2-sm4: {}", is_aarch64_feature_detected!("sve2-sm4")); println!("sve2: {}", is_aarch64_feature_detected!("sve2")); + println!("sve2p1: {}", is_aarch64_feature_detected!("sve2p1")); println!("sve: {}", is_aarch64_feature_detected!("sve")); println!("tme: {}", is_aarch64_feature_detected!("tme")); + println!("wfxt: {}", is_aarch64_feature_detected!("wfxt")); // tidy-alphabetical-end } diff --git a/library/stdarch b/library/stdarch index 47b929ddc52..d9466edb4c5 160000 --- a/library/stdarch +++ b/library/stdarch @@ -1 +1 @@ -Subproject commit 47b929ddc521a78b0f699ba8d5c274d28593448a +Subproject commit d9466edb4c53cece8686ee6e17b028436ddf4151 diff --git a/library/test/src/types.rs b/library/test/src/types.rs index c3be3466cb9..802cab989c6 100644 --- a/library/test/src/types.rs +++ b/library/test/src/types.rs @@ -250,3 +250,37 @@ pub struct TestDescAndFn { pub desc: TestDesc, pub testfn: TestFn, } + +impl TestDescAndFn { + pub const fn new_doctest( + test_name: &'static str, + ignore: bool, + source_file: &'static str, + start_line: usize, + no_run: bool, + should_panic: bool, + testfn: TestFn, + ) -> Self { + Self { + desc: TestDesc { + name: StaticTestName(test_name), + ignore, + ignore_message: None, + source_file, + start_line, + start_col: 0, + end_line: 0, + end_col: 0, + compile_fail: false, + no_run, + should_panic: if should_panic { + options::ShouldPanic::Yes + } else { + options::ShouldPanic::No + }, + test_type: TestType::DocTest, + }, + testfn, + } + } +} diff --git a/library/windows_targets/Cargo.toml b/library/windows_targets/Cargo.toml new file mode 100644 index 00000000000..94d7c821064 --- /dev/null +++ b/library/windows_targets/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "windows-targets" +description = "A drop-in replacement for the real windows-targets crate for use in std only." +version = "0.0.0" +edition = "2021" + +[features] +# Enable using raw-dylib for Windows imports. +# This will eventually be the default. +windows_raw_dylib = [] diff --git a/library/std/src/sys/pal/windows/c/windows_targets.rs b/library/windows_targets/src/lib.rs similarity index 95% rename from library/std/src/sys/pal/windows/c/windows_targets.rs rename to library/windows_targets/src/lib.rs index 252bceb7094..1965b6cf4ce 100644 --- a/library/std/src/sys/pal/windows/c/windows_targets.rs +++ b/library/windows_targets/src/lib.rs @@ -2,6 +2,10 @@ //! //! This is a simple wrapper around an `extern` block with a `#[link]` attribute. //! It's very roughly equivalent to the windows-targets crate. +#![no_std] +#![no_core] +#![feature(decl_macro)] +#![feature(no_core)] #[cfg(feature = "windows_raw_dylib")] pub macro link { diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index 60453764d82..357c6175152 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -4,30 +4,24 @@ version = 3 [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "anstyle" -version = "1.0.4" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "bitflags" -version = "1.3.2" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "block-buffer" @@ -71,9 +65,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc" +checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" dependencies = [ "memchr", "regex-automata", @@ -102,9 +96,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.4.13" +version = "4.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52bdc885e4cacc7f7c9eedc1ef6da641603180c783c41a15c264944deeaab642" +checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" dependencies = [ "clap_builder", "clap_derive", @@ -112,9 +106,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.12" +version = "4.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb7fb5e4e979aec3be7791562fcba452f94ad85e954da024396433e0e25a79e9" +checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" dependencies = [ "anstyle", "clap_lex", @@ -122,18 +116,18 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.4.6" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97aeaa95557bd02f23fbb662f981670c3d20c5a26e69f7354b28f57092437fcd" +checksum = "1ee158892bd7ce77aa15c208abbdb73e155d191c287a659b57abd5adb92feb03" dependencies = [ "clap", ] [[package]] name = "clap_derive" -version = "4.4.7" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" dependencies = [ "heck", "proc-macro2", @@ -143,9 +137,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.6.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "cmake" @@ -158,15 +152,15 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" dependencies = [ "libc", ] @@ -224,12 +218,12 @@ dependencies = [ [[package]] name = "errno" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -240,19 +234,19 @@ checksum = "7e5768da2206272c81ef0b5e951a41862938a6070da63bcea197899942d3b947" dependencies = [ "cfg-if", "rustix", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "filetime" -version = "0.2.23" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" +checksum = "bf401df4a4e3872c4fe8151134cf483738e74b67fc934d6532c882b3d24a4550" dependencies = [ "cfg-if", "libc", - "redox_syscall", - "windows-sys", + "libredox", + "windows-sys 0.59.0", ] [[package]] @@ -280,9 +274,9 @@ dependencies = [ [[package]] name = "heck" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "home" @@ -290,14 +284,14 @@ version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" dependencies = [ - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "ignore" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "747ad1b4ae841a78e8aba0d63adbfbeaea26b517b63705d47856b73015d27060" +checksum = "b46810df39e66e925525d6e38ce1e7f6e1d208f72dc39757880fcb66e2c58af1" dependencies = [ "crossbeam-deque", "globset", @@ -311,9 +305,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "junction" @@ -322,26 +316,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c9c415a9b7b1e86cd5738f39d34c9e78c765da7fb1756dbd7d31b3b0d2e7afa" dependencies = [ "scopeguard", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "libc" -version = "0.2.155" +version = "0.2.157" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "374af5f94e54fa97cf75e945cce8a6b201e88a1a07e688b47dfd2a59c66dbd86" + +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags", + "libc", + "redox_syscall", +] [[package]] name = "linux-raw-sys" -version = "0.4.12" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "log" -version = "0.4.20" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "lzma-sys" @@ -356,9 +361,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "ntapi" @@ -371,9 +376,9 @@ dependencies = [ [[package]] name = "object" -version = "0.32.2" +version = "0.36.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" dependencies = [ "memchr", ] @@ -390,9 +395,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "pretty_assertions" @@ -406,36 +411,36 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.76" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" dependencies = [ - "bitflags 1.3.2", + "bitflags", ] [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", @@ -444,28 +449,28 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "rustix" -version = "0.38.28" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.4.1", + "bitflags", "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "ryu" -version = "1.0.16" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" @@ -484,24 +489,24 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.195" +version = "1.0.208" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" +checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.195" +version = "1.0.208" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" +checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" dependencies = [ "proc-macro2", "quote", @@ -510,11 +515,12 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.111" +version = "1.0.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" +checksum = "83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31ed" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] @@ -532,9 +538,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.48" +version = "2.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" dependencies = [ "proc-macro2", "quote", @@ -556,9 +562,9 @@ dependencies = [ [[package]] name = "tar" -version = "0.4.40" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" +checksum = "cb797dad5fb5b76fcf519e702f4a589483b5ef06567f160c392832c1f5e44909" dependencies = [ "filetime", "libc", @@ -567,9 +573,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] @@ -597,15 +603,15 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "walkdir" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -629,11 +635,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "winapi", + "windows-sys 0.59.0", ] [[package]] @@ -723,6 +729,15 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-targets" version = "0.52.6" @@ -789,9 +804,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "xattr" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "914566e6413e7fa959cc394fb30e563ba80f3541fbd40816d4c05a0fc3f2a0f1" +checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" dependencies = [ "libc", "linux-raw-sys", diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 84262c115b1..07f7444aaff 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -47,7 +47,7 @@ fd-lock = "4.0" home = "0.5" ignore = "0.4" libc = "0.2" -object = { version = "0.32", default-features = false, features = ["archive", "coff", "read_core", "unaligned"] } +object = { version = "0.36.3", default-features = false, features = ["archive", "coff", "read_core", "unaligned"] } opener = "0.5" semver = "1.0" serde = "1.0" diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 4e8e0fd2532..71f69e03a9f 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -79,6 +79,11 @@ def get(base, url, path, checksums, verbose=False): eprint("removing", temp_path) os.unlink(temp_path) +def curl_version(): + m = re.match(bytes("^curl ([0-9]+)\\.([0-9]+)", "utf8"), require(["curl", "-V"])) + if m is None: + return (0, 0) + return (int(m[1]), int(m[2])) def download(path, url, probably_big, verbose): for _ in range(4): @@ -107,11 +112,15 @@ def _download(path, url, probably_big, verbose, exception): # If curl is not present on Win32, we should not sys.exit # but raise `CalledProcessError` or `OSError` instead require(["curl", "--version"], exception=platform_is_win32()) - run(["curl", option, + extra_flags = [] + if curl_version() > (7, 70): + extra_flags = [ "--retry-all-errors" ] + run(["curl", option] + extra_flags + [ "-L", # Follow redirect. "-y", "30", "-Y", "10", # timeout if speed is < 10 bytes/sec for > 30 seconds "--connect-timeout", "30", # timeout if cannot connect within 30 seconds "-o", path, + "--continue-at", "-", "--retry", "3", "-SRf", url], verbose=verbose, exception=True, # Will raise RuntimeError on failure @@ -533,9 +542,13 @@ class RustBuild(object): bin_root = self.bin_root() key = self.stage0_compiler.date - if self.rustc().startswith(bin_root) and \ - (not os.path.exists(self.rustc()) or - self.program_out_of_date(self.rustc_stamp(), key)): + is_outdated = self.program_out_of_date(self.rustc_stamp(), key) + need_rustc = self.rustc().startswith(bin_root) and (not os.path.exists(self.rustc()) \ + or is_outdated) + need_cargo = self.cargo().startswith(bin_root) and (not os.path.exists(self.cargo()) \ + or is_outdated) + + if need_rustc or need_cargo: if os.path.exists(bin_root): # HACK: On Windows, we can't delete rust-analyzer-proc-macro-server while it's # running. Kill it. @@ -556,7 +569,6 @@ class RustBuild(object): run_powershell([script]) shutil.rmtree(bin_root) - key = self.stage0_compiler.date cache_dst = (self.get_toml('bootstrap-cache-path', 'build') or os.path.join(self.build_dir, "cache")) @@ -568,11 +580,16 @@ class RustBuild(object): toolchain_suffix = "{}-{}{}".format(rustc_channel, self.build, tarball_suffix) - tarballs_to_download = [ - ("rust-std-{}".format(toolchain_suffix), "rust-std-{}".format(self.build)), - ("rustc-{}".format(toolchain_suffix), "rustc"), - ("cargo-{}".format(toolchain_suffix), "cargo"), - ] + tarballs_to_download = [] + + if need_rustc: + tarballs_to_download.append( + ("rust-std-{}".format(toolchain_suffix), "rust-std-{}".format(self.build)) + ) + tarballs_to_download.append(("rustc-{}".format(toolchain_suffix), "rustc")) + + if need_cargo: + tarballs_to_download.append(("cargo-{}".format(toolchain_suffix), "cargo")) tarballs_download_info = [ DownloadInfo( diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp index 11316004412..90901530501 100644 --- a/src/bootstrap/download-ci-llvm-stamp +++ b/src/bootstrap/download-ci-llvm-stamp @@ -1,4 +1,4 @@ Change this file to make users of the `download-ci-llvm` configuration download a new version of LLVM from CI, even if the LLVM submodule hasn’t changed. -Last change is for: https://github.com/rust-lang/rust/pull/125642 +Last change is for: https://github.com/rust-lang/rust/pull/129116 diff --git a/src/bootstrap/src/bin/rustdoc.rs b/src/bootstrap/src/bin/rustdoc.rs index ba6b0c2dbda..a338b9c8080 100644 --- a/src/bootstrap/src/bin/rustdoc.rs +++ b/src/bootstrap/src/bin/rustdoc.rs @@ -59,8 +59,6 @@ fn main() { if stage == "0" { cmd.arg("--cfg=bootstrap"); } - cmd.arg("-Zunstable-options"); - cmd.arg("--check-cfg=cfg(bootstrap)"); maybe_dump(format!("stage{stage}-rustdoc"), &cmd); diff --git a/src/bootstrap/src/core/build_steps/clippy.rs b/src/bootstrap/src/core/build_steps/clippy.rs index 4ee9fbc3142..a2bb03cd5ac 100644 --- a/src/bootstrap/src/core/build_steps/clippy.rs +++ b/src/bootstrap/src/core/build_steps/clippy.rs @@ -313,7 +313,7 @@ lint_any!( RemoteTestServer, "src/tools/remote-test-server", "remote-test-server"; Rls, "src/tools/rls", "rls"; RustAnalyzer, "src/tools/rust-analyzer", "rust-analyzer"; - Rustdoc, "src/tools/rustdoc", "clippy"; + Rustdoc, "src/librustdoc", "clippy"; Rustfmt, "src/tools/rustfmt", "rustfmt"; RustInstaller, "src/tools/rust-installer", "rust-installer"; Tidy, "src/tools/tidy", "tidy"; diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 4353cfadd8d..edf18e2ebf3 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -199,16 +199,6 @@ impl Step for Std { builder.require_submodule("library/stdarch", None); - // Profiler information requires LLVM's compiler-rt - if builder.config.profiler { - builder.require_submodule( - "src/llvm-project", - Some( - "The `build.profiler` config option requires `compiler-rt` sources from LLVM.", - ), - ); - } - let mut target_deps = builder.ensure(StartupObjects { compiler, target }); let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); @@ -466,6 +456,29 @@ pub fn std_crates_for_run_make(run: &RunConfig<'_>) -> Vec { } } +/// Tries to find LLVM's `compiler-rt` source directory, for building `library/profiler_builtins`. +/// +/// Normally it lives in the `src/llvm-project` submodule, but if we will be using a +/// downloaded copy of CI LLVM, then we try to use the `compiler-rt` sources from +/// there instead, which lets us avoid checking out the LLVM submodule. +fn compiler_rt_for_profiler(builder: &Builder<'_>) -> PathBuf { + // Try to use `compiler-rt` sources from downloaded CI LLVM, if possible. + if builder.config.llvm_from_ci { + // CI LLVM might not have been downloaded yet, so try to download it now. + builder.config.maybe_download_ci_llvm(); + let ci_llvm_compiler_rt = builder.config.ci_llvm_root().join("compiler-rt"); + if ci_llvm_compiler_rt.exists() { + return ci_llvm_compiler_rt; + } + } + + // Otherwise, fall back to requiring the LLVM submodule. + builder.require_submodule("src/llvm-project", { + Some("The `build.profiler` config option requires `compiler-rt` sources from LLVM.") + }); + builder.src.join("src/llvm-project/compiler-rt") +} + /// Configure cargo to compile the standard library, adding appropriate env vars /// and such. pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, cargo: &mut Cargo) { @@ -473,8 +486,15 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car cargo.env("MACOSX_DEPLOYMENT_TARGET", target); } + // Paths needed by `library/profiler_builtins/build.rs`. if let Some(path) = builder.config.profiler_path(target) { cargo.env("LLVM_PROFILER_RT_LIB", path); + } else if builder.config.profiler_enabled(target) { + let compiler_rt = compiler_rt_for_profiler(builder); + // Currently this is separate from the env var used by `compiler_builtins` + // (below) so that adding support for CI LLVM here doesn't risk breaking + // the compiler builtins. But they could be unified if desired. + cargo.env("RUST_COMPILER_RT_FOR_PROFILER", compiler_rt); } // Determine if we're going to compile in optimized C intrinsics to @@ -507,8 +527,8 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car ); let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt"); assert!(compiler_builtins_root.exists()); - // Note that `libprofiler_builtins/build.rs` also computes this so if - // you're changing something here please also change that. + // The path to `compiler-rt` is also used by `profiler_builtins` (above), + // so if you're changing something here please also change that as appropriate. cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root); " compiler-builtins-c" } else { diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 530eb9b446a..4957de2e1b7 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -19,6 +19,7 @@ use object::BinaryFormat; use crate::core::build_steps::doc::DocumentationFormat; use crate::core::build_steps::tool::{self, Tool}; +use crate::core::build_steps::vendor::default_paths_to_vendor; use crate::core::build_steps::{compile, llvm}; use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step}; use crate::core::config::TargetSelection; @@ -268,34 +269,45 @@ fn make_win_dist( let target_libs = find_files(&target_libs, &lib_path); // Copy runtime dlls next to rustc.exe - let dist_bin_dir = rust_root.join("bin/"); - fs::create_dir_all(&dist_bin_dir).expect("creating dist_bin_dir failed"); - for src in rustc_dlls { - builder.copy_link_to_folder(&src, &dist_bin_dir); + let rust_bin_dir = rust_root.join("bin/"); + fs::create_dir_all(&rust_bin_dir).expect("creating rust_bin_dir failed"); + for src in &rustc_dlls { + builder.copy_link_to_folder(src, &rust_bin_dir); + } + + if builder.config.lld_enabled { + // rust-lld.exe also needs runtime dlls + let rust_target_bin_dir = rust_root.join("lib/rustlib").join(target).join("bin"); + fs::create_dir_all(&rust_target_bin_dir).expect("creating rust_target_bin_dir failed"); + for src in &rustc_dlls { + builder.copy_link_to_folder(src, &rust_target_bin_dir); + } } //Copy platform tools to platform-specific bin directory - let target_bin_dir = - plat_root.join("lib").join("rustlib").join(target).join("bin").join("self-contained"); - fs::create_dir_all(&target_bin_dir).expect("creating target_bin_dir failed"); + let plat_target_bin_self_contained_dir = + plat_root.join("lib/rustlib").join(target).join("bin/self-contained"); + fs::create_dir_all(&plat_target_bin_self_contained_dir) + .expect("creating plat_target_bin_self_contained_dir failed"); for src in target_tools { - builder.copy_link_to_folder(&src, &target_bin_dir); + builder.copy_link_to_folder(&src, &plat_target_bin_self_contained_dir); } // Warn windows-gnu users that the bundled GCC cannot compile C files builder.create( - &target_bin_dir.join("GCC-WARNING.txt"), + &plat_target_bin_self_contained_dir.join("GCC-WARNING.txt"), "gcc.exe contained in this folder cannot be used for compiling C files - it is only \ used as a linker. In order to be able to compile projects containing C code use \ the GCC provided by MinGW or Cygwin.", ); //Copy platform libs to platform-specific lib directory - let target_lib_dir = - plat_root.join("lib").join("rustlib").join(target).join("lib").join("self-contained"); - fs::create_dir_all(&target_lib_dir).expect("creating target_lib_dir failed"); + let plat_target_lib_self_contained_dir = + plat_root.join("lib/rustlib").join(target).join("lib/self-contained"); + fs::create_dir_all(&plat_target_lib_self_contained_dir) + .expect("creating plat_target_lib_self_contained_dir failed"); for src in target_libs { - builder.copy_link_to_folder(&src, &target_lib_dir); + builder.copy_link_to_folder(&src, &plat_target_lib_self_contained_dir); } } @@ -1004,35 +1016,18 @@ impl Step for PlainSourceTarball { if builder.rust_info().is_managed_git_subrepository() || builder.rust_info().is_from_tarball() { - // FIXME: This code looks _very_ similar to what we have in `src/core/build_steps/vendor.rs` - // perhaps it should be removed in favor of making `dist` perform the `vendor` step? - builder.require_and_update_all_submodules(); // Vendor all Cargo dependencies let mut cmd = command(&builder.initial_cargo); - cmd.arg("vendor") - .arg("--versioned-dirs") - .arg("--sync") - .arg(builder.src.join("./src/tools/cargo/Cargo.toml")) - .arg("--sync") - .arg(builder.src.join("./src/tools/rust-analyzer/Cargo.toml")) - .arg("--sync") - .arg(builder.src.join("./compiler/rustc_codegen_cranelift/Cargo.toml")) - .arg("--sync") - .arg(builder.src.join("./compiler/rustc_codegen_gcc/Cargo.toml")) - .arg("--sync") - .arg(builder.src.join("./library/Cargo.toml")) - .arg("--sync") - .arg(builder.src.join("./src/bootstrap/Cargo.toml")) - .arg("--sync") - .arg(builder.src.join("./src/tools/opt-dist/Cargo.toml")) - .arg("--sync") - .arg(builder.src.join("./src/tools/rustc-perf/Cargo.toml")) - .arg("--sync") - .arg(builder.src.join("./src/tools/rustbook/Cargo.toml")) - // Will read the libstd Cargo.toml - // which uses the unstable `public-dependency` feature. + cmd.arg("vendor").arg("--versioned-dirs"); + + for p in default_paths_to_vendor(builder) { + cmd.arg("--sync").arg(p); + } + + cmd + // Will read the libstd Cargo.toml which uses the unstable `public-dependency` feature. .env("RUSTC_BOOTSTRAP", "1") .current_dir(plain_dst_src); @@ -2322,6 +2317,19 @@ impl Step for RustDev { let link_type = if builder.llvm_link_shared() { "dynamic" } else { "static" }; t!(std::fs::write(tarball.image_dir().join("link-type.txt"), link_type), dst_libdir); + // Copy the `compiler-rt` source, so that `library/profiler_builtins` + // can potentially use it to build the profiler runtime without needing + // to check out the LLVM submodule. + copy_src_dirs( + builder, + &builder.src.join("src").join("llvm-project"), + &["compiler-rt"], + // The test subdirectory is much larger than the rest of the source, + // and we currently don't use these test files anyway. + &["compiler-rt/test"], + tarball.image_dir(), + ); + Some(tarball.generate()) } } diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 301633559fe..ffb617c642b 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -303,10 +303,11 @@ fn invoke_rustdoc( .arg(&out) .arg(&path) .arg("--markdown-css") - .arg("../rust.css"); + .arg("../rust.css") + .arg("-Zunstable-options"); if !builder.config.docs_minification { - cmd.arg("-Z").arg("unstable-options").arg("--disable-minification"); + cmd.arg("--disable-minification"); } cmd.run(builder); @@ -376,8 +377,6 @@ impl Step for Standalone { } let mut cmd = builder.rustdoc_cmd(compiler); - // Needed for --index-page flag - cmd.arg("-Z").arg("unstable-options"); cmd.arg("--html-after-content") .arg(&footer) @@ -386,6 +385,7 @@ impl Step for Standalone { .arg("--html-in-header") .arg(&favicon) .arg("--markdown-no-toc") + .arg("-Zunstable-options") .arg("--index-page") .arg(builder.src.join("src/doc/index.md")) .arg("--markdown-playground-url") @@ -478,9 +478,6 @@ impl Step for Releases { mem::drop(tmpfile); let mut cmd = builder.rustdoc_cmd(compiler); - // Needed for --index-page flag - cmd.arg("-Z").arg("unstable-options"); - cmd.arg("--html-after-content") .arg(&footer) .arg("--html-before-content") @@ -490,6 +487,7 @@ impl Step for Releases { .arg("--markdown-no-toc") .arg("--markdown-css") .arg("rust.css") + .arg("-Zunstable-options") .arg("--index-page") .arg(builder.src.join("src/doc/index.md")) .arg("--markdown-playground-url") @@ -636,6 +634,8 @@ impl Step for Std { if !builder.config.docs_minification { extra_args.push("--disable-minification"); } + // For `--index-page` and `--output-format=json`. + extra_args.push("-Zunstable-options"); doc_std(builder, self.format, stage, target, &out, &extra_args, &crates); @@ -715,8 +715,6 @@ fn doc_std( .arg("--target-dir") .arg(&*target_dir.to_string_lossy()) .arg("-Zskip-rustdoc-fingerprint") - .rustdocflag("-Z") - .rustdocflag("unstable-options") .rustdocflag("--resource-suffix") .rustdocflag(&builder.version); for arg in extra_args { @@ -822,7 +820,6 @@ impl Step for Rustc { // Since we always pass --document-private-items, there's no need to warn about linking to private items. cargo.rustdocflag("-Arustdoc::private-intra-doc-links"); cargo.rustdocflag("--enable-index-page"); - cargo.rustdocflag("-Zunstable-options"); cargo.rustdocflag("-Znormalize-docs"); cargo.rustdocflag("--show-type-layout"); // FIXME: `--generate-link-to-definition` tries to resolve cfged out code @@ -830,7 +827,6 @@ impl Step for Rustc { // cargo.rustdocflag("--generate-link-to-definition"); compile::rustc_cargo(builder, &mut cargo, target, &compiler); - cargo.arg("-Zunstable-options"); cargo.arg("-Zskip-rustdoc-fingerprint"); // Only include compiler crates, no dependencies of those, such as `libc`. @@ -986,7 +982,6 @@ macro_rules! tool_doc { cargo.rustdocflag("-Arustdoc::private-intra-doc-links"); cargo.rustdocflag("--enable-index-page"); cargo.rustdocflag("--show-type-layout"); - cargo.rustdocflag("-Zunstable-options"); // FIXME: `--generate-link-to-definition` tries to resolve cfged out code // see https://github.com/rust-lang/rust/pull/122066#issuecomment-1983049222 // cargo.rustdocflag("--generate-link-to-definition"); diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index c5a1ab78801..e1eea31b3bb 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -110,7 +110,7 @@ pub fn prebuilt_llvm_config(builder: &Builder<'_>, target: TargetSelection) -> L // Initialize the llvm submodule if not initialized already. // If submodules are disabled, this does nothing. - builder.update_submodule("src/llvm-project"); + builder.config.update_submodule("src/llvm-project"); let root = "src/llvm-project/llvm"; let out_dir = builder.llvm_out(target); diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs index 8cd9ba5fd14..f7b26712cab 100644 --- a/src/bootstrap/src/core/build_steps/setup.rs +++ b/src/bootstrap/src/core/build_steps/setup.rs @@ -247,9 +247,11 @@ pub struct Link; impl Step for Link { type Output = (); const DEFAULT: bool = true; + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.alias("link") } + fn make_run(run: RunConfig<'_>) { if run.builder.config.dry_run() { return; @@ -262,21 +264,30 @@ impl Step for Link { } fn run(self, builder: &Builder<'_>) -> Self::Output { let config = &builder.config; + if config.dry_run() { return; } + + if !rustup_installed(builder) { + println!("WARNING: `rustup` is not installed; Skipping `stage1` toolchain linking."); + return; + } + let stage_path = ["build", config.build.rustc_target_arg(), "stage1"].join(MAIN_SEPARATOR_STR); - if !rustup_installed(builder) { - eprintln!("`rustup` is not installed; cannot link `stage1` toolchain"); - } else if stage_dir_exists(&stage_path[..]) && !config.dry_run() { + + if stage_dir_exists(&stage_path[..]) && !config.dry_run() { attempt_toolchain_link(builder, &stage_path[..]); } } } fn rustup_installed(builder: &Builder<'_>) -> bool { - command("rustup").arg("--version").run_capture_stdout(builder).is_success() + let mut rustup = command("rustup"); + rustup.arg("--version"); + + rustup.allow_failure().run_always().run_capture_stdout(builder).is_success() } fn stage_dir_exists(stage_path: &str) -> bool { diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index 4d573b107b5..3a1eb43b801 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -1091,18 +1091,13 @@ macro_rules! tool_extended { } } -// NOTE: tools need to be also added to `Builder::get_step_descriptions` in `builder.rs` -// to make `./x.py build ` work. tool_extended!((self, builder), Cargofmt, "src/tools/rustfmt", "cargo-fmt", stable=true; CargoClippy, "src/tools/clippy", "cargo-clippy", stable=true; Clippy, "src/tools/clippy", "clippy-driver", stable=true, add_bins_to_sysroot = ["clippy-driver", "cargo-clippy"]; Miri, "src/tools/miri", "miri", stable=false, add_bins_to_sysroot = ["miri"]; - CargoMiri, "src/tools/miri/cargo-miri", "cargo-miri", stable=true, add_bins_to_sysroot = ["cargo-miri"]; - // FIXME: tool_std is not quite right, we shouldn't allow nightly features. - // But `builder.cargo` doesn't know how to handle ToolBootstrap in stages other than 0, - // and this is close enough for now. - Rls, "src/tools/rls", "rls", stable=true, tool_std=true; + CargoMiri, "src/tools/miri/cargo-miri", "cargo-miri", stable=false, add_bins_to_sysroot = ["cargo-miri"]; + Rls, "src/tools/rls", "rls", stable=true; Rustfmt, "src/tools/rustfmt", "rustfmt", stable=true, add_bins_to_sysroot = ["rustfmt", "cargo-fmt"]; ); diff --git a/src/bootstrap/src/core/build_steps/vendor.rs b/src/bootstrap/src/core/build_steps/vendor.rs index 33768465225..82a6b4d4f28 100644 --- a/src/bootstrap/src/core/build_steps/vendor.rs +++ b/src/bootstrap/src/core/build_steps/vendor.rs @@ -4,6 +4,26 @@ use crate::core::build_steps::tool::SUBMODULES_FOR_RUSTBOOK; use crate::core::builder::{Builder, RunConfig, ShouldRun, Step}; use crate::utils::exec::command; +/// List of default paths used for vendoring for `x vendor` and dist tarballs. +pub fn default_paths_to_vendor(builder: &Builder<'_>) -> Vec { + let mut paths = vec![]; + for p in [ + "src/tools/cargo/Cargo.toml", + "src/tools/rust-analyzer/Cargo.toml", + "compiler/rustc_codegen_cranelift/Cargo.toml", + "compiler/rustc_codegen_gcc/Cargo.toml", + "library/Cargo.toml", + "src/bootstrap/Cargo.toml", + "src/tools/rustbook/Cargo.toml", + "src/tools/rustc-perf/Cargo.toml", + "src/tools/opt-dist/Cargo.toml", + ] { + paths.push(builder.src.join(p)); + } + + paths +} + #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub(crate) struct Vendor { sync_args: Vec, @@ -42,16 +62,8 @@ impl Step for Vendor { } // Sync these paths by default. - for p in [ - "src/tools/cargo/Cargo.toml", - "src/tools/rust-analyzer/Cargo.toml", - "compiler/rustc_codegen_cranelift/Cargo.toml", - "compiler/rustc_codegen_gcc/Cargo.toml", - "library/Cargo.toml", - "src/bootstrap/Cargo.toml", - "src/tools/rustbook/Cargo.toml", - ] { - cmd.arg("--sync").arg(builder.src.join(p)); + for p in default_paths_to_vendor(builder) { + cmd.arg("--sync").arg(p); } // Also sync explicitly requested paths. diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 454cc20d155..ff0d1f3a725 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -1455,15 +1455,11 @@ impl<'a> Builder<'a> { assert_eq!(target, compiler.host); } - if self.config.rust_optimize.is_release() { - // FIXME: cargo bench/install do not accept `--release` - // and miri doesn't want it - match cmd_kind { - Kind::Bench | Kind::Install | Kind::Miri | Kind::MiriSetup | Kind::MiriTest => {} - _ => { - cargo.arg("--release"); - } - } + if self.config.rust_optimize.is_release() && + // cargo bench/install do not accept `--release` and miri doesn't want it + !matches!(cmd_kind, Kind::Bench | Kind::Install | Kind::Miri | Kind::MiriSetup | Kind::MiriTest) + { + cargo.arg("--release"); } // Remove make-related flags to ensure Cargo can correctly set things up @@ -1616,7 +1612,6 @@ impl<'a> Builder<'a> { rustflags.arg("-Csymbol-mangling-version=v0"); } else { rustflags.arg("-Csymbol-mangling-version=legacy"); - rustflags.arg("-Zunstable-options"); } // Enable compile-time checking of `cfg` names, values and Cargo `features`. @@ -1864,16 +1859,7 @@ impl<'a> Builder<'a> { }, ); - let split_debuginfo = self.config.split_debuginfo(target); - let split_debuginfo_is_stable = target.contains("linux") - || target.contains("apple") - || (target.is_msvc() && split_debuginfo == SplitDebuginfo::Packed) - || (target.is_windows() && split_debuginfo == SplitDebuginfo::Off); - - if !split_debuginfo_is_stable { - rustflags.arg("-Zunstable-options"); - } - match split_debuginfo { + match self.config.split_debuginfo(target) { SplitDebuginfo::Packed => rustflags.arg("-Csplit-debuginfo=packed"), SplitDebuginfo::Unpacked => rustflags.arg("-Csplit-debuginfo=unpacked"), SplitDebuginfo::Off => rustflags.arg("-Csplit-debuginfo=off"), @@ -2050,7 +2036,6 @@ impl<'a> Builder<'a> { } if mode == Mode::Rustc { - rustflags.arg("-Zunstable-options"); rustflags.arg("-Wrustc::internal"); // FIXME(edition_2024): Change this to `-Wrust_2024_idioms` when all // of the individual lints are satisfied. diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 36de8324f67..bdfee55d8d1 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -14,7 +14,7 @@ use std::sync::OnceLock; use std::{cmp, env, fs}; use build_helper::exit; -use build_helper::git::GitConfig; +use build_helper::git::{output_result, GitConfig}; use serde::{Deserialize, Deserializer}; use serde_derive::Deserialize; @@ -36,6 +36,14 @@ macro_rules! check_ci_llvm { }; } +/// This file is embedded in the overlay directory of the tarball sources. It is +/// useful in scenarios where developers want to see how the tarball sources were +/// generated. +/// +/// We also use this file to compare the host's config.toml against the CI rustc builder +/// configuration to detect any incompatible options. +pub(crate) const BUILDER_CONFIG_FILENAME: &str = "builder-config"; + #[derive(Clone, Default)] pub enum DryRun { /// This isn't a dry run. @@ -47,7 +55,7 @@ pub enum DryRun { UserSelected, } -#[derive(Copy, Clone, Default, PartialEq, Eq)] +#[derive(Copy, Clone, Default, Debug, Eq, PartialEq)] pub enum DebuginfoLevel { #[default] None, @@ -117,7 +125,7 @@ impl Display for DebuginfoLevel { /// 2) MSVC /// - Self-contained: `-Clinker=` /// - External: `-Clinker=lld` -#[derive(Default, Copy, Clone)] +#[derive(Copy, Clone, Default, Debug, PartialEq)] pub enum LldMode { /// Do not use LLD #[default] @@ -1203,40 +1211,42 @@ impl Config { } } - pub fn parse(flags: Flags) -> Config { - #[cfg(test)] - fn get_toml(_: &Path) -> TomlConfig { - TomlConfig::default() - } - - #[cfg(not(test))] - fn get_toml(file: &Path) -> TomlConfig { - let contents = - t!(fs::read_to_string(file), format!("config file {} not found", file.display())); - // Deserialize to Value and then TomlConfig to prevent the Deserialize impl of - // TomlConfig and sub types to be monomorphized 5x by toml. - toml::from_str(&contents) - .and_then(|table: toml::Value| TomlConfig::deserialize(table)) - .unwrap_or_else(|err| { - if let Ok(Some(changes)) = toml::from_str(&contents) - .and_then(|table: toml::Value| ChangeIdWrapper::deserialize(table)).map(|change_id| change_id.inner.map(crate::find_recent_config_change_ids)) - { - if !changes.is_empty() { - println!( - "WARNING: There have been changes to x.py since you last updated:\n{}", - crate::human_readable_changes(&changes) - ); - } - } - - eprintln!("failed to parse TOML configuration '{}': {err}", file.display()); - exit!(2); - }) - } - Self::parse_inner(flags, get_toml) + #[cfg(test)] + fn get_toml(_: &Path) -> Result { + Ok(TomlConfig::default()) } - pub(crate) fn parse_inner(mut flags: Flags, get_toml: impl Fn(&Path) -> TomlConfig) -> Config { + #[cfg(not(test))] + fn get_toml(file: &Path) -> Result { + let contents = + t!(fs::read_to_string(file), format!("config file {} not found", file.display())); + // Deserialize to Value and then TomlConfig to prevent the Deserialize impl of + // TomlConfig and sub types to be monomorphized 5x by toml. + toml::from_str(&contents) + .and_then(|table: toml::Value| TomlConfig::deserialize(table)) + .inspect_err(|_| { + if let Ok(Some(changes)) = toml::from_str(&contents) + .and_then(|table: toml::Value| ChangeIdWrapper::deserialize(table)) + .map(|change_id| change_id.inner.map(crate::find_recent_config_change_ids)) + { + if !changes.is_empty() { + println!( + "WARNING: There have been changes to x.py since you last updated:\n{}", + crate::human_readable_changes(&changes) + ); + } + } + }) + } + + pub fn parse(flags: Flags) -> Config { + Self::parse_inner(flags, Self::get_toml) + } + + pub(crate) fn parse_inner( + mut flags: Flags, + get_toml: impl Fn(&Path) -> Result, + ) -> Config { let mut config = Config::default_opts(); // Set flags. @@ -1344,7 +1354,10 @@ impl Config { } else { toml_path.clone() }); - get_toml(&toml_path) + get_toml(&toml_path).unwrap_or_else(|e| { + eprintln!("ERROR: Failed to parse '{}': {e}", toml_path.display()); + exit!(2); + }) } else { config.config = None; TomlConfig::default() @@ -1375,7 +1388,13 @@ impl Config { include_path.push("bootstrap"); include_path.push("defaults"); include_path.push(format!("config.{include}.toml")); - let included_toml = get_toml(&include_path); + let included_toml = get_toml(&include_path).unwrap_or_else(|e| { + eprintln!( + "ERROR: Failed to parse default config profile at '{}': {e}", + include_path.display() + ); + exit!(2); + }); toml.merge(included_toml, ReplaceOpt::IgnoreDuplicate); } @@ -1591,24 +1610,6 @@ impl Config { let mut is_user_configured_rust_channel = false; if let Some(rust) = toml.rust { - if let Some(commit) = config.download_ci_rustc_commit(rust.download_rustc.clone()) { - // Primarily used by CI runners to avoid handling download-rustc incompatible - // options one by one on shell scripts. - let disable_ci_rustc_if_incompatible = - env::var_os("DISABLE_CI_RUSTC_IF_INCOMPATIBLE") - .is_some_and(|s| s == "1" || s == "true"); - - if let Err(e) = check_incompatible_options_for_ci_rustc(&rust) { - if disable_ci_rustc_if_incompatible { - config.download_rustc_commit = None; - } else { - panic!("{}", e); - } - } else { - config.download_rustc_commit = Some(commit); - } - } - let Rust { optimize: optimize_toml, debug: debug_toml, @@ -1656,7 +1657,7 @@ impl Config { new_symbol_mangling, profile_generate, profile_use, - download_rustc: _, + download_rustc, lto, validate_mir_opts, frame_pointers, @@ -1668,6 +1669,8 @@ impl Config { is_user_configured_rust_channel = channel.is_some(); set(&mut config.channel, channel.clone()); + config.download_rustc_commit = config.download_ci_rustc_commit(download_rustc); + debug = debug_toml; debug_assertions = debug_assertions_toml; debug_assertions_std = debug_assertions_std_toml; @@ -1882,6 +1885,22 @@ impl Config { warn("link-shared"); } + // FIXME(#129153): instead of all the ad-hoc `download-ci-llvm` checks that follow, + // use the `builder-config` present in tarballs since #128822 to compare the local + // config to the ones used to build the LLVM artifacts on CI, and only notify users + // if they've chosen a different value. + + if libzstd.is_some() { + println!( + "WARNING: when using `download-ci-llvm`, the local `llvm.libzstd` option, \ + like almost all `llvm.*` options, will be ignored and set by the LLVM CI \ + artifacts builder config." + ); + println!( + "HELP: To use `llvm.libzstd` for LLVM/LLD builds, set `download-ci-llvm` option to false." + ); + } + // None of the LLVM options, except assertions, are supported // when using downloaded LLVM. We could just ignore these but // that's potentially confusing, so force them to not be @@ -1891,7 +1910,6 @@ impl Config { check_ci_llvm!(optimize_toml); check_ci_llvm!(thin_lto); check_ci_llvm!(release_debuginfo); - check_ci_llvm!(libzstd); check_ci_llvm!(targets); check_ci_llvm!(experimental_targets); check_ci_llvm!(clang_cl); @@ -2345,6 +2363,45 @@ impl Config { None => None, Some(commit) => { self.download_ci_rustc(commit); + + if let Some(config_path) = &self.config { + let builder_config_path = + self.out.join(self.build.triple).join("ci-rustc").join(BUILDER_CONFIG_FILENAME); + + let ci_config_toml = match Self::get_toml(&builder_config_path) { + Ok(ci_config_toml) => ci_config_toml, + Err(e) if e.to_string().contains("unknown field") => { + println!("WARNING: CI rustc has some fields that are no longer supported in bootstrap; download-rustc will be disabled."); + println!("HELP: Consider rebasing to a newer commit if available."); + return None; + }, + Err(e) => { + eprintln!("ERROR: Failed to parse CI rustc config at '{}': {e}", builder_config_path.display()); + exit!(2); + }, + }; + + let current_config_toml = Self::get_toml(config_path).unwrap(); + + // Check the config compatibility + // FIXME: this doesn't cover `--set` flags yet. + let res = check_incompatible_options_for_ci_rustc( + current_config_toml, + ci_config_toml, + ); + + let disable_ci_rustc_if_incompatible = + env::var_os("DISABLE_CI_RUSTC_IF_INCOMPATIBLE") + .is_some_and(|s| s == "1" || s == "true"); + + if disable_ci_rustc_if_incompatible && res.is_err() { + println!("WARNING: download-rustc is disabled with `DISABLE_CI_RUSTC_IF_INCOMPATIBLE` env."); + return None; + } + + res.unwrap(); + } + Some(commit.clone()) } }) @@ -2467,6 +2524,123 @@ impl Config { } } + /// Given a path to the directory of a submodule, update it. + /// + /// `relative_path` should be relative to the root of the git repository, not an absolute path. + /// + /// This *does not* update the submodule if `config.toml` explicitly says + /// not to, or if we're not in a git repository (like a plain source + /// tarball). Typically [`crate::Build::require_submodule`] should be + /// used instead to provide a nice error to the user if the submodule is + /// missing. + pub(crate) fn update_submodule(&self, relative_path: &str) { + if !self.submodules() { + return; + } + + let absolute_path = self.src.join(relative_path); + + // NOTE: The check for the empty directory is here because when running x.py the first time, + // the submodule won't be checked out. Check it out now so we can build it. + if !GitInfo::new(false, &absolute_path).is_managed_git_subrepository() + && !helpers::dir_is_empty(&absolute_path) + { + return; + } + + // Submodule updating actually happens during in the dry run mode. We need to make sure that + // all the git commands below are actually executed, because some follow-up code + // in bootstrap might depend on the submodules being checked out. Furthermore, not all + // the command executions below work with an empty output (produced during dry run). + // Therefore, all commands below are marked with `run_always()`, so that they also run in + // dry run mode. + let submodule_git = || { + let mut cmd = helpers::git(Some(&absolute_path)); + cmd.run_always(); + cmd + }; + + // Determine commit checked out in submodule. + let checked_out_hash = output(submodule_git().args(["rev-parse", "HEAD"]).as_command_mut()); + let checked_out_hash = checked_out_hash.trim_end(); + // Determine commit that the submodule *should* have. + let recorded = output( + helpers::git(Some(&self.src)) + .run_always() + .args(["ls-tree", "HEAD"]) + .arg(relative_path) + .as_command_mut(), + ); + + let actual_hash = recorded + .split_whitespace() + .nth(2) + .unwrap_or_else(|| panic!("unexpected output `{}`", recorded)); + + if actual_hash == checked_out_hash { + // already checked out + return; + } + + println!("Updating submodule {relative_path}"); + self.check_run( + helpers::git(Some(&self.src)) + .run_always() + .args(["submodule", "-q", "sync"]) + .arg(relative_path), + ); + + // Try passing `--progress` to start, then run git again without if that fails. + let update = |progress: bool| { + // Git is buggy and will try to fetch submodules from the tracking branch for *this* repository, + // even though that has no relation to the upstream for the submodule. + let current_branch = output_result( + helpers::git(Some(&self.src)) + .allow_failure() + .run_always() + .args(["symbolic-ref", "--short", "HEAD"]) + .as_command_mut(), + ) + .map(|b| b.trim().to_owned()); + + let mut git = helpers::git(Some(&self.src)).allow_failure(); + git.run_always(); + if let Ok(branch) = current_branch { + // If there is a tag named after the current branch, git will try to disambiguate by prepending `heads/` to the branch name. + // This syntax isn't accepted by `branch.{branch}`. Strip it. + let branch = branch.strip_prefix("heads/").unwrap_or(&branch); + git.arg("-c").arg(format!("branch.{branch}.remote=origin")); + } + git.args(["submodule", "update", "--init", "--recursive", "--depth=1"]); + if progress { + git.arg("--progress"); + } + git.arg(relative_path); + git + }; + if !self.check_run(&mut update(true)) { + self.check_run(&mut update(false)); + } + + // Save any local changes, but avoid running `git stash pop` if there are none (since it will exit with an error). + // diff-index reports the modifications through the exit status + let has_local_modifications = !self.check_run(submodule_git().allow_failure().args([ + "diff-index", + "--quiet", + "HEAD", + ])); + if has_local_modifications { + self.check_run(submodule_git().args(["stash", "push"])); + } + + self.check_run(submodule_git().args(["reset", "-q", "--hard"])); + self.check_run(submodule_git().args(["clean", "-qdfx"])); + + if has_local_modifications { + self.check_run(submodule_git().args(["stash", "pop"])); + } + } + #[cfg(feature = "bootstrap-self-test")] pub fn check_stage0_version(&self, _program_path: &Path, _component_name: &'static str) {} @@ -2571,19 +2745,23 @@ impl Config { asserts: bool, ) -> bool { let if_unchanged = || { - // Git is needed to track modifications here, but tarball source is not available. - // If not modified here or built through tarball source, we maintain consistency - // with '"if available"'. - if !self.rust_info.is_from_tarball() - && self - .last_modified_commit(&["src/llvm-project"], "download-ci-llvm", true) - .is_none() - { - // there are some untracked changes in the given paths. - false - } else { - llvm::is_ci_llvm_available(self, asserts) + if self.rust_info.is_from_tarball() { + // Git is needed for running "if-unchanged" logic. + println!( + "WARNING: 'if-unchanged' has no effect on tarball sources; ignoring `download-ci-llvm`." + ); + return false; } + + self.update_submodule("src/llvm-project"); + + // Check for untracked changes in `src/llvm-project`. + let has_changes = self + .last_modified_commit(&["src/llvm-project"], "download-ci-llvm", true) + .is_none(); + + // Return false if there are untracked changes, otherwise check if CI LLVM is available. + if has_changes { false } else { llvm::is_ci_llvm_available(self, asserts) } }; match download_ci_llvm { @@ -2662,31 +2840,52 @@ impl Config { } } -/// Checks the CI rustc incompatible options by destructuring the `Rust` instance -/// and makes sure that no rust options from config.toml are missed. -fn check_incompatible_options_for_ci_rustc(rust: &Rust) -> Result<(), String> { +/// Compares the current Rust options against those in the CI rustc builder and detects any incompatible options. +/// It does this by destructuring the `Rust` instance to make sure every `Rust` field is covered and not missing. +fn check_incompatible_options_for_ci_rustc( + current_config_toml: TomlConfig, + ci_config_toml: TomlConfig, +) -> Result<(), String> { macro_rules! err { - ($name:expr) => { - if $name.is_some() { - return Err(format!( - "ERROR: Setting `rust.{}` is incompatible with `rust.download-rustc`.", - stringify!($name).replace("_", "-") - )); - } + ($current:expr, $expected:expr) => { + if let Some(current) = &$current { + if Some(current) != $expected.as_ref() { + return Err(format!( + "ERROR: Setting `rust.{}` is incompatible with `rust.download-rustc`. \ + Current value: {:?}, Expected value(s): {}{:?}", + stringify!($expected).replace("_", "-"), + $current, + if $expected.is_some() { "None/" } else { "" }, + $expected, + )); + }; + }; }; } macro_rules! warn { - ($name:expr) => { - if $name.is_some() { - println!( - "WARNING: `rust.{}` has no effect with `rust.download-rustc`.", - stringify!($name).replace("_", "-") - ); - } + ($current:expr, $expected:expr) => { + if let Some(current) = &$current { + if Some(current) != $expected.as_ref() { + println!( + "WARNING: `rust.{}` has no effect with `rust.download-rustc`. \ + Current value: {:?}, Expected value(s): {}{:?}", + stringify!($expected).replace("_", "-"), + $current, + if $expected.is_some() { "None/" } else { "" }, + $expected, + ); + }; + }; }; } + let (Some(current_rust_config), Some(ci_rust_config)) = + (current_config_toml.rust, ci_config_toml.rust) + else { + return Ok(()); + }; + let Rust { // Following options are the CI rustc incompatible ones. optimize, @@ -2744,7 +2943,7 @@ fn check_incompatible_options_for_ci_rustc(rust: &Rust) -> Result<(), String> { download_rustc: _, validate_mir_opts: _, frame_pointers: _, - } = rust; + } = ci_rust_config; // There are two kinds of checks for CI rustc incompatible options: // 1. Checking an option that may change the compiler behaviour/output. @@ -2752,22 +2951,23 @@ fn check_incompatible_options_for_ci_rustc(rust: &Rust) -> Result<(), String> { // // If the option belongs to the first category, we call `err` macro for a hard error; // otherwise, we just print a warning with `warn` macro. - err!(optimize); - err!(debug_logging); - err!(debuginfo_level_rustc); - err!(default_linker); - err!(rpath); - err!(strip); - err!(stack_protector); - err!(lld_mode); - err!(llvm_tools); - err!(llvm_bitcode_linker); - err!(jemalloc); - err!(lto); - warn!(channel); - warn!(description); - warn!(incremental); + err!(current_rust_config.optimize, optimize); + err!(current_rust_config.debug_logging, debug_logging); + err!(current_rust_config.debuginfo_level_rustc, debuginfo_level_rustc); + err!(current_rust_config.rpath, rpath); + err!(current_rust_config.strip, strip); + err!(current_rust_config.lld_mode, lld_mode); + err!(current_rust_config.llvm_tools, llvm_tools); + err!(current_rust_config.llvm_bitcode_linker, llvm_bitcode_linker); + err!(current_rust_config.jemalloc, jemalloc); + err!(current_rust_config.default_linker, default_linker); + err!(current_rust_config.stack_protector, stack_protector); + err!(current_rust_config.lto, lto); + + warn!(current_rust_config.channel, channel); + warn!(current_rust_config.description, description); + warn!(current_rust_config.incremental, incremental); Ok(()) } diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs index 40f3e5e7222..219c5a6ec91 100644 --- a/src/bootstrap/src/core/config/tests.rs +++ b/src/bootstrap/src/core/config/tests.rs @@ -14,7 +14,7 @@ use crate::core::config::{LldMode, Target, TargetSelection, TomlConfig}; fn parse(config: &str) -> Config { Config::parse_inner( Flags::parse(&["check".to_string(), "--config=/does/not/exist".to_string()]), - |&_| toml::from_str(&config).unwrap(), + |&_| toml::from_str(&config), ) } @@ -96,8 +96,8 @@ fn detect_src_and_out() { test(parse(""), None); { - let build_dir = if cfg!(windows) { Some("C:\\tmp") } else { Some("/tmp") }; - test(parse("build.build-dir = \"/tmp\""), build_dir); + let build_dir = if cfg!(windows) { "C:\\tmp" } else { "/tmp" }; + test(parse(&format!("build.build-dir = '{build_dir}'")), Some(build_dir)); } } @@ -151,7 +151,6 @@ runner = "x86_64-runner" "#, ) - .unwrap() }, ); assert_eq!(config.change_id, Some(1), "setting top-level value"); @@ -208,13 +207,13 @@ fn override_toml_duplicate() { "--set=change-id=1".to_owned(), "--set=change-id=2".to_owned(), ]), - |&_| toml::from_str("change-id = 0").unwrap(), + |&_| toml::from_str("change-id = 0"), ); } #[test] fn profile_user_dist() { - fn get_toml(file: &Path) -> TomlConfig { + fn get_toml(file: &Path) -> Result { let contents = if file.ends_with("config.toml") || env::var_os("RUST_BOOTSTRAP_CONFIG").is_some() { "profile = \"user\"".to_owned() @@ -223,9 +222,7 @@ fn profile_user_dist() { std::fs::read_to_string(file).unwrap() }; - toml::from_str(&contents) - .and_then(|table: toml::Value| TomlConfig::deserialize(table)) - .unwrap() + toml::from_str(&contents).and_then(|table: toml::Value| TomlConfig::deserialize(table)) } Config::parse_inner(Flags::parse(&["check".to_owned()]), get_toml); } diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index 8131666fcb2..1e3f8da5258 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -9,6 +9,7 @@ use std::sync::OnceLock; use build_helper::ci::CiEnv; use xz2::bufread::XzDecoder; +use crate::core::config::BUILDER_CONFIG_FILENAME; use crate::utils::exec::{command, BootstrapCommand}; use crate::utils::helpers::{check_run, exe, hex_encode, move_file, program_out_of_date}; use crate::{t, Config}; @@ -21,6 +22,24 @@ fn try_run(config: &Config, cmd: &mut Command) -> Result<(), ()> { config.try_run(cmd) } +fn extract_curl_version(out: &[u8]) -> semver::Version { + let out = String::from_utf8_lossy(out); + // The output should look like this: "curl .. ..." + out.lines() + .next() + .and_then(|line| line.split(" ").nth(1)) + .and_then(|version| semver::Version::parse(version).ok()) + .unwrap_or(semver::Version::new(1, 0, 0)) +} + +fn curl_version() -> semver::Version { + let mut curl = Command::new("curl"); + curl.arg("-V"); + let Ok(out) = curl.output() else { return semver::Version::new(1, 0, 0) }; + let out = out.stdout; + extract_curl_version(&out) +} + /// Generic helpers that are useful anywhere in bootstrap. impl Config { pub fn is_verbose(&self) -> bool { @@ -55,7 +74,7 @@ impl Config { /// Returns false if do not execute at all, otherwise returns its /// `status.success()`. pub(crate) fn check_run(&self, cmd: &mut BootstrapCommand) -> bool { - if self.dry_run() { + if self.dry_run() && !cmd.run_always { return true; } self.verbose(|| println!("running: {cmd:?}")); @@ -219,6 +238,8 @@ impl Config { "30", // timeout if cannot connect within 30 seconds "-o", tempfile.to_str().unwrap(), + "--continue-at", + "-", "--retry", "3", "-SRf", @@ -229,6 +250,10 @@ impl Config { } else { curl.arg("--progress-bar"); } + // --retry-all-errors was added in 7.71.0, don't use it if curl is old. + if curl_version() >= semver::Version::new(7, 71, 0) { + curl.arg("--retry-all-errors"); + } curl.arg(url); if !self.check_run(&mut curl) { if self.build.contains("windows-msvc") { @@ -273,11 +298,12 @@ impl Config { let mut tar = tar::Archive::new(decompressor); + let is_ci_rustc = dst.ends_with("ci-rustc"); + // `compile::Sysroot` needs to know the contents of the `rustc-dev` tarball to avoid adding // it to the sysroot unless it was explicitly requested. But parsing the 100 MB tarball is slow. // Cache the entries when we extract it so we only have to read it once. - let mut recorded_entries = - if dst.ends_with("ci-rustc") { recorded_entries(dst, pattern) } else { None }; + let mut recorded_entries = if is_ci_rustc { recorded_entries(dst, pattern) } else { None }; for member in t!(tar.entries()) { let mut member = t!(member); @@ -287,10 +313,12 @@ impl Config { continue; } let mut short_path = t!(original_path.strip_prefix(directory_prefix)); - if !short_path.starts_with(pattern) { + let is_builder_config = short_path.to_str() == Some(BUILDER_CONFIG_FILENAME); + + if !(short_path.starts_with(pattern) || (is_ci_rustc && is_builder_config)) { continue; } - short_path = t!(short_path.strip_prefix(pattern)); + short_path = short_path.strip_prefix(pattern).unwrap_or(short_path); let dst_path = dst.join(short_path); self.verbose(|| { println!("extracting {} to {}", original_path.display(), dst.display()) @@ -519,7 +547,7 @@ impl Config { extra_components: &[&str], download_component: fn(&Config, String, &str, &str), ) { - let host = self.build; + let host = self.build.triple; let bin_root = self.out.join(host).join(sysroot); let rustc_stamp = bin_root.join(".rustc-stamp"); @@ -616,8 +644,6 @@ impl Config { }; // For the beta compiler, put special effort into ensuring the checksums are valid. - // FIXME: maybe we should do this for download-rustc as well? but it would be a pain to update - // this on each and every nightly ... let checksum = if should_verify { let error = format!( "src/stage0 doesn't contain a checksum for {url}. \ @@ -703,9 +729,7 @@ download-rustc = false let file_times = fs::FileTimes::new().set_accessed(now).set_modified(now); let llvm_config = llvm_root.join("bin").join(exe("llvm-config", self.build)); - let llvm_config_file = t!(File::options().write(true).open(llvm_config)); - - t!(llvm_config_file.set_times(file_times)); + t!(crate::utils::helpers::set_file_times(llvm_config, file_times)); if self.should_fix_bins_and_dylibs() { let llvm_lib = llvm_root.join("lib"); diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index bfd0e42acfd..268392c5fb1 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -37,7 +37,9 @@ use crate::core::builder; use crate::core::builder::{Builder, Kind}; use crate::core::config::{flags, DryRun, LldMode, LlvmLibunwind, Target, TargetSelection}; use crate::utils::exec::{command, BehaviorOnFailure, BootstrapCommand, CommandOutput, OutputMode}; -use crate::utils::helpers::{self, dir_is_empty, exe, libdir, mtime, output, symlink_dir}; +use crate::utils::helpers::{ + self, dir_is_empty, exe, libdir, mtime, output, set_file_times, symlink_dir, +}; mod core; mod utils; @@ -471,117 +473,6 @@ impl Build { build } - /// Given a path to the directory of a submodule, update it. - /// - /// `relative_path` should be relative to the root of the git repository, not an absolute path. - /// - /// This *does not* update the submodule if `config.toml` explicitly says - /// not to, or if we're not in a git repository (like a plain source - /// tarball). Typically [`Build::require_submodule`] should be - /// used instead to provide a nice error to the user if the submodule is - /// missing. - fn update_submodule(&self, relative_path: &str) { - if !self.config.submodules() { - return; - } - - let absolute_path = self.config.src.join(relative_path); - - // NOTE: The check for the empty directory is here because when running x.py the first time, - // the submodule won't be checked out. Check it out now so we can build it. - if !GitInfo::new(false, &absolute_path).is_managed_git_subrepository() - && !dir_is_empty(&absolute_path) - { - return; - } - - // Submodule updating actually happens during in the dry run mode. We need to make sure that - // all the git commands below are actually executed, because some follow-up code - // in bootstrap might depend on the submodules being checked out. Furthermore, not all - // the command executions below work with an empty output (produced during dry run). - // Therefore, all commands below are marked with `run_always()`, so that they also run in - // dry run mode. - let submodule_git = || { - let mut cmd = helpers::git(Some(&absolute_path)); - cmd.run_always(); - cmd - }; - - // Determine commit checked out in submodule. - let checked_out_hash = - submodule_git().args(["rev-parse", "HEAD"]).run_capture_stdout(self).stdout(); - let checked_out_hash = checked_out_hash.trim_end(); - // Determine commit that the submodule *should* have. - let recorded = helpers::git(Some(&self.src)) - .run_always() - .args(["ls-tree", "HEAD"]) - .arg(relative_path) - .run_capture_stdout(self) - .stdout(); - let actual_hash = recorded - .split_whitespace() - .nth(2) - .unwrap_or_else(|| panic!("unexpected output `{}`", recorded)); - - if actual_hash == checked_out_hash { - // already checked out - return; - } - - println!("Updating submodule {relative_path}"); - helpers::git(Some(&self.src)) - .run_always() - .args(["submodule", "-q", "sync"]) - .arg(relative_path) - .run(self); - - // Try passing `--progress` to start, then run git again without if that fails. - let update = |progress: bool| { - // Git is buggy and will try to fetch submodules from the tracking branch for *this* repository, - // even though that has no relation to the upstream for the submodule. - let current_branch = helpers::git(Some(&self.src)) - .allow_failure() - .run_always() - .args(["symbolic-ref", "--short", "HEAD"]) - .run_capture_stdout(self) - .stdout_if_ok() - .map(|s| s.trim().to_owned()); - - let mut git = helpers::git(Some(&self.src)).allow_failure(); - git.run_always(); - if let Some(branch) = current_branch { - // If there is a tag named after the current branch, git will try to disambiguate by prepending `heads/` to the branch name. - // This syntax isn't accepted by `branch.{branch}`. Strip it. - let branch = branch.strip_prefix("heads/").unwrap_or(&branch); - git.arg("-c").arg(format!("branch.{branch}.remote=origin")); - } - git.args(["submodule", "update", "--init", "--recursive", "--depth=1"]); - if progress { - git.arg("--progress"); - } - git.arg(relative_path); - git - }; - if !update(true).run(self) { - update(false).run(self); - } - - // Save any local changes, but avoid running `git stash pop` if there are none (since it will exit with an error). - // diff-index reports the modifications through the exit status - let has_local_modifications = - !submodule_git().allow_failure().args(["diff-index", "--quiet", "HEAD"]).run(self); - if has_local_modifications { - submodule_git().args(["stash", "push"]).run(self); - } - - submodule_git().args(["reset", "-q", "--hard"]).run(self); - submodule_git().args(["clean", "-qdfx"]).run(self); - - if has_local_modifications { - submodule_git().args(["stash", "pop"]).run(self); - } - } - /// Updates a submodule, and exits with a failure if submodule management /// is disabled and the submodule does not exist. /// @@ -596,7 +487,7 @@ impl Build { if cfg!(test) && !self.config.submodules() { return; } - self.update_submodule(submodule); + self.config.update_submodule(submodule); let absolute_path = self.config.src.join(submodule); if dir_is_empty(&absolute_path) { let maybe_enable = if !self.config.submodules() @@ -644,7 +535,7 @@ impl Build { let path = Path::new(submodule); // Don't update the submodule unless it's already been cloned. if GitInfo::new(false, path).is_managed_git_subrepository() { - self.update_submodule(submodule); + self.config.update_submodule(submodule); } } } @@ -657,7 +548,7 @@ impl Build { } if GitInfo::new(false, Path::new(submodule)).is_managed_git_subrepository() { - self.update_submodule(submodule); + self.config.update_submodule(submodule); } } @@ -1056,11 +947,29 @@ Executed at: {executed_at}"#, } }; - let fail = |message: &str| { + let fail = |message: &str, output: CommandOutput| -> ! { if self.is_verbose() { println!("{message}"); } else { - println!("Command has failed. Rerun with -v to see more details."); + let (stdout, stderr) = (output.stdout_if_present(), output.stderr_if_present()); + // If the command captures output, the user would not see any indication that + // it has failed. In this case, print a more verbose error, since to provide more + // context. + if stdout.is_some() || stderr.is_some() { + if let Some(stdout) = + output.stdout_if_present().take_if(|s| !s.trim().is_empty()) + { + println!("STDOUT:\n{stdout}\n"); + } + if let Some(stderr) = + output.stderr_if_present().take_if(|s| !s.trim().is_empty()) + { + println!("STDERR:\n{stderr}\n"); + } + println!("Command {command:?} has failed. Rerun with -v to see more details."); + } else { + println!("Command has failed. Rerun with -v to see more details."); + } } exit!(1); }; @@ -1069,14 +978,14 @@ Executed at: {executed_at}"#, match command.failure_behavior { BehaviorOnFailure::DelayFail => { if self.fail_fast { - fail(&message); + fail(&message, output); } let mut failures = self.delayed_failures.borrow_mut(); failures.push(message); } BehaviorOnFailure::Exit => { - fail(&message); + fail(&message, output); } BehaviorOnFailure::Ignore => { // If failures are allowed, either the error has been printed already @@ -1774,21 +1683,20 @@ Executed at: {executed_at}"#, } } if let Ok(()) = fs::hard_link(&src, dst) { - // Attempt to "easy copy" by creating a hard link - // (symlinks don't work on windows), but if that fails - // just fall back to a slow `copy` operation. + // Attempt to "easy copy" by creating a hard link (symlinks are priviledged on windows), + // but if that fails just fall back to a slow `copy` operation. } else { if let Err(e) = fs::copy(&src, dst) { panic!("failed to copy `{}` to `{}`: {}", src.display(), dst.display(), e) } t!(fs::set_permissions(dst, metadata.permissions())); + // Restore file times because changing permissions on e.g. Linux using `chmod` can cause + // file access time to change. let file_times = fs::FileTimes::new() .set_accessed(t!(metadata.accessed())) .set_modified(t!(metadata.modified())); - - let dst_file = t!(fs::File::open(dst)); - t!(dst_file.set_times(file_times)); + t!(set_file_times(dst, file_times)); } } diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index c629f04c00e..51a25104e4c 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -230,4 +230,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Warning, summary: "./x test --rustc-args was renamed to --compiletest-rustc-args as it only applies there. ./x miri --rustc-args was also removed.", }, + ChangeInfo { + change_id: 129295, + severity: ChangeSeverity::Info, + summary: "The `build.profiler` option now tries to use source code from `download-ci-llvm` if possible, instead of checking out the `src/llvm-project` submodule.", + }, ]; diff --git a/src/bootstrap/src/utils/exec.rs b/src/bootstrap/src/utils/exec.rs index 9f0d0b7e969..530d760a584 100644 --- a/src/bootstrap/src/utils/exec.rs +++ b/src/bootstrap/src/utils/exec.rs @@ -291,6 +291,11 @@ impl CommandOutput { .expect("Cannot parse process stdout as UTF-8") } + #[must_use] + pub fn stdout_if_present(&self) -> Option { + self.stdout.as_ref().and_then(|s| String::from_utf8(s.clone()).ok()) + } + #[must_use] pub fn stdout_if_ok(&self) -> Option { if self.is_success() { Some(self.stdout()) } else { None } @@ -303,6 +308,11 @@ impl CommandOutput { ) .expect("Cannot parse process stderr as UTF-8") } + + #[must_use] + pub fn stderr_if_present(&self) -> Option { + self.stderr.as_ref().and_then(|s| String::from_utf8(s.clone()).ok()) + } } impl Default for CommandOutput { diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs index 65e75f114bb..a856c99ff55 100644 --- a/src/bootstrap/src/utils/helpers.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -544,3 +544,15 @@ pub fn get_closest_merge_base_commit( Ok(output_result(git.as_command_mut())?.trim().to_owned()) } + +/// Sets the file times for a given file at `path`. +pub fn set_file_times>(path: P, times: fs::FileTimes) -> io::Result<()> { + // Windows requires file to be writable to modify file times. But on Linux CI the file does not + // need to be writable to modify file times and might be read-only. + let f = if cfg!(windows) { + fs::File::options().write(true).open(path)? + } else { + fs::File::open(path)? + }; + f.set_times(times) +} diff --git a/src/bootstrap/src/utils/helpers/tests.rs b/src/bootstrap/src/utils/helpers/tests.rs index 103c4d26a18..86016a91e49 100644 --- a/src/bootstrap/src/utils/helpers/tests.rs +++ b/src/bootstrap/src/utils/helpers/tests.rs @@ -3,7 +3,8 @@ use std::io::Write; use std::path::PathBuf; use crate::utils::helpers::{ - check_cfg_arg, extract_beta_rev, hex_encode, make, program_out_of_date, symlink_dir, + check_cfg_arg, extract_beta_rev, hex_encode, make, program_out_of_date, set_file_times, + symlink_dir, }; use crate::{Config, Flags}; @@ -92,3 +93,25 @@ fn test_symlink_dir() { #[cfg(not(windows))] fs::remove_file(link_path).unwrap(); } + +#[test] +fn test_set_file_times_sanity_check() { + let config = + Config::parse(Flags::parse(&["check".to_owned(), "--config=/does/not/exist".to_owned()])); + let tempfile = config.tempdir().join(".tmp-file"); + + { + File::create(&tempfile).unwrap().write_all(b"dummy value").unwrap(); + assert!(tempfile.exists()); + } + + // This might only fail on Windows (if file is default read-only then we try to modify file + // times). + let unix_epoch = std::time::SystemTime::UNIX_EPOCH; + let target_time = fs::FileTimes::new().set_accessed(unix_epoch).set_modified(unix_epoch); + set_file_times(&tempfile, target_time).unwrap(); + + let found_metadata = fs::metadata(tempfile).unwrap(); + assert_eq!(found_metadata.accessed().unwrap(), unix_epoch); + assert_eq!(found_metadata.modified().unwrap(), unix_epoch) +} diff --git a/src/bootstrap/src/utils/tarball.rs b/src/bootstrap/src/utils/tarball.rs index 3f7f6214cf6..3c6c7a7fa18 100644 --- a/src/bootstrap/src/utils/tarball.rs +++ b/src/bootstrap/src/utils/tarball.rs @@ -9,6 +9,7 @@ use std::path::{Path, PathBuf}; use crate::core::build_steps::dist::distdir; use crate::core::builder::{Builder, Kind}; +use crate::core::config::BUILDER_CONFIG_FILENAME; use crate::utils::exec::BootstrapCommand; use crate::utils::helpers::{move_file, t}; use crate::utils::{channel, helpers}; @@ -320,7 +321,7 @@ impl<'a> Tarball<'a> { // Add config file if present. if let Some(config) = &self.builder.config.config { - self.add_renamed_file(config, &self.overlay_dir, "builder-config"); + self.add_renamed_file(config, &self.overlay_dir, BUILDER_CONFIG_FILENAME); } for file in self.overlay.legal_and_readme() { diff --git a/src/ci/docker/README.md b/src/ci/docker/README.md index 985e3b37422..876787c30e5 100644 --- a/src/ci/docker/README.md +++ b/src/ci/docker/README.md @@ -266,9 +266,9 @@ For targets: `loongarch64-unknown-linux-gnu` - Target options > Bitness = 64-bit - Operating System > Target OS = linux - Operating System > Linux kernel version = 5.19.16 -- Binary utilities > Version of binutils = 2.40 +- Binary utilities > Version of binutils = 2.42 - C-library > glibc version = 2.36 -- C compiler > gcc version = 13.2.0 +- C compiler > gcc version = 14.2.0 - C compiler > C++ = ENABLE -- to cross compile LLVM ### `loongarch64-linux-musl.defconfig` @@ -282,9 +282,9 @@ For targets: `loongarch64-unknown-linux-musl` - Target options > Bitness = 64-bit - Operating System > Target OS = linux - Operating System > Linux kernel version = 5.19.16 -- Binary utilities > Version of binutils = 2.41 +- Binary utilities > Version of binutils = 2.42 - C-library > musl version = 1.2.5 -- C compiler > gcc version = 13.2.0 +- C compiler > gcc version = 14.2.0 - C compiler > C++ = ENABLE -- to cross compile LLVM ### `mips-linux-gnu.defconfig` diff --git a/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile index d3956651663..865a9e32fa9 100644 --- a/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile @@ -3,8 +3,8 @@ FROM ubuntu:22.04 COPY scripts/cross-apt-packages.sh /scripts/ RUN sh /scripts/cross-apt-packages.sh -COPY scripts/crosstool-ng.sh /scripts/ -RUN sh /scripts/crosstool-ng.sh +COPY scripts/crosstool-ng-git.sh /scripts/ +RUN sh /scripts/crosstool-ng-git.sh COPY scripts/rustbuild-setup.sh /scripts/ RUN sh /scripts/rustbuild-setup.sh diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile index 61e9694f1e2..e857f38e68a 100644 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile @@ -62,9 +62,9 @@ COPY host-x86_64/dist-x86_64-linux/build-clang.sh /tmp/ RUN ./build-clang.sh ENV CC=clang CXX=clang++ -# rustc's LLVM needs zstd. -COPY scripts/zstd.sh /tmp/ -RUN ./zstd.sh +# Build zstd to enable `llvm.libzstd`. +COPY host-x86_64/dist-x86_64-linux/build-zstd.sh /tmp/ +RUN ./build-zstd.sh COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/scripts/zstd.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-zstd.sh similarity index 100% rename from src/ci/docker/scripts/zstd.sh rename to src/ci/docker/host-x86_64/dist-x86_64-linux/build-zstd.sh diff --git a/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/Cargo.toml b/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/Cargo.toml index 2d17cf7d47a..976245f5bdd 100644 --- a/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/Cargo.toml +++ b/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/Cargo.toml @@ -4,7 +4,7 @@ version = "0.0.0" edition = "2021" [workspace] -resolver = "1" +resolver = "2" [dependencies] r-efi = "4.1.0" diff --git a/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile index 19683317126..83c2aa8cfb3 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile @@ -28,5 +28,6 @@ ENV RUST_CONFIGURE_ARGS \ --build=x86_64-unknown-linux-gnu \ --enable-sanitizers \ --enable-profiler \ - --enable-compiler-docs + --enable-compiler-docs \ + --set llvm.libzstd=true ENV SCRIPT python3 ../x.py --stage 2 test diff --git a/src/ci/docker/scripts/crosstool-ng-git.sh b/src/ci/docker/scripts/crosstool-ng-git.sh index 2a10e262df8..e86810ae613 100644 --- a/src/ci/docker/scripts/crosstool-ng-git.sh +++ b/src/ci/docker/scripts/crosstool-ng-git.sh @@ -2,7 +2,7 @@ set -ex URL=https://github.com/crosstool-ng/crosstool-ng -REV=c64500d94be92ed1bcdfdef911048a14e216a5e1 +REV=ed12fa68402f58e171a6f79500f73f4781fdc9e5 mkdir crosstool-ng cd crosstool-ng diff --git a/src/ci/docker/scripts/rfl-build.sh b/src/ci/docker/scripts/rfl-build.sh index d690aac27fa..389abb2fdd3 100755 --- a/src/ci/docker/scripts/rfl-build.sh +++ b/src/ci/docker/scripts/rfl-build.sh @@ -2,7 +2,7 @@ set -euo pipefail -LINUX_VERSION=v6.11-rc1 +LINUX_VERSION=4c7864e81d8bbd51036dacf92fb0a400e13aaeee # Build rustc, rustdoc and cargo ../x.py build --stage 1 library rustdoc @@ -28,7 +28,7 @@ rm -rf linux || true # Download Linux at a specific commit mkdir -p linux git -C linux init -git -C linux remote add origin https://github.com/torvalds/linux.git +git -C linux remote add origin https://github.com/Rust-for-Linux/linux.git git -C linux fetch --depth 1 origin ${LINUX_VERSION} git -C linux checkout FETCH_HEAD diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 638f14ad53f..4de44c6dd39 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -285,8 +285,10 @@ auto: - image: dist-apple-various env: - SCRIPT: ./x.py dist bootstrap --include-default-paths --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim - RUST_CONFIGURE_ARGS: --enable-sanitizers --enable-profiler --set rust.jemalloc + SCRIPT: ./x.py dist bootstrap --include-default-paths --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim,aarch64-apple-ios-macabi,x86_64-apple-ios-macabi + # Mac Catalyst cannot currently compile the sanitizer: + # https://github.com/rust-lang/rust/issues/129069 + RUST_CONFIGURE_ARGS: --enable-sanitizers --enable-profiler --set rust.jemalloc --set target.aarch64-apple-ios-macabi.sanitizers=false --set target.x86_64-apple-ios-macabi.sanitizers=false RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.12 SELECT_XCODE: /Applications/Xcode_14.3.1.app diff --git a/src/doc/book b/src/doc/book index 67fa5367680..e7d217be2a7 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 67fa536768013d9d5a13f3a06790521d511ef711 +Subproject commit e7d217be2a75ef1753f0988d6ccaba4d7e376259 diff --git a/src/doc/edition-guide b/src/doc/edition-guide index 5454de3d12b..eeba2cb9c37 160000 --- a/src/doc/edition-guide +++ b/src/doc/edition-guide @@ -1 +1 @@ -Subproject commit 5454de3d12b9ccc6375b629cf7ccda8264640aac +Subproject commit eeba2cb9c37ab74118a4fb5e5233f7397e4a91f8 diff --git a/src/doc/embedded-book b/src/doc/embedded-book index 019f3928d8b..ff5d61d56f1 160000 --- a/src/doc/embedded-book +++ b/src/doc/embedded-book @@ -1 +1 @@ -Subproject commit 019f3928d8b939ec71b63722dcc2e46330156441 +Subproject commit ff5d61d56f11e1986bfa9652c6aff7731576c37d diff --git a/src/doc/nomicon b/src/doc/nomicon index 0ebdacadbda..14649f15d23 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 0ebdacadbda8ce2cd8fbf93985e15af61a7ab895 +Subproject commit 14649f15d232d509478206ee9ed5105641aa60d0 diff --git a/src/doc/reference b/src/doc/reference index 2e191814f16..0668397076d 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 2e191814f163ee1e77e2d6094eee4dd78a289c5b +Subproject commit 0668397076da350c404dadcf07b6cbc433ad3743 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 89aecb6951b..859786c5bc9 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 89aecb6951b77bc746da73df8c9f2b2ceaad494a +Subproject commit 859786c5bc99301bbc22fc631a5c2b341860da08 diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide index 0c4d55cb59f..fa928a6d19e 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit 0c4d55cb59fe440d1a630e4e5774d043968edb3f +Subproject commit fa928a6d19e1666d8d811dfe3fd35cdad3b4e459 diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 467fd6f43e4..b3a74a7716b 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -49,6 +49,7 @@ - [aarch64-unknown-teeos](platform-support/aarch64-unknown-teeos.md) - [\*-espidf](platform-support/esp-idf.md) - [\*-unknown-fuchsia](platform-support/fuchsia.md) + - [\*-unknown-trusty](platform-support/trusty.md) - [\*-kmc-solid_\*](platform-support/kmc-solid.md) - [csky-unknown-linux-gnuabiv2\*](platform-support/csky-unknown-linux-gnuabiv2.md) - [hexagon-unknown-linux-musl](platform-support/hexagon-unknown-linux-musl.md) @@ -61,6 +62,7 @@ - [mipsisa\*r6\*-unknown-linux-gnu\*](platform-support/mips-release-6.md) - [nvptx64-nvidia-cuda](platform-support/nvptx64-nvidia-cuda.md) - [powerpc-unknown-openbsd](platform-support/powerpc-unknown-openbsd.md) + - [powerpc-unknown-linux-muslspe](platform-support/powerpc-unknown-linux-muslspe.md) - [powerpc64-ibm-aix](platform-support/aix.md) - [riscv32im-risc0-zkvm-elf](platform-support/riscv32im-risc0-zkvm-elf.md) - [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md) @@ -80,6 +82,7 @@ - [wasm32-wasip1](platform-support/wasm32-wasip1.md) - [wasm32-wasip1-threads](platform-support/wasm32-wasip1-threads.md) - [wasm32-wasip2](platform-support/wasm32-wasip2.md) + - [wasm32-unknown-unknown](platform-support/wasm32-unknown-unknown.md) - [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md) - [\*-win7-windows-msvc](platform-support/win7-windows-msvc.md) - [x86_64-fortanix-unknown-sgx](platform-support/x86_64-fortanix-unknown-sgx.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index bd12172ecbb..0d79e5f4114 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -136,6 +136,7 @@ so Rustup may install the documentation for a similar tier 1 target instead. target | std | notes -------|:---:|------- [`aarch64-apple-ios`](platform-support/apple-ios.md) | ✓ | ARM64 iOS +[`aarch64-apple-ios-macabi`](platform-support/apple-ios-macabi.md) | ✓ | Mac Catalyst on ARM64 [`aarch64-apple-ios-sim`](platform-support/apple-ios.md) | ✓ | Apple iOS Simulator on ARM64 `aarch64-fuchsia` | ✓ | Alias for `aarch64-unknown-fuchsia` [`aarch64-unknown-fuchsia`](platform-support/fuchsia.md) | ✓ | ARM64 Fuchsia @@ -191,11 +192,12 @@ target | std | notes [`thumbv8m.main-none-eabi`](platform-support/thumbv8m.main-none-eabi.md) | * | Bare Armv8-M Mainline [`thumbv8m.main-none-eabihf`](platform-support/thumbv8m.main-none-eabi.md) | * | Bare Armv8-M Mainline, hardfloat `wasm32-unknown-emscripten` | ✓ | WebAssembly via Emscripten -`wasm32-unknown-unknown` | ✓ | WebAssembly +[`wasm32-unknown-unknown`](platform-support/wasm32-unknown-unknown.md) | ✓ | WebAssembly `wasm32-wasi` | ✓ | WebAssembly with WASI (undergoing a [rename to `wasm32-wasip1`][wasi-rename]) [`wasm32-wasip1`](platform-support/wasm32-wasip1.md) | ✓ | WebAssembly with WASI [`wasm32-wasip1-threads`](platform-support/wasm32-wasip1-threads.md) | ✓ | WebAssembly with WASI Preview 1 and threads [`x86_64-apple-ios`](platform-support/apple-ios.md) | ✓ | 64-bit x86 iOS +[`x86_64-apple-ios-macabi`](platform-support/apple-ios-macabi.md) | ✓ | Mac Catalyst on x86_64 [`x86_64-fortanix-unknown-sgx`](platform-support/x86_64-fortanix-unknown-sgx.md) | ✓ | [Fortanix ABI] for 64-bit Intel SGX `x86_64-fuchsia` | ✓ | Alias for `x86_64-unknown-fuchsia` [`x86_64-unknown-fuchsia`](platform-support/fuchsia.md) | ✓ | 64-bit x86 Fuchsia @@ -245,7 +247,6 @@ target | std | host | notes -------|:---:|:----:|------- [`arm64e-apple-ios`](platform-support/arm64e-apple-ios.md) | ✓ | | ARM64e Apple iOS [`arm64e-apple-darwin`](platform-support/arm64e-apple-darwin.md) | ✓ | ✓ | ARM64e Apple Darwin -[`aarch64-apple-ios-macabi`](platform-support/apple-ios-macabi.md) | ✓ | | Apple Catalyst on ARM64 [`aarch64-apple-tvos`](platform-support/apple-tvos.md) | ✓ | | ARM64 tvOS [`aarch64-apple-tvos-sim`](platform-support/apple-tvos.md) | ✓ | | ARM64 tvOS Simulator [`aarch64-apple-watchos`](platform-support/apple-watchos.md) | ✓ | | ARM64 Apple WatchOS @@ -263,6 +264,7 @@ target | std | host | notes [`aarch64-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | ARM64 NetBSD [`aarch64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | ARM64 OpenBSD [`aarch64-unknown-redox`](platform-support/redox.md) | ✓ | | ARM64 Redox OS +[`aarch64-unknown-trusty`](platform-support/trusty.md) | ? | | `aarch64-uwp-windows-msvc` | ✓ | | [`aarch64-wrs-vxworks`](platform-support/vxworks.md) | ✓ | | ARM64 VxWorks OS `aarch64_be-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (big-endian, ILP32 ABI) @@ -282,6 +284,7 @@ target | std | host | notes [`armv7-unknown-linux-uclibceabihf`](platform-support/armv7-unknown-linux-uclibceabihf.md) | ✓ | ? | Armv7-A Linux with uClibc, hardfloat `armv7-unknown-freebsd` | ✓ | ✓ | Armv7-A FreeBSD [`armv7-unknown-netbsd-eabihf`](platform-support/netbsd.md) | ✓ | ✓ | Armv7-A NetBSD w/hard-float +[`armv7-unknown-trusty`](platform-support/trusty.md) | ? | | [`armv7-wrs-vxworks-eabihf`](platform-support/vxworks.md) | ✓ | | Armv7-A for VxWorks [`armv7a-kmc-solid_asp3-eabi`](platform-support/kmc-solid.md) | ✓ | | ARM SOLID with TOPPERS/ASP3 [`armv7a-kmc-solid_asp3-eabihf`](platform-support/kmc-solid.md) | ✓ | | ARM SOLID with TOPPERS/ASP3, hardfloat @@ -332,6 +335,7 @@ target | std | host | notes `msp430-none-elf` | * | | 16-bit MSP430 microcontrollers `powerpc-unknown-linux-gnuspe` | ✓ | | PowerPC SPE Linux `powerpc-unknown-linux-musl` | ? | | PowerPC Linux with musl 1.2.3 +[`powerpc-unknown-linux-muslspe`](platform-support/powerpc-unknown-linux-muslspe.md) | ? | | PowerPC SPE Linux [`powerpc-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD 32-bit powerpc systems [`powerpc-unknown-openbsd`](platform-support/powerpc-unknown-openbsd.md) | * | | [`powerpc-wrs-vxworks-spe`](platform-support/vxworks.md) | ✓ | | @@ -370,7 +374,6 @@ target | std | host | notes `thumbv7neon-unknown-linux-musleabihf` | ? | | Thumb2-mode Armv7-A Linux with NEON, musl 1.2.3 [`wasm32-wasip2`](platform-support/wasm32-wasip2.md) | ✓ | | WebAssembly [`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? | | WebAssembly -[`x86_64-apple-ios-macabi`](platform-support/apple-ios-macabi.md) | ✓ | | Apple Catalyst on x86_64 [`x86_64-apple-tvos`](platform-support/apple-tvos.md) | ✓ | | x86 64-bit tvOS [`x86_64-apple-watchos-sim`](platform-support/apple-watchos.md) | ✓ | | x86 64-bit Apple WatchOS simulator [`x86_64-pc-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX Neutrino 7.1 RTOS | diff --git a/src/doc/rustc/src/platform-support/android.md b/src/doc/rustc/src/platform-support/android.md index 9ddf00e3a50..96499b0d801 100644 --- a/src/doc/rustc/src/platform-support/android.md +++ b/src/doc/rustc/src/platform-support/android.md @@ -61,3 +61,8 @@ Currently the `riscv64-linux-android` target requires the following architecture * `Zba` (address calculation instructions) * `Zbb` (base instructions) * `Zbs` (single-bit instructions) + +### aarch64-linux-android on Nightly compilers + +As soon as `-Zfixed-x18` compiler flag is supplied, the [`ShadowCallStack` sanitizer](https://releases.llvm.org/7.0.1/tools/clang/docs/ShadowCallStack.html) +instrumentation is also made avaiable by supplying the second compiler flag `-Zsanitizer=shadow-call-stack`. diff --git a/src/doc/rustc/src/platform-support/apple-ios-macabi.md b/src/doc/rustc/src/platform-support/apple-ios-macabi.md index 15ba31e0f06..678630873b1 100644 --- a/src/doc/rustc/src/platform-support/apple-ios-macabi.md +++ b/src/doc/rustc/src/platform-support/apple-ios-macabi.md @@ -2,7 +2,7 @@ Apple Mac Catalyst targets. -**Tier: 3** +**Tier: 2 (without Host Tools)** - `aarch64-apple-ios-macabi`: Mac Catalyst on ARM64. - `x86_64-apple-ios-macabi`: Mac Catalyst on 64-bit x86. @@ -32,15 +32,19 @@ case `IPHONEOS_DEPLOYMENT_TARGET`. ## Building the target -The targets can be built by enabling them for a `rustc` build in -`config.toml`, by adding, for example: - -```toml -[build] -target = ["aarch64-apple-ios-macabi", "x86_64-apple-ios-macabi"] +The targets are distributed through `rustup`, and can be installed using one +of: +```console +$ rustup target add aarch64-apple-ios-macabi +$ rustup target add x86_64-apple-ios-macabi ``` -Using the unstable `-Zbuild-std` with a nightly Cargo may also work. +### Sanitizers + +Due to CMake having poor support for Mac Catalyst, sanitizer runtimes are not +currently available, see [#129069]. + +[#129069]: https://github.com/rust-lang/rust/issues/129069 ## Building Rust programs diff --git a/src/doc/rustc/src/platform-support/powerpc-unknown-linux-muslspe.md b/src/doc/rustc/src/platform-support/powerpc-unknown-linux-muslspe.md new file mode 100644 index 00000000000..4c416b51929 --- /dev/null +++ b/src/doc/rustc/src/platform-support/powerpc-unknown-linux-muslspe.md @@ -0,0 +1,32 @@ +# powerpc-unknown-linux-muslspe + +**Tier: 3** + +This target is very similar to already existing ones like `powerpc_unknown_linux_musl` and `powerpc_unknown_linux_gnuspe`. +This one has PowerPC SPE support for musl. Unfortunately, the last supported gcc version with PowerPC SPE is 8.4.0. + +## Target maintainers + +- [@BKPepe](https://github.com/BKPepe) + +## Requirements + +This target is cross-compiled. There is no support for `std`. There is no +default allocator, but it's possible to use `alloc` by supplying an allocator. + +This target generated binaries in the ELF format. + +## Building the target + +This target was tested and used within the `OpenWrt` build system for CZ.NIC Turris 1.x routers using Freescale P2020. + +## Building Rust programs + +Rust does not yet ship pre-compiled artifacts for this target. To compile for +this target, you will either need to build Rust with the target enabled (see +"Building the target" above), or build your own copy of `core` by using +`build-std` or similar. + +## Testing + +This is a cross-compiled target and there is no support to run rustc test suite. diff --git a/src/doc/rustc/src/platform-support/trusty.md b/src/doc/rustc/src/platform-support/trusty.md new file mode 100644 index 00000000000..dec3b96ff64 --- /dev/null +++ b/src/doc/rustc/src/platform-support/trusty.md @@ -0,0 +1,51 @@ +# `aarch64-unknown-trusty` and `armv7-unknown-trusty` + +**Tier: 3** + +[Trusty] is a secure Operating System that provides a Trusted Execution +Environment (TEE) for Android. + +## Target maintainers + +- Nicole LeGare (@randomPoison) +- Stephen Crane (@rinon) +- As a fallback trusty-dev-team@google.com can be contacted + +## Requirements + +These targets are cross-compiled. They have no special requirements for the host. + +Support for the standard library is work-in-progress. It is expected that +they will support alloc with the default allocator, and partially support std. + +Trusty uses the ELF file format. + +## Building the target + +The targets can be built by enabling them for a `rustc` build, for example: + +```toml +[build] +build-stage = 1 +target = ["aarch64-unknown-trusty", "armv7-unknown-trusty"] +``` + +## Building Rust programs + +There is currently no supported way to build a Trusty app with Cargo. You can +follow the [Trusty build instructions] to build the Trusty kernel along with any +Rust apps that are setup in the project. + +## Testing + +See the [Trusty build instructions] for information on how to build Rust code +within the main Trusty project. The main project also includes infrastructure +for testing Rust applications within a QEMU emulator. + +## Cross-compilation toolchains and C code + +See the [Trusty build instructions] for information on how C code is built +within Trusty. + +[Trusty]: https://source.android.com/docs/security/features/trusty +[Trusty build instructions]: https://source.android.com/docs/security/features/trusty/download-and-build diff --git a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md new file mode 100644 index 00000000000..12b7817c382 --- /dev/null +++ b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md @@ -0,0 +1,197 @@ +# `wasm32-unknown-unknown` + +**Tier: 2** + +The `wasm32-unknown-unknown` target is a WebAssembly compilation target which +does not import any functions from the host for the standard library. This is +the "minimal" WebAssembly in the sense of making the fewest assumptions about +the host environment. This target is often used when compiling to the web or +JavaScript environments as there is no standard for what functions can be +imported on the web. This target can also be useful for creating minimal or +bare-bones WebAssembly binaries. + +The `wasm32-unknown-unknown` target has support for the Rust standard library +but many parts of the standard library do not work and return errors. For +example `println!` does nothing, `std::fs` always return errors, and +`std::thread::spawn` will panic. There is no means by which this can be +overridden. For a WebAssembly target that more fully supports the standard +library see the [`wasm32-wasip1`](./wasm32-wasip1.md) or +[`wasm32-wasip2`](./wasm32-wasip2.md) targets. + +The `wasm32-unknown-unknown` target has full support for the `core` and `alloc` +crates. It additionally supports the `HashMap` type in the `std` crate, although +hash maps are not randomized like they are on other platforms. + +One existing user of this target (please feel free to edit and expand this list +too) is the [`wasm-bindgen` project](https://github.com/rustwasm/wasm-bindgen) +which facilitates Rust code interoperating with JavaScript code. Note, though, +that not all uses of `wasm32-unknown-unknown` are using JavaScript and the web. + +## Target maintainers + +When this target was added to the compiler, platform-specific documentation here +was not maintained at that time. This means that the list below is not +exhaustive, and there are more interested parties in this target. That being +said, those interested in maintaining this target are: + +- Alex Crichton, https://github.com/alexcrichton + +## Requirements + +This target is cross-compiled. The target includes support for `std` itself, +but as mentioned above many pieces of functionality that require an operating +system do not work and will return errors. + +This target currently has no equivalent in C/C++. There is no C/C++ toolchain +for this target. While interop is theoretically possible it's recommended to +instead use one of: + +* `wasm32-unknown-emscripten` - for web-based use cases the Emscripten + toolchain is typically chosen for running C/C++. +* [`wasm32-wasip1`](./wasm32-wasip1.md) - the wasi-sdk toolchain is used to + compile C/C++ on this target and can interop with Rust code. WASI works on + the web so far as there's no blocker, but an implementation of WASI APIs + must be either chosen or reimplemented. + +This target has no build requirements beyond what's in-tree in the Rust +repository. Linking binaries requires LLD to be enabled for the `wasm-ld` +driver. This target uses the `dlmalloc` crate as the default global allocator. + +## Building the target + +Building this target can be done by: + +* Configure the `wasm32-unknown-unknown` target to get built. +* Configure LLD to be built. +* Ensure the `WebAssembly` target backend is not disabled in LLVM. + +These are all controlled through `config.toml` options. It should be possible +to build this target on any platform. + +## Building Rust programs + +Rust programs can be compiled by adding this target via rustup: + +```sh +$ rustup target add wasm32-unknown-unknown +``` + +and then compiling with the target: + +```sh +$ rustc foo.rs --target wasm32-unknown-unknown +$ file foo.wasm +``` + +## Cross-compilation + +This target can be cross-compiled from any host. + +## Testing + +This target is not tested in CI for the rust-lang/rust repository. Many tests +must be disabled to run on this target and failures are non-obvious because +`println!` doesn't work in the standard library. It's recommended to test the +`wasm32-wasip1` target instead for WebAssembly compatibility. + +## Conditionally compiling code + +It's recommended to conditionally compile code for this target with: + +```text +#[cfg(all(target_family = "wasm", target_os = "unknown"))] +``` + +Note that there is no way to tell via `#[cfg]` whether code will be running on +the web or not. + +## Enabled WebAssembly features + +WebAssembly is an evolving standard which adds new features such as new +instructions over time. This target's default set of supported WebAssembly +features will additionally change over time. The `wasm32-unknown-unknown` target +inherits the default settings of LLVM which typically matches the default +settings of Emscripten as well. + +Changes to WebAssembly go through a [proposals process][proposals] but reaching +the final stage (stage 5) does not automatically mean that the feature will be +enabled in LLVM and Rust by default. At this time the general guidance is that +features must be present in most engines for a "good chunk of time" before +they're enabled in LLVM by default. There is currently no exact number of +months or engines that are required to enable features by default. + +[proposals]: https://github.com/WebAssembly/proposals + +As of the time of this writing the proposals that are enabled by default (the +`generic` CPU in LLVM terminology) are: + +* `multivalue` +* `mutable-globals` +* `reference-types` +* `sign-ext` + +If you're compiling WebAssembly code for an engine that does not support a +feature in LLVM's default feature set then the feature must be disabled at +compile time. Note, though, that enabled features may be used in the standard +library or precompiled libraries shipped via rustup. This means that not only +does your own code need to be compiled with the correct set of flags but the +Rust standard library additionally must be recompiled. + +Compiling all code for the initial release of WebAssembly looks like: + +```sh +$ export RUSTFLAGS=-Ctarget-cpu=mvp +$ cargo +nightly build -Zbuild-std=panic_abort,std --target wasm32-unknown-unknown +``` + +Here the `mvp` "cpu" is a placeholder in LLVM for disabling all supported +features by default. Cargo's `-Zbuild-std` feature, a Nightly Rust feature, is +then used to recompile the standard library in addition to your own code. This +will produce a binary that uses only the original WebAssembly features by +default and no proposals since its inception. + +To enable individual features it can be done with `-Ctarget-feature=+foo`. +Available features for Rust code itself are documented in the [reference] and +can also be found through: + +```sh +$ rustc -Ctarget-feature=help --target wasm32-unknown-unknown +``` + +You'll need to consult your WebAssembly engine's documentation to learn more +about the supported WebAssembly features the engine has. + +[reference]: https://doc.rust-lang.org/reference/attributes/codegen.html#wasm32-or-wasm64 + +Note that it is still possible for Rust crates and libraries to enable +WebAssembly features on a per-function level. This means that the build +command above may not be sufficient to disable all WebAssembly features. If the +final binary still has SIMD instructions, for example, the function in question +will need to be found and the crate in question will likely contain something +like: + +```rust,ignore (not-always-compiled-to-wasm) +#[target_feature(enable = "simd128")] +fn foo() { + // ... +} +``` + +In this situation there is no compiler flag to disable emission of SIMD +instructions and the crate must instead be modified to not include this function +at compile time either by default or through a Cargo feature. For crate authors +it's recommended to avoid `#[target_feature(enable = "...")]` except where +necessary and instead use: + +```rust,ignore (not-always-compiled-to-wasm) +#[cfg(target_feature = "simd128")] +fn foo() { + // ... +} +``` + +That is to say instead of enabling target features it's recommended to +conditionally compile code instead. This is notably different to the way native +platforms such as x86\_64 work, and this is due to the fact that WebAssembly +binaries must only contain code the engine understands. Native binaries work so +long as the CPU doesn't execute unknown code dynamically at runtime. diff --git a/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md b/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md index c3eda26ca8e..994c0f4bbb3 100644 --- a/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md +++ b/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md @@ -162,3 +162,17 @@ It's recommended to conditionally compile code for this target with: Prior to Rust 1.80 the `target_env = "p1"` key was not set. Currently the `target_feature = "atomics"` is Nightly-only. Note that the precise `#[cfg]` necessary to detect this target may change as the target becomes more stable. + +## Enabled WebAssembly features + +The default set of WebAssembly features enabled for compilation includes two +more features in addition to that which +[`wasm32-unknown-unknown`](./wasm32-unknown-unknown.md) enables: + +* `bulk-memory` +* `atomics` + +For more information about features see the documentation for +[`wasm32-unknown-unknown`](./wasm32-unknown-unknown.md), but note that the +`mvp` CPU in LLVM does not support this target as it's required that +`bulk-memory`, `atomics`, and `mutable-globals` are all enabled. diff --git a/src/doc/rustc/src/platform-support/wasm32-wasip1.md b/src/doc/rustc/src/platform-support/wasm32-wasip1.md index fb70bbdc2b4..0e4def6768d 100644 --- a/src/doc/rustc/src/platform-support/wasm32-wasip1.md +++ b/src/doc/rustc/src/platform-support/wasm32-wasip1.md @@ -132,3 +132,9 @@ It's recommended to conditionally compile code for this target with: Note that the `target_env = "p1"` condition first appeared in Rust 1.80. Prior to Rust 1.80 the `target_env` condition was not set. + +## Enabled WebAssembly features + +The default set of WebAssembly features enabled for compilation is currently the +same as [`wasm32-unknown-unknown`](./wasm32-unknown-unknown.md). See the +documentation there for more information. diff --git a/src/doc/rustc/src/platform-support/wasm32-wasip2.md b/src/doc/rustc/src/platform-support/wasm32-wasip2.md index 1e53fbc178e..bb2348b201e 100644 --- a/src/doc/rustc/src/platform-support/wasm32-wasip2.md +++ b/src/doc/rustc/src/platform-support/wasm32-wasip2.md @@ -61,3 +61,9 @@ It's recommended to conditionally compile code for this target with: ```text #[cfg(all(target_os = "wasi", target_env = "p2"))] ``` + +## Enabled WebAssembly features + +The default set of WebAssembly features enabled for compilation is currently the +same as [`wasm32-unknown-unknown`](./wasm32-unknown-unknown.md). See the +documentation there for more information. diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 39f24a13143..ebbe141b6f5 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -515,6 +515,9 @@ pub fn no_documentation() {} Note that the third item is the crate root, which in this case is undocumented. +If you want the JSON output to be displayed on `stdout` instead of having a file generated, you can +use `-o -`. + ### `-w`/`--output-format`: output format `--output-format json` emits documentation in the experimental diff --git a/src/doc/rustdoc/src/write-documentation/documentation-tests.md b/src/doc/rustdoc/src/write-documentation/documentation-tests.md index 9526f33359e..7ed2e9720fe 100644 --- a/src/doc/rustdoc/src/write-documentation/documentation-tests.md +++ b/src/doc/rustdoc/src/write-documentation/documentation-tests.md @@ -376,6 +376,57 @@ that the code sample should be compiled using the respective edition of Rust. # fn foo() {} ``` +Starting in the 2024 edition[^edition-note], compatible doctests are merged as one before being +run. We combine doctests for performance reasons: the slowest part of doctests is to compile them. +Merging all of them into one file and compiling this new file, then running the doctests is much +faster. Whether doctests are merged or not, they are run in their own process. + +An example of time spent when running doctests: + +[sysinfo crate](https://crates.io/crates/sysinfo): + +```text +wall-time duration: 4.59s +total compile time: 27.067s +total runtime: 3.969s +``` + +Rust core library: + +```text +wall-time duration: 102s +total compile time: 775.204s +total runtime: 15.487s +``` + +[^edition-note]: This is based on the edition of the whole crate, not the edition of the individual +test case that may be specified in its code attribute. + +In some cases, doctests cannot be merged. For example, if you have: + +```rust +//! ``` +//! let location = std::panic::Location::caller(); +//! assert_eq!(location.line(), 4); +//! ``` +``` + +The problem with this code is that, if you change any other doctests, it'll likely break when +runing `rustdoc --test`, making it tricky to maintain. + +This is where the `standalone` attribute comes in: it tells `rustdoc` that a doctest +should not be merged with the others. So the previous code should use it: + +```rust +//! ```standalone +//! let location = std::panic::Location::caller(); +//! assert_eq!(location.line(), 4); +//! ``` +``` + +In this case, it means that the line information will not change if you add/remove other +doctests. + ### Custom CSS classes for code blocks ```rust diff --git a/src/doc/style-guide/src/items.md b/src/doc/style-guide/src/items.md index 8e1b1d80fb6..5ea8b6cd542 100644 --- a/src/doc/style-guide/src/items.md +++ b/src/doc/style-guide/src/items.md @@ -449,8 +449,8 @@ entries, format it across multiple lines as with a type alias. ## extern items When writing extern items (such as `extern "C" fn`), always specify the ABI. -For example, write `extern "C" fn foo ...`, not `extern fn foo ...`, or -`extern "C" { ... }`. +For example, write `extern "C" fn foo ...` or `unsafe extern "C" { ...}` +and avoid `extern fn foo ...` and `unsafe extern { ... }`. ## Imports (`use` statements) diff --git a/src/doc/unstable-book/src/compiler-flags/embed-source.md b/src/doc/unstable-book/src/compiler-flags/embed-source.md new file mode 100644 index 00000000000..01a11e37797 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/embed-source.md @@ -0,0 +1,12 @@ +# `embed-source` + +This flag controls whether the compiler embeds the program source code text into +the object debug information section. It takes one of the following values: + +* `y`, `yes`, `on` or `true`: put source code in debug info. +* `n`, `no`, `off`, `false` or no value: omit source code from debug info (the default). + +This flag is ignored in configurations that don't emit DWARF debug information +and is ignored on non-LLVM backends. `-Z embed-source` requires DWARFv5. Use +`-Z dwarf-version=5` to control the compiler's DWARF target version and `-g` to +enable debug info generation. diff --git a/src/doc/unstable-book/src/compiler-flags/fixed-x18.md b/src/doc/unstable-book/src/compiler-flags/fixed-x18.md index 8c8bff5fa29..b215bc84fbb 100644 --- a/src/doc/unstable-book/src/compiler-flags/fixed-x18.md +++ b/src/doc/unstable-book/src/compiler-flags/fixed-x18.md @@ -1,7 +1,7 @@ # `fixed-x18` This option prevents the compiler from using the x18 register. It is only -supported on aarch64. +supported on `aarch64`. From the [ABI spec][arm-abi]: @@ -23,6 +23,11 @@ Currently, the `-Zsanitizer=shadow-call-stack` flag is only supported on platforms that always treat x18 as a reserved register, and the `-Zfixed-x18` flag is not required to use the sanitizer on such platforms. However, the sanitizer may be supported on targets where this is not the case in the future. +One way to do so now on Nightly compilers is to explicitly supply this `-Zfixed-x18` +flag with `aarch64` targets, so that the sanitizer is available for instrumentation +on targets like `aarch64-unknown-none`, for instance. However, discretion is still +required to make sure that the runtime support is in place for this sanitizer +to be effective. It is undefined behavior for `-Zsanitizer=shadow-call-stack` code to call into code where x18 is a temporary register. On the other hand, when you are *not* diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md index 72b44e002b4..edc63a25ac1 100644 --- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md +++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md @@ -787,6 +787,10 @@ A runtime must be provided by the application or operating system. See the [Clang ShadowCallStack documentation][clang-scs] for more details. +* `aarch64-unknown-none` + +In addition to support from a runtime by the application or operating system, the `-Zfixed-x18` flag is also mandatory. + # ThreadSanitizer ThreadSanitizer is a data race detection tool. It is supported on the following diff --git a/src/doc/unstable-book/src/language-features/asm-const.md b/src/doc/unstable-book/src/language-features/asm-const.md deleted file mode 100644 index 670c4df414f..00000000000 --- a/src/doc/unstable-book/src/language-features/asm-const.md +++ /dev/null @@ -1,11 +0,0 @@ -# `asm_const` - -The tracking issue for this feature is: [#93332] - -[#93332]: https://github.com/rust-lang/rust/issues/93332 - ------------------------- - -This feature adds a `const ` operand type to `asm!` and `global_asm!`. -- `` must be an integer constant expression. -- The value of the expression is formatted as a string and substituted directly into the asm template string. diff --git a/src/doc/unstable-book/src/language-features/struct-target-features.md b/src/doc/unstable-book/src/language-features/struct-target-features.md new file mode 100644 index 00000000000..e814fe90072 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/struct-target-features.md @@ -0,0 +1,7 @@ +# `struct_target_features` + +The tracking issue for this feature is: [#129107] + +[#129107]: https://github.com/rust-lang/rust/issues/129107 + +------------------------ diff --git a/src/etc/completions/x.py.fish b/src/etc/completions/x.py.fish index 297dc11cd61..3a83c89280f 100644 --- a/src/etc/completions/x.py.fish +++ b/src/etc/completions/x.py.fish @@ -1,664 +1,690 @@ -complete -c x.py -n "__fish_use_subcommand" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_use_subcommand" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_use_subcommand" -l build -d 'build target of the stage0 compiler' -r -f -complete -c x.py -n "__fish_use_subcommand" -l host -d 'host targets to build' -r -f -complete -c x.py -n "__fish_use_subcommand" -l target -d 'target targets to build' -r -f -complete -c x.py -n "__fish_use_subcommand" -l exclude -d 'build paths to exclude' -r -F -complete -c x.py -n "__fish_use_subcommand" -l skip -d 'build paths to skip' -r -F -complete -c x.py -n "__fish_use_subcommand" -l rustc-error-format -r -f -complete -c x.py -n "__fish_use_subcommand" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" -complete -c x.py -n "__fish_use_subcommand" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f -complete -c x.py -n "__fish_use_subcommand" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_use_subcommand" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_use_subcommand" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_use_subcommand" -s j -l jobs -d 'number of jobs to run in parallel' -r -f -complete -c x.py -n "__fish_use_subcommand" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny '',warn '',default ''}" -complete -c x.py -n "__fish_use_subcommand" -l error-format -d 'rustc error format' -r -f -complete -c x.py -n "__fish_use_subcommand" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always '',never '',auto ''}" -complete -c x.py -n "__fish_use_subcommand" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true '',false ''}" -complete -c x.py -n "__fish_use_subcommand" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F -complete -c x.py -n "__fish_use_subcommand" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F -complete -c x.py -n "__fish_use_subcommand" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F -complete -c x.py -n "__fish_use_subcommand" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_use_subcommand" -l set -d 'override options in config.toml' -r -f -complete -c x.py -n "__fish_use_subcommand" -s v -l verbose -d 'use verbose output (-vv for very verbose)' -complete -c x.py -n "__fish_use_subcommand" -s i -l incremental -d 'use incremental compilation' -complete -c x.py -n "__fish_use_subcommand" -l include-default-paths -d 'include default paths in addition to the provided ones' -complete -c x.py -n "__fish_use_subcommand" -l dry-run -d 'dry run; don\'t build anything' -complete -c x.py -n "__fish_use_subcommand" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' -complete -c x.py -n "__fish_use_subcommand" -l json-output -d 'use message-format=json' -complete -c x.py -n "__fish_use_subcommand" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' -complete -c x.py -n "__fish_use_subcommand" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' -complete -c x.py -n "__fish_use_subcommand" -l enable-bolt-settings -d 'Enable BOLT link flags' -complete -c x.py -n "__fish_use_subcommand" -l skip-stage0-validation -d 'Skip stage0 compiler validation' -complete -c x.py -n "__fish_use_subcommand" -s h -l help -d 'Print help (see more with \'--help\')' -complete -c x.py -n "__fish_use_subcommand" -f -a "build" -d 'Compile either the compiler or libraries' -complete -c x.py -n "__fish_use_subcommand" -f -a "check" -d 'Compile either the compiler or libraries, using cargo check' -complete -c x.py -n "__fish_use_subcommand" -f -a "clippy" -d 'Run Clippy (uses rustup/cargo-installed clippy binary)' -complete -c x.py -n "__fish_use_subcommand" -f -a "fix" -d 'Run cargo fix' -complete -c x.py -n "__fish_use_subcommand" -f -a "fmt" -d 'Run rustfmt' -complete -c x.py -n "__fish_use_subcommand" -f -a "doc" -d 'Build documentation' -complete -c x.py -n "__fish_use_subcommand" -f -a "test" -d 'Build and run some test suites' -complete -c x.py -n "__fish_use_subcommand" -f -a "miri" -d 'Build and run some test suites *in Miri*' -complete -c x.py -n "__fish_use_subcommand" -f -a "bench" -d 'Build and run some benchmarks' -complete -c x.py -n "__fish_use_subcommand" -f -a "clean" -d 'Clean out build directories' -complete -c x.py -n "__fish_use_subcommand" -f -a "dist" -d 'Build distribution artifacts' -complete -c x.py -n "__fish_use_subcommand" -f -a "install" -d 'Install distribution artifacts' -complete -c x.py -n "__fish_use_subcommand" -f -a "run" -d 'Run tools contained in this repository' -complete -c x.py -n "__fish_use_subcommand" -f -a "setup" -d 'Set up the environment for development' -complete -c x.py -n "__fish_use_subcommand" -f -a "suggest" -d 'Suggest a subset of tests to run, based on modified files' -complete -c x.py -n "__fish_use_subcommand" -f -a "vendor" -d 'Vendor dependencies' -complete -c x.py -n "__fish_use_subcommand" -f -a "perf" -d 'Perform profiling and benchmarking of the compiler using the `rustc-perf-wrapper` tool' -complete -c x.py -n "__fish_seen_subcommand_from build" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from build" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_seen_subcommand_from build" -l build -d 'build target of the stage0 compiler' -r -f -complete -c x.py -n "__fish_seen_subcommand_from build" -l host -d 'host targets to build' -r -f -complete -c x.py -n "__fish_seen_subcommand_from build" -l target -d 'target targets to build' -r -f -complete -c x.py -n "__fish_seen_subcommand_from build" -l exclude -d 'build paths to exclude' -r -F -complete -c x.py -n "__fish_seen_subcommand_from build" -l skip -d 'build paths to skip' -r -F -complete -c x.py -n "__fish_seen_subcommand_from build" -l rustc-error-format -r -f -complete -c x.py -n "__fish_seen_subcommand_from build" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" -complete -c x.py -n "__fish_seen_subcommand_from build" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from build" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from build" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from build" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_seen_subcommand_from build" -s j -l jobs -d 'number of jobs to run in parallel' -r -f -complete -c x.py -n "__fish_seen_subcommand_from build" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny '',warn '',default ''}" -complete -c x.py -n "__fish_seen_subcommand_from build" -l error-format -d 'rustc error format' -r -f -complete -c x.py -n "__fish_seen_subcommand_from build" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always '',never '',auto ''}" -complete -c x.py -n "__fish_seen_subcommand_from build" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true '',false ''}" -complete -c x.py -n "__fish_seen_subcommand_from build" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from build" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from build" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from build" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_seen_subcommand_from build" -l set -d 'override options in config.toml' -r -f -complete -c x.py -n "__fish_seen_subcommand_from build" -s v -l verbose -d 'use verbose output (-vv for very verbose)' -complete -c x.py -n "__fish_seen_subcommand_from build" -s i -l incremental -d 'use incremental compilation' -complete -c x.py -n "__fish_seen_subcommand_from build" -l include-default-paths -d 'include default paths in addition to the provided ones' -complete -c x.py -n "__fish_seen_subcommand_from build" -l dry-run -d 'dry run; don\'t build anything' -complete -c x.py -n "__fish_seen_subcommand_from build" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' -complete -c x.py -n "__fish_seen_subcommand_from build" -l json-output -d 'use message-format=json' -complete -c x.py -n "__fish_seen_subcommand_from build" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' -complete -c x.py -n "__fish_seen_subcommand_from build" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' -complete -c x.py -n "__fish_seen_subcommand_from build" -l enable-bolt-settings -d 'Enable BOLT link flags' -complete -c x.py -n "__fish_seen_subcommand_from build" -l skip-stage0-validation -d 'Skip stage0 compiler validation' -complete -c x.py -n "__fish_seen_subcommand_from build" -s h -l help -d 'Print help (see more with \'--help\')' -complete -c x.py -n "__fish_seen_subcommand_from check" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from check" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_seen_subcommand_from check" -l build -d 'build target of the stage0 compiler' -r -f -complete -c x.py -n "__fish_seen_subcommand_from check" -l host -d 'host targets to build' -r -f -complete -c x.py -n "__fish_seen_subcommand_from check" -l target -d 'target targets to build' -r -f -complete -c x.py -n "__fish_seen_subcommand_from check" -l exclude -d 'build paths to exclude' -r -F -complete -c x.py -n "__fish_seen_subcommand_from check" -l skip -d 'build paths to skip' -r -F -complete -c x.py -n "__fish_seen_subcommand_from check" -l rustc-error-format -r -f -complete -c x.py -n "__fish_seen_subcommand_from check" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" -complete -c x.py -n "__fish_seen_subcommand_from check" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from check" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from check" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from check" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_seen_subcommand_from check" -s j -l jobs -d 'number of jobs to run in parallel' -r -f -complete -c x.py -n "__fish_seen_subcommand_from check" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny '',warn '',default ''}" -complete -c x.py -n "__fish_seen_subcommand_from check" -l error-format -d 'rustc error format' -r -f -complete -c x.py -n "__fish_seen_subcommand_from check" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always '',never '',auto ''}" -complete -c x.py -n "__fish_seen_subcommand_from check" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true '',false ''}" -complete -c x.py -n "__fish_seen_subcommand_from check" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from check" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from check" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from check" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_seen_subcommand_from check" -l set -d 'override options in config.toml' -r -f -complete -c x.py -n "__fish_seen_subcommand_from check" -l all-targets -d 'Check all targets' -complete -c x.py -n "__fish_seen_subcommand_from check" -s v -l verbose -d 'use verbose output (-vv for very verbose)' -complete -c x.py -n "__fish_seen_subcommand_from check" -s i -l incremental -d 'use incremental compilation' -complete -c x.py -n "__fish_seen_subcommand_from check" -l include-default-paths -d 'include default paths in addition to the provided ones' -complete -c x.py -n "__fish_seen_subcommand_from check" -l dry-run -d 'dry run; don\'t build anything' -complete -c x.py -n "__fish_seen_subcommand_from check" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' -complete -c x.py -n "__fish_seen_subcommand_from check" -l json-output -d 'use message-format=json' -complete -c x.py -n "__fish_seen_subcommand_from check" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' -complete -c x.py -n "__fish_seen_subcommand_from check" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' -complete -c x.py -n "__fish_seen_subcommand_from check" -l enable-bolt-settings -d 'Enable BOLT link flags' -complete -c x.py -n "__fish_seen_subcommand_from check" -l skip-stage0-validation -d 'Skip stage0 compiler validation' -complete -c x.py -n "__fish_seen_subcommand_from check" -s h -l help -d 'Print help (see more with \'--help\')' -complete -c x.py -n "__fish_seen_subcommand_from clippy" -s A -d 'clippy lints to allow' -r -complete -c x.py -n "__fish_seen_subcommand_from clippy" -s D -d 'clippy lints to deny' -r -complete -c x.py -n "__fish_seen_subcommand_from clippy" -s W -d 'clippy lints to warn on' -r -complete -c x.py -n "__fish_seen_subcommand_from clippy" -s F -d 'clippy lints to forbid' -r -complete -c x.py -n "__fish_seen_subcommand_from clippy" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from clippy" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_seen_subcommand_from clippy" -l build -d 'build target of the stage0 compiler' -r -f -complete -c x.py -n "__fish_seen_subcommand_from clippy" -l host -d 'host targets to build' -r -f -complete -c x.py -n "__fish_seen_subcommand_from clippy" -l target -d 'target targets to build' -r -f -complete -c x.py -n "__fish_seen_subcommand_from clippy" -l exclude -d 'build paths to exclude' -r -F -complete -c x.py -n "__fish_seen_subcommand_from clippy" -l skip -d 'build paths to skip' -r -F -complete -c x.py -n "__fish_seen_subcommand_from clippy" -l rustc-error-format -r -f -complete -c x.py -n "__fish_seen_subcommand_from clippy" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" -complete -c x.py -n "__fish_seen_subcommand_from clippy" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from clippy" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from clippy" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from clippy" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_seen_subcommand_from clippy" -s j -l jobs -d 'number of jobs to run in parallel' -r -f -complete -c x.py -n "__fish_seen_subcommand_from clippy" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny '',warn '',default ''}" -complete -c x.py -n "__fish_seen_subcommand_from clippy" -l error-format -d 'rustc error format' -r -f -complete -c x.py -n "__fish_seen_subcommand_from clippy" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always '',never '',auto ''}" -complete -c x.py -n "__fish_seen_subcommand_from clippy" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true '',false ''}" -complete -c x.py -n "__fish_seen_subcommand_from clippy" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from clippy" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from clippy" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from clippy" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_seen_subcommand_from clippy" -l set -d 'override options in config.toml' -r -f -complete -c x.py -n "__fish_seen_subcommand_from clippy" -l fix -complete -c x.py -n "__fish_seen_subcommand_from clippy" -l allow-dirty -complete -c x.py -n "__fish_seen_subcommand_from clippy" -l allow-staged -complete -c x.py -n "__fish_seen_subcommand_from clippy" -s v -l verbose -d 'use verbose output (-vv for very verbose)' -complete -c x.py -n "__fish_seen_subcommand_from clippy" -s i -l incremental -d 'use incremental compilation' -complete -c x.py -n "__fish_seen_subcommand_from clippy" -l include-default-paths -d 'include default paths in addition to the provided ones' -complete -c x.py -n "__fish_seen_subcommand_from clippy" -l dry-run -d 'dry run; don\'t build anything' -complete -c x.py -n "__fish_seen_subcommand_from clippy" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' -complete -c x.py -n "__fish_seen_subcommand_from clippy" -l json-output -d 'use message-format=json' -complete -c x.py -n "__fish_seen_subcommand_from clippy" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' -complete -c x.py -n "__fish_seen_subcommand_from clippy" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' -complete -c x.py -n "__fish_seen_subcommand_from clippy" -l enable-bolt-settings -d 'Enable BOLT link flags' -complete -c x.py -n "__fish_seen_subcommand_from clippy" -l skip-stage0-validation -d 'Skip stage0 compiler validation' -complete -c x.py -n "__fish_seen_subcommand_from clippy" -s h -l help -d 'Print help (see more with \'--help\')' -complete -c x.py -n "__fish_seen_subcommand_from fix" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from fix" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_seen_subcommand_from fix" -l build -d 'build target of the stage0 compiler' -r -f -complete -c x.py -n "__fish_seen_subcommand_from fix" -l host -d 'host targets to build' -r -f -complete -c x.py -n "__fish_seen_subcommand_from fix" -l target -d 'target targets to build' -r -f -complete -c x.py -n "__fish_seen_subcommand_from fix" -l exclude -d 'build paths to exclude' -r -F -complete -c x.py -n "__fish_seen_subcommand_from fix" -l skip -d 'build paths to skip' -r -F -complete -c x.py -n "__fish_seen_subcommand_from fix" -l rustc-error-format -r -f -complete -c x.py -n "__fish_seen_subcommand_from fix" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" -complete -c x.py -n "__fish_seen_subcommand_from fix" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from fix" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from fix" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from fix" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_seen_subcommand_from fix" -s j -l jobs -d 'number of jobs to run in parallel' -r -f -complete -c x.py -n "__fish_seen_subcommand_from fix" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny '',warn '',default ''}" -complete -c x.py -n "__fish_seen_subcommand_from fix" -l error-format -d 'rustc error format' -r -f -complete -c x.py -n "__fish_seen_subcommand_from fix" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always '',never '',auto ''}" -complete -c x.py -n "__fish_seen_subcommand_from fix" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true '',false ''}" -complete -c x.py -n "__fish_seen_subcommand_from fix" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from fix" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from fix" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from fix" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_seen_subcommand_from fix" -l set -d 'override options in config.toml' -r -f -complete -c x.py -n "__fish_seen_subcommand_from fix" -s v -l verbose -d 'use verbose output (-vv for very verbose)' -complete -c x.py -n "__fish_seen_subcommand_from fix" -s i -l incremental -d 'use incremental compilation' -complete -c x.py -n "__fish_seen_subcommand_from fix" -l include-default-paths -d 'include default paths in addition to the provided ones' -complete -c x.py -n "__fish_seen_subcommand_from fix" -l dry-run -d 'dry run; don\'t build anything' -complete -c x.py -n "__fish_seen_subcommand_from fix" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' -complete -c x.py -n "__fish_seen_subcommand_from fix" -l json-output -d 'use message-format=json' -complete -c x.py -n "__fish_seen_subcommand_from fix" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' -complete -c x.py -n "__fish_seen_subcommand_from fix" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' -complete -c x.py -n "__fish_seen_subcommand_from fix" -l enable-bolt-settings -d 'Enable BOLT link flags' -complete -c x.py -n "__fish_seen_subcommand_from fix" -l skip-stage0-validation -d 'Skip stage0 compiler validation' -complete -c x.py -n "__fish_seen_subcommand_from fix" -s h -l help -d 'Print help (see more with \'--help\')' -complete -c x.py -n "__fish_seen_subcommand_from fmt" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from fmt" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_seen_subcommand_from fmt" -l build -d 'build target of the stage0 compiler' -r -f -complete -c x.py -n "__fish_seen_subcommand_from fmt" -l host -d 'host targets to build' -r -f -complete -c x.py -n "__fish_seen_subcommand_from fmt" -l target -d 'target targets to build' -r -f -complete -c x.py -n "__fish_seen_subcommand_from fmt" -l exclude -d 'build paths to exclude' -r -F -complete -c x.py -n "__fish_seen_subcommand_from fmt" -l skip -d 'build paths to skip' -r -F -complete -c x.py -n "__fish_seen_subcommand_from fmt" -l rustc-error-format -r -f -complete -c x.py -n "__fish_seen_subcommand_from fmt" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" -complete -c x.py -n "__fish_seen_subcommand_from fmt" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from fmt" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from fmt" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from fmt" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_seen_subcommand_from fmt" -s j -l jobs -d 'number of jobs to run in parallel' -r -f -complete -c x.py -n "__fish_seen_subcommand_from fmt" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny '',warn '',default ''}" -complete -c x.py -n "__fish_seen_subcommand_from fmt" -l error-format -d 'rustc error format' -r -f -complete -c x.py -n "__fish_seen_subcommand_from fmt" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always '',never '',auto ''}" -complete -c x.py -n "__fish_seen_subcommand_from fmt" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true '',false ''}" -complete -c x.py -n "__fish_seen_subcommand_from fmt" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from fmt" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from fmt" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from fmt" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_seen_subcommand_from fmt" -l set -d 'override options in config.toml' -r -f -complete -c x.py -n "__fish_seen_subcommand_from fmt" -l check -d 'check formatting instead of applying' -complete -c x.py -n "__fish_seen_subcommand_from fmt" -l all -d 'apply to all appropriate files, not just those that have been modified' -complete -c x.py -n "__fish_seen_subcommand_from fmt" -s v -l verbose -d 'use verbose output (-vv for very verbose)' -complete -c x.py -n "__fish_seen_subcommand_from fmt" -s i -l incremental -d 'use incremental compilation' -complete -c x.py -n "__fish_seen_subcommand_from fmt" -l include-default-paths -d 'include default paths in addition to the provided ones' -complete -c x.py -n "__fish_seen_subcommand_from fmt" -l dry-run -d 'dry run; don\'t build anything' -complete -c x.py -n "__fish_seen_subcommand_from fmt" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' -complete -c x.py -n "__fish_seen_subcommand_from fmt" -l json-output -d 'use message-format=json' -complete -c x.py -n "__fish_seen_subcommand_from fmt" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' -complete -c x.py -n "__fish_seen_subcommand_from fmt" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' -complete -c x.py -n "__fish_seen_subcommand_from fmt" -l enable-bolt-settings -d 'Enable BOLT link flags' -complete -c x.py -n "__fish_seen_subcommand_from fmt" -l skip-stage0-validation -d 'Skip stage0 compiler validation' -complete -c x.py -n "__fish_seen_subcommand_from fmt" -s h -l help -d 'Print help (see more with \'--help\')' -complete -c x.py -n "__fish_seen_subcommand_from doc" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from doc" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_seen_subcommand_from doc" -l build -d 'build target of the stage0 compiler' -r -f -complete -c x.py -n "__fish_seen_subcommand_from doc" -l host -d 'host targets to build' -r -f -complete -c x.py -n "__fish_seen_subcommand_from doc" -l target -d 'target targets to build' -r -f -complete -c x.py -n "__fish_seen_subcommand_from doc" -l exclude -d 'build paths to exclude' -r -F -complete -c x.py -n "__fish_seen_subcommand_from doc" -l skip -d 'build paths to skip' -r -F -complete -c x.py -n "__fish_seen_subcommand_from doc" -l rustc-error-format -r -f -complete -c x.py -n "__fish_seen_subcommand_from doc" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" -complete -c x.py -n "__fish_seen_subcommand_from doc" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from doc" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from doc" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from doc" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_seen_subcommand_from doc" -s j -l jobs -d 'number of jobs to run in parallel' -r -f -complete -c x.py -n "__fish_seen_subcommand_from doc" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny '',warn '',default ''}" -complete -c x.py -n "__fish_seen_subcommand_from doc" -l error-format -d 'rustc error format' -r -f -complete -c x.py -n "__fish_seen_subcommand_from doc" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always '',never '',auto ''}" -complete -c x.py -n "__fish_seen_subcommand_from doc" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true '',false ''}" -complete -c x.py -n "__fish_seen_subcommand_from doc" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from doc" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from doc" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from doc" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_seen_subcommand_from doc" -l set -d 'override options in config.toml' -r -f -complete -c x.py -n "__fish_seen_subcommand_from doc" -l open -d 'open the docs in a browser' -complete -c x.py -n "__fish_seen_subcommand_from doc" -l json -d 'render the documentation in JSON format in addition to the usual HTML format' -complete -c x.py -n "__fish_seen_subcommand_from doc" -s v -l verbose -d 'use verbose output (-vv for very verbose)' -complete -c x.py -n "__fish_seen_subcommand_from doc" -s i -l incremental -d 'use incremental compilation' -complete -c x.py -n "__fish_seen_subcommand_from doc" -l include-default-paths -d 'include default paths in addition to the provided ones' -complete -c x.py -n "__fish_seen_subcommand_from doc" -l dry-run -d 'dry run; don\'t build anything' -complete -c x.py -n "__fish_seen_subcommand_from doc" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' -complete -c x.py -n "__fish_seen_subcommand_from doc" -l json-output -d 'use message-format=json' -complete -c x.py -n "__fish_seen_subcommand_from doc" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' -complete -c x.py -n "__fish_seen_subcommand_from doc" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' -complete -c x.py -n "__fish_seen_subcommand_from doc" -l enable-bolt-settings -d 'Enable BOLT link flags' -complete -c x.py -n "__fish_seen_subcommand_from doc" -l skip-stage0-validation -d 'Skip stage0 compiler validation' -complete -c x.py -n "__fish_seen_subcommand_from doc" -s h -l help -d 'Print help (see more with \'--help\')' -complete -c x.py -n "__fish_seen_subcommand_from test" -l test-args -d 'extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)' -r -complete -c x.py -n "__fish_seen_subcommand_from test" -l compiletest-rustc-args -d 'extra options to pass the compiler when running compiletest tests' -r -complete -c x.py -n "__fish_seen_subcommand_from test" -l extra-checks -d 'comma-separated list of other files types to check (accepts py, py:lint, py:fmt, shell)' -r -complete -c x.py -n "__fish_seen_subcommand_from test" -l compare-mode -d 'mode describing what file the actual ui output will be compared to' -r -complete -c x.py -n "__fish_seen_subcommand_from test" -l pass -d 'force {check,build,run}-pass tests to this mode' -r -complete -c x.py -n "__fish_seen_subcommand_from test" -l run -d 'whether to execute run-* tests' -r -complete -c x.py -n "__fish_seen_subcommand_from test" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from test" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_seen_subcommand_from test" -l build -d 'build target of the stage0 compiler' -r -f -complete -c x.py -n "__fish_seen_subcommand_from test" -l host -d 'host targets to build' -r -f -complete -c x.py -n "__fish_seen_subcommand_from test" -l target -d 'target targets to build' -r -f -complete -c x.py -n "__fish_seen_subcommand_from test" -l exclude -d 'build paths to exclude' -r -F -complete -c x.py -n "__fish_seen_subcommand_from test" -l skip -d 'build paths to skip' -r -F -complete -c x.py -n "__fish_seen_subcommand_from test" -l rustc-error-format -r -f -complete -c x.py -n "__fish_seen_subcommand_from test" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" -complete -c x.py -n "__fish_seen_subcommand_from test" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from test" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from test" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from test" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_seen_subcommand_from test" -s j -l jobs -d 'number of jobs to run in parallel' -r -f -complete -c x.py -n "__fish_seen_subcommand_from test" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny '',warn '',default ''}" -complete -c x.py -n "__fish_seen_subcommand_from test" -l error-format -d 'rustc error format' -r -f -complete -c x.py -n "__fish_seen_subcommand_from test" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always '',never '',auto ''}" -complete -c x.py -n "__fish_seen_subcommand_from test" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true '',false ''}" -complete -c x.py -n "__fish_seen_subcommand_from test" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from test" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from test" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from test" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_seen_subcommand_from test" -l set -d 'override options in config.toml' -r -f -complete -c x.py -n "__fish_seen_subcommand_from test" -l no-fail-fast -d 'run all tests regardless of failure' -complete -c x.py -n "__fish_seen_subcommand_from test" -l no-doc -d 'do not run doc tests' -complete -c x.py -n "__fish_seen_subcommand_from test" -l doc -d 'only run doc tests' -complete -c x.py -n "__fish_seen_subcommand_from test" -l bless -d 'whether to automatically update stderr/stdout files' -complete -c x.py -n "__fish_seen_subcommand_from test" -l force-rerun -d 'rerun tests even if the inputs are unchanged' -complete -c x.py -n "__fish_seen_subcommand_from test" -l only-modified -d 'only run tests that result has been changed' -complete -c x.py -n "__fish_seen_subcommand_from test" -l rustfix-coverage -d 'enable this to generate a Rustfix coverage file, which is saved in `//rustfix_missing_coverage.txt`' -complete -c x.py -n "__fish_seen_subcommand_from test" -s v -l verbose -d 'use verbose output (-vv for very verbose)' -complete -c x.py -n "__fish_seen_subcommand_from test" -s i -l incremental -d 'use incremental compilation' -complete -c x.py -n "__fish_seen_subcommand_from test" -l include-default-paths -d 'include default paths in addition to the provided ones' -complete -c x.py -n "__fish_seen_subcommand_from test" -l dry-run -d 'dry run; don\'t build anything' -complete -c x.py -n "__fish_seen_subcommand_from test" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' -complete -c x.py -n "__fish_seen_subcommand_from test" -l json-output -d 'use message-format=json' -complete -c x.py -n "__fish_seen_subcommand_from test" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' -complete -c x.py -n "__fish_seen_subcommand_from test" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' -complete -c x.py -n "__fish_seen_subcommand_from test" -l enable-bolt-settings -d 'Enable BOLT link flags' -complete -c x.py -n "__fish_seen_subcommand_from test" -l skip-stage0-validation -d 'Skip stage0 compiler validation' -complete -c x.py -n "__fish_seen_subcommand_from test" -s h -l help -d 'Print help (see more with \'--help\')' -complete -c x.py -n "__fish_seen_subcommand_from miri" -l test-args -d 'extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)' -r -complete -c x.py -n "__fish_seen_subcommand_from miri" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from miri" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_seen_subcommand_from miri" -l build -d 'build target of the stage0 compiler' -r -f -complete -c x.py -n "__fish_seen_subcommand_from miri" -l host -d 'host targets to build' -r -f -complete -c x.py -n "__fish_seen_subcommand_from miri" -l target -d 'target targets to build' -r -f -complete -c x.py -n "__fish_seen_subcommand_from miri" -l exclude -d 'build paths to exclude' -r -F -complete -c x.py -n "__fish_seen_subcommand_from miri" -l skip -d 'build paths to skip' -r -F -complete -c x.py -n "__fish_seen_subcommand_from miri" -l rustc-error-format -r -f -complete -c x.py -n "__fish_seen_subcommand_from miri" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" -complete -c x.py -n "__fish_seen_subcommand_from miri" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from miri" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from miri" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from miri" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_seen_subcommand_from miri" -s j -l jobs -d 'number of jobs to run in parallel' -r -f -complete -c x.py -n "__fish_seen_subcommand_from miri" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny '',warn '',default ''}" -complete -c x.py -n "__fish_seen_subcommand_from miri" -l error-format -d 'rustc error format' -r -f -complete -c x.py -n "__fish_seen_subcommand_from miri" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always '',never '',auto ''}" -complete -c x.py -n "__fish_seen_subcommand_from miri" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true '',false ''}" -complete -c x.py -n "__fish_seen_subcommand_from miri" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from miri" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from miri" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from miri" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_seen_subcommand_from miri" -l set -d 'override options in config.toml' -r -f -complete -c x.py -n "__fish_seen_subcommand_from miri" -l no-fail-fast -d 'run all tests regardless of failure' -complete -c x.py -n "__fish_seen_subcommand_from miri" -l no-doc -d 'do not run doc tests' -complete -c x.py -n "__fish_seen_subcommand_from miri" -l doc -d 'only run doc tests' -complete -c x.py -n "__fish_seen_subcommand_from miri" -s v -l verbose -d 'use verbose output (-vv for very verbose)' -complete -c x.py -n "__fish_seen_subcommand_from miri" -s i -l incremental -d 'use incremental compilation' -complete -c x.py -n "__fish_seen_subcommand_from miri" -l include-default-paths -d 'include default paths in addition to the provided ones' -complete -c x.py -n "__fish_seen_subcommand_from miri" -l dry-run -d 'dry run; don\'t build anything' -complete -c x.py -n "__fish_seen_subcommand_from miri" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' -complete -c x.py -n "__fish_seen_subcommand_from miri" -l json-output -d 'use message-format=json' -complete -c x.py -n "__fish_seen_subcommand_from miri" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' -complete -c x.py -n "__fish_seen_subcommand_from miri" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' -complete -c x.py -n "__fish_seen_subcommand_from miri" -l enable-bolt-settings -d 'Enable BOLT link flags' -complete -c x.py -n "__fish_seen_subcommand_from miri" -l skip-stage0-validation -d 'Skip stage0 compiler validation' -complete -c x.py -n "__fish_seen_subcommand_from miri" -s h -l help -d 'Print help (see more with \'--help\')' -complete -c x.py -n "__fish_seen_subcommand_from bench" -l test-args -r -complete -c x.py -n "__fish_seen_subcommand_from bench" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from bench" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_seen_subcommand_from bench" -l build -d 'build target of the stage0 compiler' -r -f -complete -c x.py -n "__fish_seen_subcommand_from bench" -l host -d 'host targets to build' -r -f -complete -c x.py -n "__fish_seen_subcommand_from bench" -l target -d 'target targets to build' -r -f -complete -c x.py -n "__fish_seen_subcommand_from bench" -l exclude -d 'build paths to exclude' -r -F -complete -c x.py -n "__fish_seen_subcommand_from bench" -l skip -d 'build paths to skip' -r -F -complete -c x.py -n "__fish_seen_subcommand_from bench" -l rustc-error-format -r -f -complete -c x.py -n "__fish_seen_subcommand_from bench" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" -complete -c x.py -n "__fish_seen_subcommand_from bench" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from bench" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from bench" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from bench" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_seen_subcommand_from bench" -s j -l jobs -d 'number of jobs to run in parallel' -r -f -complete -c x.py -n "__fish_seen_subcommand_from bench" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny '',warn '',default ''}" -complete -c x.py -n "__fish_seen_subcommand_from bench" -l error-format -d 'rustc error format' -r -f -complete -c x.py -n "__fish_seen_subcommand_from bench" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always '',never '',auto ''}" -complete -c x.py -n "__fish_seen_subcommand_from bench" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true '',false ''}" -complete -c x.py -n "__fish_seen_subcommand_from bench" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from bench" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from bench" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from bench" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_seen_subcommand_from bench" -l set -d 'override options in config.toml' -r -f -complete -c x.py -n "__fish_seen_subcommand_from bench" -s v -l verbose -d 'use verbose output (-vv for very verbose)' -complete -c x.py -n "__fish_seen_subcommand_from bench" -s i -l incremental -d 'use incremental compilation' -complete -c x.py -n "__fish_seen_subcommand_from bench" -l include-default-paths -d 'include default paths in addition to the provided ones' -complete -c x.py -n "__fish_seen_subcommand_from bench" -l dry-run -d 'dry run; don\'t build anything' -complete -c x.py -n "__fish_seen_subcommand_from bench" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' -complete -c x.py -n "__fish_seen_subcommand_from bench" -l json-output -d 'use message-format=json' -complete -c x.py -n "__fish_seen_subcommand_from bench" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' -complete -c x.py -n "__fish_seen_subcommand_from bench" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' -complete -c x.py -n "__fish_seen_subcommand_from bench" -l enable-bolt-settings -d 'Enable BOLT link flags' -complete -c x.py -n "__fish_seen_subcommand_from bench" -l skip-stage0-validation -d 'Skip stage0 compiler validation' -complete -c x.py -n "__fish_seen_subcommand_from bench" -s h -l help -d 'Print help (see more with \'--help\')' -complete -c x.py -n "__fish_seen_subcommand_from clean" -l stage -d 'Clean a specific stage without touching other artifacts. By default, every stage is cleaned if this option is not used' -r -complete -c x.py -n "__fish_seen_subcommand_from clean" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from clean" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_seen_subcommand_from clean" -l build -d 'build target of the stage0 compiler' -r -f -complete -c x.py -n "__fish_seen_subcommand_from clean" -l host -d 'host targets to build' -r -f -complete -c x.py -n "__fish_seen_subcommand_from clean" -l target -d 'target targets to build' -r -f -complete -c x.py -n "__fish_seen_subcommand_from clean" -l exclude -d 'build paths to exclude' -r -F -complete -c x.py -n "__fish_seen_subcommand_from clean" -l skip -d 'build paths to skip' -r -F -complete -c x.py -n "__fish_seen_subcommand_from clean" -l rustc-error-format -r -f -complete -c x.py -n "__fish_seen_subcommand_from clean" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" -complete -c x.py -n "__fish_seen_subcommand_from clean" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from clean" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from clean" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_seen_subcommand_from clean" -s j -l jobs -d 'number of jobs to run in parallel' -r -f -complete -c x.py -n "__fish_seen_subcommand_from clean" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny '',warn '',default ''}" -complete -c x.py -n "__fish_seen_subcommand_from clean" -l error-format -d 'rustc error format' -r -f -complete -c x.py -n "__fish_seen_subcommand_from clean" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always '',never '',auto ''}" -complete -c x.py -n "__fish_seen_subcommand_from clean" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true '',false ''}" -complete -c x.py -n "__fish_seen_subcommand_from clean" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from clean" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from clean" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from clean" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_seen_subcommand_from clean" -l set -d 'override options in config.toml' -r -f -complete -c x.py -n "__fish_seen_subcommand_from clean" -l all -d 'Clean the entire build directory (not used by default)' -complete -c x.py -n "__fish_seen_subcommand_from clean" -s v -l verbose -d 'use verbose output (-vv for very verbose)' -complete -c x.py -n "__fish_seen_subcommand_from clean" -s i -l incremental -d 'use incremental compilation' -complete -c x.py -n "__fish_seen_subcommand_from clean" -l include-default-paths -d 'include default paths in addition to the provided ones' -complete -c x.py -n "__fish_seen_subcommand_from clean" -l dry-run -d 'dry run; don\'t build anything' -complete -c x.py -n "__fish_seen_subcommand_from clean" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' -complete -c x.py -n "__fish_seen_subcommand_from clean" -l json-output -d 'use message-format=json' -complete -c x.py -n "__fish_seen_subcommand_from clean" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' -complete -c x.py -n "__fish_seen_subcommand_from clean" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' -complete -c x.py -n "__fish_seen_subcommand_from clean" -l enable-bolt-settings -d 'Enable BOLT link flags' -complete -c x.py -n "__fish_seen_subcommand_from clean" -l skip-stage0-validation -d 'Skip stage0 compiler validation' -complete -c x.py -n "__fish_seen_subcommand_from clean" -s h -l help -d 'Print help (see more with \'--help\')' -complete -c x.py -n "__fish_seen_subcommand_from dist" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from dist" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_seen_subcommand_from dist" -l build -d 'build target of the stage0 compiler' -r -f -complete -c x.py -n "__fish_seen_subcommand_from dist" -l host -d 'host targets to build' -r -f -complete -c x.py -n "__fish_seen_subcommand_from dist" -l target -d 'target targets to build' -r -f -complete -c x.py -n "__fish_seen_subcommand_from dist" -l exclude -d 'build paths to exclude' -r -F -complete -c x.py -n "__fish_seen_subcommand_from dist" -l skip -d 'build paths to skip' -r -F -complete -c x.py -n "__fish_seen_subcommand_from dist" -l rustc-error-format -r -f -complete -c x.py -n "__fish_seen_subcommand_from dist" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" -complete -c x.py -n "__fish_seen_subcommand_from dist" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from dist" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from dist" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from dist" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_seen_subcommand_from dist" -s j -l jobs -d 'number of jobs to run in parallel' -r -f -complete -c x.py -n "__fish_seen_subcommand_from dist" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny '',warn '',default ''}" -complete -c x.py -n "__fish_seen_subcommand_from dist" -l error-format -d 'rustc error format' -r -f -complete -c x.py -n "__fish_seen_subcommand_from dist" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always '',never '',auto ''}" -complete -c x.py -n "__fish_seen_subcommand_from dist" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true '',false ''}" -complete -c x.py -n "__fish_seen_subcommand_from dist" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from dist" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from dist" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from dist" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_seen_subcommand_from dist" -l set -d 'override options in config.toml' -r -f -complete -c x.py -n "__fish_seen_subcommand_from dist" -s v -l verbose -d 'use verbose output (-vv for very verbose)' -complete -c x.py -n "__fish_seen_subcommand_from dist" -s i -l incremental -d 'use incremental compilation' -complete -c x.py -n "__fish_seen_subcommand_from dist" -l include-default-paths -d 'include default paths in addition to the provided ones' -complete -c x.py -n "__fish_seen_subcommand_from dist" -l dry-run -d 'dry run; don\'t build anything' -complete -c x.py -n "__fish_seen_subcommand_from dist" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' -complete -c x.py -n "__fish_seen_subcommand_from dist" -l json-output -d 'use message-format=json' -complete -c x.py -n "__fish_seen_subcommand_from dist" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' -complete -c x.py -n "__fish_seen_subcommand_from dist" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' -complete -c x.py -n "__fish_seen_subcommand_from dist" -l enable-bolt-settings -d 'Enable BOLT link flags' -complete -c x.py -n "__fish_seen_subcommand_from dist" -l skip-stage0-validation -d 'Skip stage0 compiler validation' -complete -c x.py -n "__fish_seen_subcommand_from dist" -s h -l help -d 'Print help (see more with \'--help\')' -complete -c x.py -n "__fish_seen_subcommand_from install" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from install" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_seen_subcommand_from install" -l build -d 'build target of the stage0 compiler' -r -f -complete -c x.py -n "__fish_seen_subcommand_from install" -l host -d 'host targets to build' -r -f -complete -c x.py -n "__fish_seen_subcommand_from install" -l target -d 'target targets to build' -r -f -complete -c x.py -n "__fish_seen_subcommand_from install" -l exclude -d 'build paths to exclude' -r -F -complete -c x.py -n "__fish_seen_subcommand_from install" -l skip -d 'build paths to skip' -r -F -complete -c x.py -n "__fish_seen_subcommand_from install" -l rustc-error-format -r -f -complete -c x.py -n "__fish_seen_subcommand_from install" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" -complete -c x.py -n "__fish_seen_subcommand_from install" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from install" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from install" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from install" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_seen_subcommand_from install" -s j -l jobs -d 'number of jobs to run in parallel' -r -f -complete -c x.py -n "__fish_seen_subcommand_from install" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny '',warn '',default ''}" -complete -c x.py -n "__fish_seen_subcommand_from install" -l error-format -d 'rustc error format' -r -f -complete -c x.py -n "__fish_seen_subcommand_from install" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always '',never '',auto ''}" -complete -c x.py -n "__fish_seen_subcommand_from install" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true '',false ''}" -complete -c x.py -n "__fish_seen_subcommand_from install" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from install" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from install" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from install" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_seen_subcommand_from install" -l set -d 'override options in config.toml' -r -f -complete -c x.py -n "__fish_seen_subcommand_from install" -s v -l verbose -d 'use verbose output (-vv for very verbose)' -complete -c x.py -n "__fish_seen_subcommand_from install" -s i -l incremental -d 'use incremental compilation' -complete -c x.py -n "__fish_seen_subcommand_from install" -l include-default-paths -d 'include default paths in addition to the provided ones' -complete -c x.py -n "__fish_seen_subcommand_from install" -l dry-run -d 'dry run; don\'t build anything' -complete -c x.py -n "__fish_seen_subcommand_from install" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' -complete -c x.py -n "__fish_seen_subcommand_from install" -l json-output -d 'use message-format=json' -complete -c x.py -n "__fish_seen_subcommand_from install" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' -complete -c x.py -n "__fish_seen_subcommand_from install" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' -complete -c x.py -n "__fish_seen_subcommand_from install" -l enable-bolt-settings -d 'Enable BOLT link flags' -complete -c x.py -n "__fish_seen_subcommand_from install" -l skip-stage0-validation -d 'Skip stage0 compiler validation' -complete -c x.py -n "__fish_seen_subcommand_from install" -s h -l help -d 'Print help (see more with \'--help\')' -complete -c x.py -n "__fish_seen_subcommand_from run" -l args -d 'arguments for the tool' -r -complete -c x.py -n "__fish_seen_subcommand_from run" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from run" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_seen_subcommand_from run" -l build -d 'build target of the stage0 compiler' -r -f -complete -c x.py -n "__fish_seen_subcommand_from run" -l host -d 'host targets to build' -r -f -complete -c x.py -n "__fish_seen_subcommand_from run" -l target -d 'target targets to build' -r -f -complete -c x.py -n "__fish_seen_subcommand_from run" -l exclude -d 'build paths to exclude' -r -F -complete -c x.py -n "__fish_seen_subcommand_from run" -l skip -d 'build paths to skip' -r -F -complete -c x.py -n "__fish_seen_subcommand_from run" -l rustc-error-format -r -f -complete -c x.py -n "__fish_seen_subcommand_from run" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" -complete -c x.py -n "__fish_seen_subcommand_from run" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from run" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from run" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from run" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_seen_subcommand_from run" -s j -l jobs -d 'number of jobs to run in parallel' -r -f -complete -c x.py -n "__fish_seen_subcommand_from run" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny '',warn '',default ''}" -complete -c x.py -n "__fish_seen_subcommand_from run" -l error-format -d 'rustc error format' -r -f -complete -c x.py -n "__fish_seen_subcommand_from run" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always '',never '',auto ''}" -complete -c x.py -n "__fish_seen_subcommand_from run" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true '',false ''}" -complete -c x.py -n "__fish_seen_subcommand_from run" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from run" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from run" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from run" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_seen_subcommand_from run" -l set -d 'override options in config.toml' -r -f -complete -c x.py -n "__fish_seen_subcommand_from run" -s v -l verbose -d 'use verbose output (-vv for very verbose)' -complete -c x.py -n "__fish_seen_subcommand_from run" -s i -l incremental -d 'use incremental compilation' -complete -c x.py -n "__fish_seen_subcommand_from run" -l include-default-paths -d 'include default paths in addition to the provided ones' -complete -c x.py -n "__fish_seen_subcommand_from run" -l dry-run -d 'dry run; don\'t build anything' -complete -c x.py -n "__fish_seen_subcommand_from run" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' -complete -c x.py -n "__fish_seen_subcommand_from run" -l json-output -d 'use message-format=json' -complete -c x.py -n "__fish_seen_subcommand_from run" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' -complete -c x.py -n "__fish_seen_subcommand_from run" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' -complete -c x.py -n "__fish_seen_subcommand_from run" -l enable-bolt-settings -d 'Enable BOLT link flags' -complete -c x.py -n "__fish_seen_subcommand_from run" -l skip-stage0-validation -d 'Skip stage0 compiler validation' -complete -c x.py -n "__fish_seen_subcommand_from run" -s h -l help -d 'Print help (see more with \'--help\')' -complete -c x.py -n "__fish_seen_subcommand_from setup" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from setup" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_seen_subcommand_from setup" -l build -d 'build target of the stage0 compiler' -r -f -complete -c x.py -n "__fish_seen_subcommand_from setup" -l host -d 'host targets to build' -r -f -complete -c x.py -n "__fish_seen_subcommand_from setup" -l target -d 'target targets to build' -r -f -complete -c x.py -n "__fish_seen_subcommand_from setup" -l exclude -d 'build paths to exclude' -r -F -complete -c x.py -n "__fish_seen_subcommand_from setup" -l skip -d 'build paths to skip' -r -F -complete -c x.py -n "__fish_seen_subcommand_from setup" -l rustc-error-format -r -f -complete -c x.py -n "__fish_seen_subcommand_from setup" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" -complete -c x.py -n "__fish_seen_subcommand_from setup" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from setup" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from setup" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from setup" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_seen_subcommand_from setup" -s j -l jobs -d 'number of jobs to run in parallel' -r -f -complete -c x.py -n "__fish_seen_subcommand_from setup" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny '',warn '',default ''}" -complete -c x.py -n "__fish_seen_subcommand_from setup" -l error-format -d 'rustc error format' -r -f -complete -c x.py -n "__fish_seen_subcommand_from setup" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always '',never '',auto ''}" -complete -c x.py -n "__fish_seen_subcommand_from setup" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true '',false ''}" -complete -c x.py -n "__fish_seen_subcommand_from setup" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from setup" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from setup" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from setup" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_seen_subcommand_from setup" -l set -d 'override options in config.toml' -r -f -complete -c x.py -n "__fish_seen_subcommand_from setup" -s v -l verbose -d 'use verbose output (-vv for very verbose)' -complete -c x.py -n "__fish_seen_subcommand_from setup" -s i -l incremental -d 'use incremental compilation' -complete -c x.py -n "__fish_seen_subcommand_from setup" -l include-default-paths -d 'include default paths in addition to the provided ones' -complete -c x.py -n "__fish_seen_subcommand_from setup" -l dry-run -d 'dry run; don\'t build anything' -complete -c x.py -n "__fish_seen_subcommand_from setup" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' -complete -c x.py -n "__fish_seen_subcommand_from setup" -l json-output -d 'use message-format=json' -complete -c x.py -n "__fish_seen_subcommand_from setup" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' -complete -c x.py -n "__fish_seen_subcommand_from setup" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' -complete -c x.py -n "__fish_seen_subcommand_from setup" -l enable-bolt-settings -d 'Enable BOLT link flags' -complete -c x.py -n "__fish_seen_subcommand_from setup" -l skip-stage0-validation -d 'Skip stage0 compiler validation' -complete -c x.py -n "__fish_seen_subcommand_from setup" -s h -l help -d 'Print help (see more with \'--help\')' -complete -c x.py -n "__fish_seen_subcommand_from suggest" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from suggest" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_seen_subcommand_from suggest" -l build -d 'build target of the stage0 compiler' -r -f -complete -c x.py -n "__fish_seen_subcommand_from suggest" -l host -d 'host targets to build' -r -f -complete -c x.py -n "__fish_seen_subcommand_from suggest" -l target -d 'target targets to build' -r -f -complete -c x.py -n "__fish_seen_subcommand_from suggest" -l exclude -d 'build paths to exclude' -r -F -complete -c x.py -n "__fish_seen_subcommand_from suggest" -l skip -d 'build paths to skip' -r -F -complete -c x.py -n "__fish_seen_subcommand_from suggest" -l rustc-error-format -r -f -complete -c x.py -n "__fish_seen_subcommand_from suggest" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" -complete -c x.py -n "__fish_seen_subcommand_from suggest" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from suggest" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from suggest" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from suggest" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_seen_subcommand_from suggest" -s j -l jobs -d 'number of jobs to run in parallel' -r -f -complete -c x.py -n "__fish_seen_subcommand_from suggest" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny '',warn '',default ''}" -complete -c x.py -n "__fish_seen_subcommand_from suggest" -l error-format -d 'rustc error format' -r -f -complete -c x.py -n "__fish_seen_subcommand_from suggest" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always '',never '',auto ''}" -complete -c x.py -n "__fish_seen_subcommand_from suggest" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true '',false ''}" -complete -c x.py -n "__fish_seen_subcommand_from suggest" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from suggest" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from suggest" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from suggest" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_seen_subcommand_from suggest" -l set -d 'override options in config.toml' -r -f -complete -c x.py -n "__fish_seen_subcommand_from suggest" -l run -d 'run suggested tests' -complete -c x.py -n "__fish_seen_subcommand_from suggest" -s v -l verbose -d 'use verbose output (-vv for very verbose)' -complete -c x.py -n "__fish_seen_subcommand_from suggest" -s i -l incremental -d 'use incremental compilation' -complete -c x.py -n "__fish_seen_subcommand_from suggest" -l include-default-paths -d 'include default paths in addition to the provided ones' -complete -c x.py -n "__fish_seen_subcommand_from suggest" -l dry-run -d 'dry run; don\'t build anything' -complete -c x.py -n "__fish_seen_subcommand_from suggest" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' -complete -c x.py -n "__fish_seen_subcommand_from suggest" -l json-output -d 'use message-format=json' -complete -c x.py -n "__fish_seen_subcommand_from suggest" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' -complete -c x.py -n "__fish_seen_subcommand_from suggest" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' -complete -c x.py -n "__fish_seen_subcommand_from suggest" -l enable-bolt-settings -d 'Enable BOLT link flags' -complete -c x.py -n "__fish_seen_subcommand_from suggest" -l skip-stage0-validation -d 'Skip stage0 compiler validation' -complete -c x.py -n "__fish_seen_subcommand_from suggest" -s h -l help -d 'Print help (see more with \'--help\')' -complete -c x.py -n "__fish_seen_subcommand_from vendor" -l sync -d 'Additional `Cargo.toml` to sync and vendor' -r -F -complete -c x.py -n "__fish_seen_subcommand_from vendor" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from vendor" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_seen_subcommand_from vendor" -l build -d 'build target of the stage0 compiler' -r -f -complete -c x.py -n "__fish_seen_subcommand_from vendor" -l host -d 'host targets to build' -r -f -complete -c x.py -n "__fish_seen_subcommand_from vendor" -l target -d 'target targets to build' -r -f -complete -c x.py -n "__fish_seen_subcommand_from vendor" -l exclude -d 'build paths to exclude' -r -F -complete -c x.py -n "__fish_seen_subcommand_from vendor" -l skip -d 'build paths to skip' -r -F -complete -c x.py -n "__fish_seen_subcommand_from vendor" -l rustc-error-format -r -f -complete -c x.py -n "__fish_seen_subcommand_from vendor" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" -complete -c x.py -n "__fish_seen_subcommand_from vendor" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from vendor" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from vendor" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from vendor" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_seen_subcommand_from vendor" -s j -l jobs -d 'number of jobs to run in parallel' -r -f -complete -c x.py -n "__fish_seen_subcommand_from vendor" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny '',warn '',default ''}" -complete -c x.py -n "__fish_seen_subcommand_from vendor" -l error-format -d 'rustc error format' -r -f -complete -c x.py -n "__fish_seen_subcommand_from vendor" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always '',never '',auto ''}" -complete -c x.py -n "__fish_seen_subcommand_from vendor" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true '',false ''}" -complete -c x.py -n "__fish_seen_subcommand_from vendor" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from vendor" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from vendor" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from vendor" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_seen_subcommand_from vendor" -l set -d 'override options in config.toml' -r -f -complete -c x.py -n "__fish_seen_subcommand_from vendor" -l versioned-dirs -d 'Always include version in subdir name' -complete -c x.py -n "__fish_seen_subcommand_from vendor" -s v -l verbose -d 'use verbose output (-vv for very verbose)' -complete -c x.py -n "__fish_seen_subcommand_from vendor" -s i -l incremental -d 'use incremental compilation' -complete -c x.py -n "__fish_seen_subcommand_from vendor" -l include-default-paths -d 'include default paths in addition to the provided ones' -complete -c x.py -n "__fish_seen_subcommand_from vendor" -l dry-run -d 'dry run; don\'t build anything' -complete -c x.py -n "__fish_seen_subcommand_from vendor" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' -complete -c x.py -n "__fish_seen_subcommand_from vendor" -l json-output -d 'use message-format=json' -complete -c x.py -n "__fish_seen_subcommand_from vendor" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' -complete -c x.py -n "__fish_seen_subcommand_from vendor" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' -complete -c x.py -n "__fish_seen_subcommand_from vendor" -l enable-bolt-settings -d 'Enable BOLT link flags' -complete -c x.py -n "__fish_seen_subcommand_from vendor" -l skip-stage0-validation -d 'Skip stage0 compiler validation' -complete -c x.py -n "__fish_seen_subcommand_from vendor" -s h -l help -d 'Print help (see more with \'--help\')' -complete -c x.py -n "__fish_seen_subcommand_from perf" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from perf" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_seen_subcommand_from perf" -l build -d 'build target of the stage0 compiler' -r -f -complete -c x.py -n "__fish_seen_subcommand_from perf" -l host -d 'host targets to build' -r -f -complete -c x.py -n "__fish_seen_subcommand_from perf" -l target -d 'target targets to build' -r -f -complete -c x.py -n "__fish_seen_subcommand_from perf" -l exclude -d 'build paths to exclude' -r -F -complete -c x.py -n "__fish_seen_subcommand_from perf" -l skip -d 'build paths to skip' -r -F -complete -c x.py -n "__fish_seen_subcommand_from perf" -l rustc-error-format -r -f -complete -c x.py -n "__fish_seen_subcommand_from perf" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" -complete -c x.py -n "__fish_seen_subcommand_from perf" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from perf" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from perf" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f -complete -c x.py -n "__fish_seen_subcommand_from perf" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" -complete -c x.py -n "__fish_seen_subcommand_from perf" -s j -l jobs -d 'number of jobs to run in parallel' -r -f -complete -c x.py -n "__fish_seen_subcommand_from perf" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny '',warn '',default ''}" -complete -c x.py -n "__fish_seen_subcommand_from perf" -l error-format -d 'rustc error format' -r -f -complete -c x.py -n "__fish_seen_subcommand_from perf" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always '',never '',auto ''}" -complete -c x.py -n "__fish_seen_subcommand_from perf" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true '',false ''}" -complete -c x.py -n "__fish_seen_subcommand_from perf" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from perf" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from perf" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F -complete -c x.py -n "__fish_seen_subcommand_from perf" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_seen_subcommand_from perf" -l set -d 'override options in config.toml' -r -f -complete -c x.py -n "__fish_seen_subcommand_from perf" -s v -l verbose -d 'use verbose output (-vv for very verbose)' -complete -c x.py -n "__fish_seen_subcommand_from perf" -s i -l incremental -d 'use incremental compilation' -complete -c x.py -n "__fish_seen_subcommand_from perf" -l include-default-paths -d 'include default paths in addition to the provided ones' -complete -c x.py -n "__fish_seen_subcommand_from perf" -l dry-run -d 'dry run; don\'t build anything' -complete -c x.py -n "__fish_seen_subcommand_from perf" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' -complete -c x.py -n "__fish_seen_subcommand_from perf" -l json-output -d 'use message-format=json' -complete -c x.py -n "__fish_seen_subcommand_from perf" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' -complete -c x.py -n "__fish_seen_subcommand_from perf" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' -complete -c x.py -n "__fish_seen_subcommand_from perf" -l enable-bolt-settings -d 'Enable BOLT link flags' -complete -c x.py -n "__fish_seen_subcommand_from perf" -l skip-stage0-validation -d 'Skip stage0 compiler validation' -complete -c x.py -n "__fish_seen_subcommand_from perf" -s h -l help -d 'Print help (see more with \'--help\')' +# Print an optspec for argparse to handle cmd's options that are independent of any subcommand. +function __fish_x.py_global_optspecs + string join \n v/verbose i/incremental config= build-dir= build= host= target= exclude= skip= include-default-paths rustc-error-format= on-fail= dry-run dump-bootstrap-shims stage= keep-stage= keep-stage-std= src= j/jobs= warnings= error-format= json-output color= bypass-bootstrap-lock llvm-skip-rebuild= rust-profile-generate= rust-profile-use= llvm-profile-use= llvm-profile-generate enable-bolt-settings skip-stage0-validation reproducible-artifact= set= h/help +end + +function __fish_x.py_needs_command + # Figure out if the current invocation already has a command. + set -l cmd (commandline -opc) + set -e cmd[1] + argparse -s (__fish_x.py_global_optspecs) -- $cmd 2>/dev/null + or return + if set -q argv[1] + # Also print the command, so this can be used to figure out what it is. + echo $argv[1] + return 1 + end + return 0 +end + +function __fish_x.py_using_subcommand + set -l cmd (__fish_x.py_needs_command) + test -z "$cmd" + and return 1 + contains -- $cmd[1] $argv +end + +complete -c x.py -n "__fish_x.py_needs_command" -l config -d 'TOML configuration file for build' -r -F +complete -c x.py -n "__fish_x.py_needs_command" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_needs_command" -l build -d 'build target of the stage0 compiler' -r -f +complete -c x.py -n "__fish_x.py_needs_command" -l host -d 'host targets to build' -r -f +complete -c x.py -n "__fish_x.py_needs_command" -l target -d 'target targets to build' -r -f +complete -c x.py -n "__fish_x.py_needs_command" -l exclude -d 'build paths to exclude' -r -F +complete -c x.py -n "__fish_x.py_needs_command" -l skip -d 'build paths to skip' -r -F +complete -c x.py -n "__fish_x.py_needs_command" -l rustc-error-format -r -f +complete -c x.py -n "__fish_x.py_needs_command" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" +complete -c x.py -n "__fish_x.py_needs_command" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f +complete -c x.py -n "__fish_x.py_needs_command" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_needs_command" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_needs_command" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_needs_command" -s j -l jobs -d 'number of jobs to run in parallel' -r -f +complete -c x.py -n "__fish_x.py_needs_command" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}" +complete -c x.py -n "__fish_x.py_needs_command" -l error-format -d 'rustc error format' -r -f +complete -c x.py -n "__fish_x.py_needs_command" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}" +complete -c x.py -n "__fish_x.py_needs_command" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}" +complete -c x.py -n "__fish_x.py_needs_command" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F +complete -c x.py -n "__fish_x.py_needs_command" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F +complete -c x.py -n "__fish_x.py_needs_command" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F +complete -c x.py -n "__fish_x.py_needs_command" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r +complete -c x.py -n "__fish_x.py_needs_command" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_needs_command" -s v -l verbose -d 'use verbose output (-vv for very verbose)' +complete -c x.py -n "__fish_x.py_needs_command" -s i -l incremental -d 'use incremental compilation' +complete -c x.py -n "__fish_x.py_needs_command" -l include-default-paths -d 'include default paths in addition to the provided ones' +complete -c x.py -n "__fish_x.py_needs_command" -l dry-run -d 'dry run; don\'t build anything' +complete -c x.py -n "__fish_x.py_needs_command" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' +complete -c x.py -n "__fish_x.py_needs_command" -l json-output -d 'use message-format=json' +complete -c x.py -n "__fish_x.py_needs_command" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' +complete -c x.py -n "__fish_x.py_needs_command" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' +complete -c x.py -n "__fish_x.py_needs_command" -l enable-bolt-settings -d 'Enable BOLT link flags' +complete -c x.py -n "__fish_x.py_needs_command" -l skip-stage0-validation -d 'Skip stage0 compiler validation' +complete -c x.py -n "__fish_x.py_needs_command" -s h -l help -d 'Print help (see more with \'--help\')' +complete -c x.py -n "__fish_x.py_needs_command" -a "build" -d 'Compile either the compiler or libraries' +complete -c x.py -n "__fish_x.py_needs_command" -a "check" -d 'Compile either the compiler or libraries, using cargo check' +complete -c x.py -n "__fish_x.py_needs_command" -a "clippy" -d 'Run Clippy (uses rustup/cargo-installed clippy binary)' +complete -c x.py -n "__fish_x.py_needs_command" -a "fix" -d 'Run cargo fix' +complete -c x.py -n "__fish_x.py_needs_command" -a "fmt" -d 'Run rustfmt' +complete -c x.py -n "__fish_x.py_needs_command" -a "doc" -d 'Build documentation' +complete -c x.py -n "__fish_x.py_needs_command" -a "test" -d 'Build and run some test suites' +complete -c x.py -n "__fish_x.py_needs_command" -a "miri" -d 'Build and run some test suites *in Miri*' +complete -c x.py -n "__fish_x.py_needs_command" -a "bench" -d 'Build and run some benchmarks' +complete -c x.py -n "__fish_x.py_needs_command" -a "clean" -d 'Clean out build directories' +complete -c x.py -n "__fish_x.py_needs_command" -a "dist" -d 'Build distribution artifacts' +complete -c x.py -n "__fish_x.py_needs_command" -a "install" -d 'Install distribution artifacts' +complete -c x.py -n "__fish_x.py_needs_command" -a "run" -d 'Run tools contained in this repository' +complete -c x.py -n "__fish_x.py_needs_command" -a "setup" -d 'Set up the environment for development' +complete -c x.py -n "__fish_x.py_needs_command" -a "suggest" -d 'Suggest a subset of tests to run, based on modified files' +complete -c x.py -n "__fish_x.py_needs_command" -a "vendor" -d 'Vendor dependencies' +complete -c x.py -n "__fish_x.py_needs_command" -a "perf" -d 'Perform profiling and benchmarking of the compiler using the `rustc-perf-wrapper` tool' +complete -c x.py -n "__fish_x.py_using_subcommand build" -l config -d 'TOML configuration file for build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand build" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand build" -l build -d 'build target of the stage0 compiler' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand build" -l host -d 'host targets to build' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand build" -l target -d 'target targets to build' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand build" -l exclude -d 'build paths to exclude' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand build" -l skip -d 'build paths to skip' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand build" -l rustc-error-format -r -f +complete -c x.py -n "__fish_x.py_using_subcommand build" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" +complete -c x.py -n "__fish_x.py_using_subcommand build" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand build" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand build" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand build" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand build" -s j -l jobs -d 'number of jobs to run in parallel' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand build" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand build" -l error-format -d 'rustc error format' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand build" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand build" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand build" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand build" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand build" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand build" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r +complete -c x.py -n "__fish_x.py_using_subcommand build" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand build" -s v -l verbose -d 'use verbose output (-vv for very verbose)' +complete -c x.py -n "__fish_x.py_using_subcommand build" -s i -l incremental -d 'use incremental compilation' +complete -c x.py -n "__fish_x.py_using_subcommand build" -l include-default-paths -d 'include default paths in addition to the provided ones' +complete -c x.py -n "__fish_x.py_using_subcommand build" -l dry-run -d 'dry run; don\'t build anything' +complete -c x.py -n "__fish_x.py_using_subcommand build" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' +complete -c x.py -n "__fish_x.py_using_subcommand build" -l json-output -d 'use message-format=json' +complete -c x.py -n "__fish_x.py_using_subcommand build" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' +complete -c x.py -n "__fish_x.py_using_subcommand build" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' +complete -c x.py -n "__fish_x.py_using_subcommand build" -l enable-bolt-settings -d 'Enable BOLT link flags' +complete -c x.py -n "__fish_x.py_using_subcommand build" -l skip-stage0-validation -d 'Skip stage0 compiler validation' +complete -c x.py -n "__fish_x.py_using_subcommand build" -s h -l help -d 'Print help (see more with \'--help\')' +complete -c x.py -n "__fish_x.py_using_subcommand check" -l config -d 'TOML configuration file for build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand check" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand check" -l build -d 'build target of the stage0 compiler' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand check" -l host -d 'host targets to build' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand check" -l target -d 'target targets to build' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand check" -l exclude -d 'build paths to exclude' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand check" -l skip -d 'build paths to skip' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand check" -l rustc-error-format -r -f +complete -c x.py -n "__fish_x.py_using_subcommand check" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" +complete -c x.py -n "__fish_x.py_using_subcommand check" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand check" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand check" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand check" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand check" -s j -l jobs -d 'number of jobs to run in parallel' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand check" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand check" -l error-format -d 'rustc error format' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand check" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand check" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand check" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand check" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand check" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand check" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r +complete -c x.py -n "__fish_x.py_using_subcommand check" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand check" -l all-targets -d 'Check all targets' +complete -c x.py -n "__fish_x.py_using_subcommand check" -s v -l verbose -d 'use verbose output (-vv for very verbose)' +complete -c x.py -n "__fish_x.py_using_subcommand check" -s i -l incremental -d 'use incremental compilation' +complete -c x.py -n "__fish_x.py_using_subcommand check" -l include-default-paths -d 'include default paths in addition to the provided ones' +complete -c x.py -n "__fish_x.py_using_subcommand check" -l dry-run -d 'dry run; don\'t build anything' +complete -c x.py -n "__fish_x.py_using_subcommand check" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' +complete -c x.py -n "__fish_x.py_using_subcommand check" -l json-output -d 'use message-format=json' +complete -c x.py -n "__fish_x.py_using_subcommand check" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' +complete -c x.py -n "__fish_x.py_using_subcommand check" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' +complete -c x.py -n "__fish_x.py_using_subcommand check" -l enable-bolt-settings -d 'Enable BOLT link flags' +complete -c x.py -n "__fish_x.py_using_subcommand check" -l skip-stage0-validation -d 'Skip stage0 compiler validation' +complete -c x.py -n "__fish_x.py_using_subcommand check" -s h -l help -d 'Print help (see more with \'--help\')' +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -s A -d 'clippy lints to allow' -r +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -s D -d 'clippy lints to deny' -r +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -s W -d 'clippy lints to warn on' -r +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -s F -d 'clippy lints to forbid' -r +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l config -d 'TOML configuration file for build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l build -d 'build target of the stage0 compiler' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l host -d 'host targets to build' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l target -d 'target targets to build' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l exclude -d 'build paths to exclude' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l skip -d 'build paths to skip' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l rustc-error-format -r -f +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -s j -l jobs -d 'number of jobs to run in parallel' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l error-format -d 'rustc error format' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l fix +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l allow-dirty +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l allow-staged +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -s v -l verbose -d 'use verbose output (-vv for very verbose)' +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -s i -l incremental -d 'use incremental compilation' +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l include-default-paths -d 'include default paths in addition to the provided ones' +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l dry-run -d 'dry run; don\'t build anything' +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l json-output -d 'use message-format=json' +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l enable-bolt-settings -d 'Enable BOLT link flags' +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l skip-stage0-validation -d 'Skip stage0 compiler validation' +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -s h -l help -d 'Print help (see more with \'--help\')' +complete -c x.py -n "__fish_x.py_using_subcommand fix" -l config -d 'TOML configuration file for build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand fix" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand fix" -l build -d 'build target of the stage0 compiler' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand fix" -l host -d 'host targets to build' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand fix" -l target -d 'target targets to build' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand fix" -l exclude -d 'build paths to exclude' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand fix" -l skip -d 'build paths to skip' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand fix" -l rustc-error-format -r -f +complete -c x.py -n "__fish_x.py_using_subcommand fix" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" +complete -c x.py -n "__fish_x.py_using_subcommand fix" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand fix" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand fix" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand fix" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand fix" -s j -l jobs -d 'number of jobs to run in parallel' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand fix" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand fix" -l error-format -d 'rustc error format' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand fix" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand fix" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand fix" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand fix" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand fix" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand fix" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r +complete -c x.py -n "__fish_x.py_using_subcommand fix" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand fix" -s v -l verbose -d 'use verbose output (-vv for very verbose)' +complete -c x.py -n "__fish_x.py_using_subcommand fix" -s i -l incremental -d 'use incremental compilation' +complete -c x.py -n "__fish_x.py_using_subcommand fix" -l include-default-paths -d 'include default paths in addition to the provided ones' +complete -c x.py -n "__fish_x.py_using_subcommand fix" -l dry-run -d 'dry run; don\'t build anything' +complete -c x.py -n "__fish_x.py_using_subcommand fix" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' +complete -c x.py -n "__fish_x.py_using_subcommand fix" -l json-output -d 'use message-format=json' +complete -c x.py -n "__fish_x.py_using_subcommand fix" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' +complete -c x.py -n "__fish_x.py_using_subcommand fix" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' +complete -c x.py -n "__fish_x.py_using_subcommand fix" -l enable-bolt-settings -d 'Enable BOLT link flags' +complete -c x.py -n "__fish_x.py_using_subcommand fix" -l skip-stage0-validation -d 'Skip stage0 compiler validation' +complete -c x.py -n "__fish_x.py_using_subcommand fix" -s h -l help -d 'Print help (see more with \'--help\')' +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l config -d 'TOML configuration file for build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l build -d 'build target of the stage0 compiler' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l host -d 'host targets to build' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l target -d 'target targets to build' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l exclude -d 'build paths to exclude' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l skip -d 'build paths to skip' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l rustc-error-format -r -f +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -s j -l jobs -d 'number of jobs to run in parallel' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l error-format -d 'rustc error format' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l check -d 'check formatting instead of applying' +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l all -d 'apply to all appropriate files, not just those that have been modified' +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -s v -l verbose -d 'use verbose output (-vv for very verbose)' +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -s i -l incremental -d 'use incremental compilation' +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l include-default-paths -d 'include default paths in addition to the provided ones' +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l dry-run -d 'dry run; don\'t build anything' +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l json-output -d 'use message-format=json' +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l enable-bolt-settings -d 'Enable BOLT link flags' +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l skip-stage0-validation -d 'Skip stage0 compiler validation' +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -s h -l help -d 'Print help (see more with \'--help\')' +complete -c x.py -n "__fish_x.py_using_subcommand doc" -l config -d 'TOML configuration file for build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand doc" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand doc" -l build -d 'build target of the stage0 compiler' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand doc" -l host -d 'host targets to build' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand doc" -l target -d 'target targets to build' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand doc" -l exclude -d 'build paths to exclude' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand doc" -l skip -d 'build paths to skip' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand doc" -l rustc-error-format -r -f +complete -c x.py -n "__fish_x.py_using_subcommand doc" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" +complete -c x.py -n "__fish_x.py_using_subcommand doc" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand doc" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand doc" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand doc" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand doc" -s j -l jobs -d 'number of jobs to run in parallel' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand doc" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand doc" -l error-format -d 'rustc error format' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand doc" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand doc" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand doc" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand doc" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand doc" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand doc" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r +complete -c x.py -n "__fish_x.py_using_subcommand doc" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand doc" -l open -d 'open the docs in a browser' +complete -c x.py -n "__fish_x.py_using_subcommand doc" -l json -d 'render the documentation in JSON format in addition to the usual HTML format' +complete -c x.py -n "__fish_x.py_using_subcommand doc" -s v -l verbose -d 'use verbose output (-vv for very verbose)' +complete -c x.py -n "__fish_x.py_using_subcommand doc" -s i -l incremental -d 'use incremental compilation' +complete -c x.py -n "__fish_x.py_using_subcommand doc" -l include-default-paths -d 'include default paths in addition to the provided ones' +complete -c x.py -n "__fish_x.py_using_subcommand doc" -l dry-run -d 'dry run; don\'t build anything' +complete -c x.py -n "__fish_x.py_using_subcommand doc" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' +complete -c x.py -n "__fish_x.py_using_subcommand doc" -l json-output -d 'use message-format=json' +complete -c x.py -n "__fish_x.py_using_subcommand doc" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' +complete -c x.py -n "__fish_x.py_using_subcommand doc" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' +complete -c x.py -n "__fish_x.py_using_subcommand doc" -l enable-bolt-settings -d 'Enable BOLT link flags' +complete -c x.py -n "__fish_x.py_using_subcommand doc" -l skip-stage0-validation -d 'Skip stage0 compiler validation' +complete -c x.py -n "__fish_x.py_using_subcommand doc" -s h -l help -d 'Print help (see more with \'--help\')' +complete -c x.py -n "__fish_x.py_using_subcommand test" -l test-args -d 'extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)' -r +complete -c x.py -n "__fish_x.py_using_subcommand test" -l compiletest-rustc-args -d 'extra options to pass the compiler when running compiletest tests' -r +complete -c x.py -n "__fish_x.py_using_subcommand test" -l extra-checks -d 'comma-separated list of other files types to check (accepts py, py:lint, py:fmt, shell)' -r +complete -c x.py -n "__fish_x.py_using_subcommand test" -l compare-mode -d 'mode describing what file the actual ui output will be compared to' -r +complete -c x.py -n "__fish_x.py_using_subcommand test" -l pass -d 'force {check,build,run}-pass tests to this mode' -r +complete -c x.py -n "__fish_x.py_using_subcommand test" -l run -d 'whether to execute run-* tests' -r +complete -c x.py -n "__fish_x.py_using_subcommand test" -l config -d 'TOML configuration file for build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand test" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand test" -l build -d 'build target of the stage0 compiler' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand test" -l host -d 'host targets to build' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand test" -l target -d 'target targets to build' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand test" -l exclude -d 'build paths to exclude' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand test" -l skip -d 'build paths to skip' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand test" -l rustc-error-format -r -f +complete -c x.py -n "__fish_x.py_using_subcommand test" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" +complete -c x.py -n "__fish_x.py_using_subcommand test" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand test" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand test" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand test" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand test" -s j -l jobs -d 'number of jobs to run in parallel' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand test" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand test" -l error-format -d 'rustc error format' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand test" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand test" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand test" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand test" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand test" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand test" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r +complete -c x.py -n "__fish_x.py_using_subcommand test" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand test" -l no-fail-fast -d 'run all tests regardless of failure' +complete -c x.py -n "__fish_x.py_using_subcommand test" -l no-doc -d 'do not run doc tests' +complete -c x.py -n "__fish_x.py_using_subcommand test" -l doc -d 'only run doc tests' +complete -c x.py -n "__fish_x.py_using_subcommand test" -l bless -d 'whether to automatically update stderr/stdout files' +complete -c x.py -n "__fish_x.py_using_subcommand test" -l force-rerun -d 'rerun tests even if the inputs are unchanged' +complete -c x.py -n "__fish_x.py_using_subcommand test" -l only-modified -d 'only run tests that result has been changed' +complete -c x.py -n "__fish_x.py_using_subcommand test" -l rustfix-coverage -d 'enable this to generate a Rustfix coverage file, which is saved in `//rustfix_missing_coverage.txt`' +complete -c x.py -n "__fish_x.py_using_subcommand test" -s v -l verbose -d 'use verbose output (-vv for very verbose)' +complete -c x.py -n "__fish_x.py_using_subcommand test" -s i -l incremental -d 'use incremental compilation' +complete -c x.py -n "__fish_x.py_using_subcommand test" -l include-default-paths -d 'include default paths in addition to the provided ones' +complete -c x.py -n "__fish_x.py_using_subcommand test" -l dry-run -d 'dry run; don\'t build anything' +complete -c x.py -n "__fish_x.py_using_subcommand test" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' +complete -c x.py -n "__fish_x.py_using_subcommand test" -l json-output -d 'use message-format=json' +complete -c x.py -n "__fish_x.py_using_subcommand test" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' +complete -c x.py -n "__fish_x.py_using_subcommand test" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' +complete -c x.py -n "__fish_x.py_using_subcommand test" -l enable-bolt-settings -d 'Enable BOLT link flags' +complete -c x.py -n "__fish_x.py_using_subcommand test" -l skip-stage0-validation -d 'Skip stage0 compiler validation' +complete -c x.py -n "__fish_x.py_using_subcommand test" -s h -l help -d 'Print help (see more with \'--help\')' +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l test-args -d 'extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)' -r +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l config -d 'TOML configuration file for build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l build -d 'build target of the stage0 compiler' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l host -d 'host targets to build' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l target -d 'target targets to build' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l exclude -d 'build paths to exclude' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l skip -d 'build paths to skip' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l rustc-error-format -r -f +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand miri" -s j -l jobs -d 'number of jobs to run in parallel' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l error-format -d 'rustc error format' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l no-fail-fast -d 'run all tests regardless of failure' +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l no-doc -d 'do not run doc tests' +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l doc -d 'only run doc tests' +complete -c x.py -n "__fish_x.py_using_subcommand miri" -s v -l verbose -d 'use verbose output (-vv for very verbose)' +complete -c x.py -n "__fish_x.py_using_subcommand miri" -s i -l incremental -d 'use incremental compilation' +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l include-default-paths -d 'include default paths in addition to the provided ones' +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l dry-run -d 'dry run; don\'t build anything' +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l json-output -d 'use message-format=json' +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l enable-bolt-settings -d 'Enable BOLT link flags' +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l skip-stage0-validation -d 'Skip stage0 compiler validation' +complete -c x.py -n "__fish_x.py_using_subcommand miri" -s h -l help -d 'Print help (see more with \'--help\')' +complete -c x.py -n "__fish_x.py_using_subcommand bench" -l test-args -r +complete -c x.py -n "__fish_x.py_using_subcommand bench" -l config -d 'TOML configuration file for build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand bench" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand bench" -l build -d 'build target of the stage0 compiler' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand bench" -l host -d 'host targets to build' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand bench" -l target -d 'target targets to build' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand bench" -l exclude -d 'build paths to exclude' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand bench" -l skip -d 'build paths to skip' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand bench" -l rustc-error-format -r -f +complete -c x.py -n "__fish_x.py_using_subcommand bench" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" +complete -c x.py -n "__fish_x.py_using_subcommand bench" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand bench" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand bench" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand bench" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand bench" -s j -l jobs -d 'number of jobs to run in parallel' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand bench" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand bench" -l error-format -d 'rustc error format' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand bench" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand bench" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand bench" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand bench" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand bench" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand bench" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r +complete -c x.py -n "__fish_x.py_using_subcommand bench" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand bench" -s v -l verbose -d 'use verbose output (-vv for very verbose)' +complete -c x.py -n "__fish_x.py_using_subcommand bench" -s i -l incremental -d 'use incremental compilation' +complete -c x.py -n "__fish_x.py_using_subcommand bench" -l include-default-paths -d 'include default paths in addition to the provided ones' +complete -c x.py -n "__fish_x.py_using_subcommand bench" -l dry-run -d 'dry run; don\'t build anything' +complete -c x.py -n "__fish_x.py_using_subcommand bench" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' +complete -c x.py -n "__fish_x.py_using_subcommand bench" -l json-output -d 'use message-format=json' +complete -c x.py -n "__fish_x.py_using_subcommand bench" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' +complete -c x.py -n "__fish_x.py_using_subcommand bench" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' +complete -c x.py -n "__fish_x.py_using_subcommand bench" -l enable-bolt-settings -d 'Enable BOLT link flags' +complete -c x.py -n "__fish_x.py_using_subcommand bench" -l skip-stage0-validation -d 'Skip stage0 compiler validation' +complete -c x.py -n "__fish_x.py_using_subcommand bench" -s h -l help -d 'Print help (see more with \'--help\')' +complete -c x.py -n "__fish_x.py_using_subcommand clean" -l stage -d 'Clean a specific stage without touching other artifacts. By default, every stage is cleaned if this option is not used' -r +complete -c x.py -n "__fish_x.py_using_subcommand clean" -l config -d 'TOML configuration file for build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand clean" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand clean" -l build -d 'build target of the stage0 compiler' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand clean" -l host -d 'host targets to build' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand clean" -l target -d 'target targets to build' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand clean" -l exclude -d 'build paths to exclude' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand clean" -l skip -d 'build paths to skip' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand clean" -l rustc-error-format -r -f +complete -c x.py -n "__fish_x.py_using_subcommand clean" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" +complete -c x.py -n "__fish_x.py_using_subcommand clean" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand clean" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand clean" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand clean" -s j -l jobs -d 'number of jobs to run in parallel' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand clean" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand clean" -l error-format -d 'rustc error format' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand clean" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand clean" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand clean" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand clean" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand clean" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand clean" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r +complete -c x.py -n "__fish_x.py_using_subcommand clean" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand clean" -l all -d 'Clean the entire build directory (not used by default)' +complete -c x.py -n "__fish_x.py_using_subcommand clean" -s v -l verbose -d 'use verbose output (-vv for very verbose)' +complete -c x.py -n "__fish_x.py_using_subcommand clean" -s i -l incremental -d 'use incremental compilation' +complete -c x.py -n "__fish_x.py_using_subcommand clean" -l include-default-paths -d 'include default paths in addition to the provided ones' +complete -c x.py -n "__fish_x.py_using_subcommand clean" -l dry-run -d 'dry run; don\'t build anything' +complete -c x.py -n "__fish_x.py_using_subcommand clean" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' +complete -c x.py -n "__fish_x.py_using_subcommand clean" -l json-output -d 'use message-format=json' +complete -c x.py -n "__fish_x.py_using_subcommand clean" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' +complete -c x.py -n "__fish_x.py_using_subcommand clean" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' +complete -c x.py -n "__fish_x.py_using_subcommand clean" -l enable-bolt-settings -d 'Enable BOLT link flags' +complete -c x.py -n "__fish_x.py_using_subcommand clean" -l skip-stage0-validation -d 'Skip stage0 compiler validation' +complete -c x.py -n "__fish_x.py_using_subcommand clean" -s h -l help -d 'Print help (see more with \'--help\')' +complete -c x.py -n "__fish_x.py_using_subcommand dist" -l config -d 'TOML configuration file for build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand dist" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand dist" -l build -d 'build target of the stage0 compiler' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand dist" -l host -d 'host targets to build' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand dist" -l target -d 'target targets to build' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand dist" -l exclude -d 'build paths to exclude' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand dist" -l skip -d 'build paths to skip' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand dist" -l rustc-error-format -r -f +complete -c x.py -n "__fish_x.py_using_subcommand dist" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" +complete -c x.py -n "__fish_x.py_using_subcommand dist" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand dist" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand dist" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand dist" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand dist" -s j -l jobs -d 'number of jobs to run in parallel' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand dist" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand dist" -l error-format -d 'rustc error format' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand dist" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand dist" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand dist" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand dist" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand dist" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand dist" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r +complete -c x.py -n "__fish_x.py_using_subcommand dist" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand dist" -s v -l verbose -d 'use verbose output (-vv for very verbose)' +complete -c x.py -n "__fish_x.py_using_subcommand dist" -s i -l incremental -d 'use incremental compilation' +complete -c x.py -n "__fish_x.py_using_subcommand dist" -l include-default-paths -d 'include default paths in addition to the provided ones' +complete -c x.py -n "__fish_x.py_using_subcommand dist" -l dry-run -d 'dry run; don\'t build anything' +complete -c x.py -n "__fish_x.py_using_subcommand dist" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' +complete -c x.py -n "__fish_x.py_using_subcommand dist" -l json-output -d 'use message-format=json' +complete -c x.py -n "__fish_x.py_using_subcommand dist" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' +complete -c x.py -n "__fish_x.py_using_subcommand dist" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' +complete -c x.py -n "__fish_x.py_using_subcommand dist" -l enable-bolt-settings -d 'Enable BOLT link flags' +complete -c x.py -n "__fish_x.py_using_subcommand dist" -l skip-stage0-validation -d 'Skip stage0 compiler validation' +complete -c x.py -n "__fish_x.py_using_subcommand dist" -s h -l help -d 'Print help (see more with \'--help\')' +complete -c x.py -n "__fish_x.py_using_subcommand install" -l config -d 'TOML configuration file for build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand install" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand install" -l build -d 'build target of the stage0 compiler' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand install" -l host -d 'host targets to build' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand install" -l target -d 'target targets to build' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand install" -l exclude -d 'build paths to exclude' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand install" -l skip -d 'build paths to skip' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand install" -l rustc-error-format -r -f +complete -c x.py -n "__fish_x.py_using_subcommand install" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" +complete -c x.py -n "__fish_x.py_using_subcommand install" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand install" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand install" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand install" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand install" -s j -l jobs -d 'number of jobs to run in parallel' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand install" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand install" -l error-format -d 'rustc error format' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand install" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand install" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand install" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand install" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand install" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand install" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r +complete -c x.py -n "__fish_x.py_using_subcommand install" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand install" -s v -l verbose -d 'use verbose output (-vv for very verbose)' +complete -c x.py -n "__fish_x.py_using_subcommand install" -s i -l incremental -d 'use incremental compilation' +complete -c x.py -n "__fish_x.py_using_subcommand install" -l include-default-paths -d 'include default paths in addition to the provided ones' +complete -c x.py -n "__fish_x.py_using_subcommand install" -l dry-run -d 'dry run; don\'t build anything' +complete -c x.py -n "__fish_x.py_using_subcommand install" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' +complete -c x.py -n "__fish_x.py_using_subcommand install" -l json-output -d 'use message-format=json' +complete -c x.py -n "__fish_x.py_using_subcommand install" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' +complete -c x.py -n "__fish_x.py_using_subcommand install" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' +complete -c x.py -n "__fish_x.py_using_subcommand install" -l enable-bolt-settings -d 'Enable BOLT link flags' +complete -c x.py -n "__fish_x.py_using_subcommand install" -l skip-stage0-validation -d 'Skip stage0 compiler validation' +complete -c x.py -n "__fish_x.py_using_subcommand install" -s h -l help -d 'Print help (see more with \'--help\')' +complete -c x.py -n "__fish_x.py_using_subcommand run" -l args -d 'arguments for the tool' -r +complete -c x.py -n "__fish_x.py_using_subcommand run" -l config -d 'TOML configuration file for build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand run" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand run" -l build -d 'build target of the stage0 compiler' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand run" -l host -d 'host targets to build' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand run" -l target -d 'target targets to build' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand run" -l exclude -d 'build paths to exclude' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand run" -l skip -d 'build paths to skip' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand run" -l rustc-error-format -r -f +complete -c x.py -n "__fish_x.py_using_subcommand run" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" +complete -c x.py -n "__fish_x.py_using_subcommand run" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand run" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand run" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand run" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand run" -s j -l jobs -d 'number of jobs to run in parallel' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand run" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand run" -l error-format -d 'rustc error format' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand run" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand run" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand run" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand run" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand run" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand run" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r +complete -c x.py -n "__fish_x.py_using_subcommand run" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand run" -s v -l verbose -d 'use verbose output (-vv for very verbose)' +complete -c x.py -n "__fish_x.py_using_subcommand run" -s i -l incremental -d 'use incremental compilation' +complete -c x.py -n "__fish_x.py_using_subcommand run" -l include-default-paths -d 'include default paths in addition to the provided ones' +complete -c x.py -n "__fish_x.py_using_subcommand run" -l dry-run -d 'dry run; don\'t build anything' +complete -c x.py -n "__fish_x.py_using_subcommand run" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' +complete -c x.py -n "__fish_x.py_using_subcommand run" -l json-output -d 'use message-format=json' +complete -c x.py -n "__fish_x.py_using_subcommand run" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' +complete -c x.py -n "__fish_x.py_using_subcommand run" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' +complete -c x.py -n "__fish_x.py_using_subcommand run" -l enable-bolt-settings -d 'Enable BOLT link flags' +complete -c x.py -n "__fish_x.py_using_subcommand run" -l skip-stage0-validation -d 'Skip stage0 compiler validation' +complete -c x.py -n "__fish_x.py_using_subcommand run" -s h -l help -d 'Print help (see more with \'--help\')' +complete -c x.py -n "__fish_x.py_using_subcommand setup" -l config -d 'TOML configuration file for build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand setup" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand setup" -l build -d 'build target of the stage0 compiler' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand setup" -l host -d 'host targets to build' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand setup" -l target -d 'target targets to build' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand setup" -l exclude -d 'build paths to exclude' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand setup" -l skip -d 'build paths to skip' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand setup" -l rustc-error-format -r -f +complete -c x.py -n "__fish_x.py_using_subcommand setup" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" +complete -c x.py -n "__fish_x.py_using_subcommand setup" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand setup" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand setup" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand setup" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand setup" -s j -l jobs -d 'number of jobs to run in parallel' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand setup" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand setup" -l error-format -d 'rustc error format' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand setup" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand setup" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand setup" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand setup" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand setup" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand setup" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r +complete -c x.py -n "__fish_x.py_using_subcommand setup" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand setup" -s v -l verbose -d 'use verbose output (-vv for very verbose)' +complete -c x.py -n "__fish_x.py_using_subcommand setup" -s i -l incremental -d 'use incremental compilation' +complete -c x.py -n "__fish_x.py_using_subcommand setup" -l include-default-paths -d 'include default paths in addition to the provided ones' +complete -c x.py -n "__fish_x.py_using_subcommand setup" -l dry-run -d 'dry run; don\'t build anything' +complete -c x.py -n "__fish_x.py_using_subcommand setup" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' +complete -c x.py -n "__fish_x.py_using_subcommand setup" -l json-output -d 'use message-format=json' +complete -c x.py -n "__fish_x.py_using_subcommand setup" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' +complete -c x.py -n "__fish_x.py_using_subcommand setup" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' +complete -c x.py -n "__fish_x.py_using_subcommand setup" -l enable-bolt-settings -d 'Enable BOLT link flags' +complete -c x.py -n "__fish_x.py_using_subcommand setup" -l skip-stage0-validation -d 'Skip stage0 compiler validation' +complete -c x.py -n "__fish_x.py_using_subcommand setup" -s h -l help -d 'Print help (see more with \'--help\')' +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l config -d 'TOML configuration file for build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l build -d 'build target of the stage0 compiler' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l host -d 'host targets to build' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l target -d 'target targets to build' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l exclude -d 'build paths to exclude' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l skip -d 'build paths to skip' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l rustc-error-format -r -f +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -s j -l jobs -d 'number of jobs to run in parallel' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l error-format -d 'rustc error format' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l run -d 'run suggested tests' +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -s v -l verbose -d 'use verbose output (-vv for very verbose)' +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -s i -l incremental -d 'use incremental compilation' +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l include-default-paths -d 'include default paths in addition to the provided ones' +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l dry-run -d 'dry run; don\'t build anything' +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l json-output -d 'use message-format=json' +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l enable-bolt-settings -d 'Enable BOLT link flags' +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l skip-stage0-validation -d 'Skip stage0 compiler validation' +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -s h -l help -d 'Print help (see more with \'--help\')' +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l sync -d 'Additional `Cargo.toml` to sync and vendor' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l config -d 'TOML configuration file for build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l build -d 'build target of the stage0 compiler' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l host -d 'host targets to build' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l target -d 'target targets to build' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l exclude -d 'build paths to exclude' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l skip -d 'build paths to skip' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l rustc-error-format -r -f +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -s j -l jobs -d 'number of jobs to run in parallel' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l error-format -d 'rustc error format' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l versioned-dirs -d 'Always include version in subdir name' +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -s v -l verbose -d 'use verbose output (-vv for very verbose)' +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -s i -l incremental -d 'use incremental compilation' +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l include-default-paths -d 'include default paths in addition to the provided ones' +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l dry-run -d 'dry run; don\'t build anything' +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l json-output -d 'use message-format=json' +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l enable-bolt-settings -d 'Enable BOLT link flags' +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l skip-stage0-validation -d 'Skip stage0 compiler validation' +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -s h -l help -d 'Print help (see more with \'--help\')' +complete -c x.py -n "__fish_x.py_using_subcommand perf" -l config -d 'TOML configuration file for build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand perf" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand perf" -l build -d 'build target of the stage0 compiler' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand perf" -l host -d 'host targets to build' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand perf" -l target -d 'target targets to build' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand perf" -l exclude -d 'build paths to exclude' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand perf" -l skip -d 'build paths to skip' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand perf" -l rustc-error-format -r -f +complete -c x.py -n "__fish_x.py_using_subcommand perf" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" +complete -c x.py -n "__fish_x.py_using_subcommand perf" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand perf" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand perf" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand perf" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand perf" -s j -l jobs -d 'number of jobs to run in parallel' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand perf" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand perf" -l error-format -d 'rustc error format' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand perf" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand perf" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand perf" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand perf" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand perf" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F +complete -c x.py -n "__fish_x.py_using_subcommand perf" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r +complete -c x.py -n "__fish_x.py_using_subcommand perf" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand perf" -s v -l verbose -d 'use verbose output (-vv for very verbose)' +complete -c x.py -n "__fish_x.py_using_subcommand perf" -s i -l incremental -d 'use incremental compilation' +complete -c x.py -n "__fish_x.py_using_subcommand perf" -l include-default-paths -d 'include default paths in addition to the provided ones' +complete -c x.py -n "__fish_x.py_using_subcommand perf" -l dry-run -d 'dry run; don\'t build anything' +complete -c x.py -n "__fish_x.py_using_subcommand perf" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' +complete -c x.py -n "__fish_x.py_using_subcommand perf" -l json-output -d 'use message-format=json' +complete -c x.py -n "__fish_x.py_using_subcommand perf" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' +complete -c x.py -n "__fish_x.py_using_subcommand perf" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' +complete -c x.py -n "__fish_x.py_using_subcommand perf" -l enable-bolt-settings -d 'Enable BOLT link flags' +complete -c x.py -n "__fish_x.py_using_subcommand perf" -l skip-stage0-validation -d 'Skip stage0 compiler validation' +complete -c x.py -n "__fish_x.py_using_subcommand perf" -s h -l help -d 'Print help (see more with \'--help\')' diff --git a/src/etc/completions/x.py.ps1 b/src/etc/completions/x.py.ps1 index 4b424471a26..240de32451d 100644 --- a/src/etc/completions/x.py.ps1 +++ b/src/etc/completions/x.py.ps1 @@ -21,44 +21,44 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { $completions = @(switch ($command) { 'x.py' { - [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') - [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') - [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build') - [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build') - [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') - [CompletionResult]::new('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip') - [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') - [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') - [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') - [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') - [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') - [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format') - [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') - [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') - [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') - [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') - [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') - [CompletionResult]::new('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') - [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') - [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') - [CompletionResult]::new('--dump-bootstrap-shims', 'dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') - [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json') - [CompletionResult]::new('--bypass-bootstrap-lock', 'bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') - [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') - [CompletionResult]::new('--enable-bolt-settings', 'enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') - [CompletionResult]::new('--skip-stage0-validation', 'skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') - [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') - [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') + [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') + [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') + [CompletionResult]::new('--exclude', '--exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') + [CompletionResult]::new('--skip', '--skip', [CompletionResultType]::ParameterName, 'build paths to skip') + [CompletionResult]::new('--rustc-error-format', '--rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') + [CompletionResult]::new('--on-fail', '--on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') + [CompletionResult]::new('--stage', '--stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') + [CompletionResult]::new('--keep-stage', '--keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--keep-stage-std', '--keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--src', '--src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') + [CompletionResult]::new('-j', '-j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--jobs', '--jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') + [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format') + [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') + [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') + [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') + [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') + [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') + [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--incremental', '--incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--include-default-paths', '--include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') + [CompletionResult]::new('--dry-run', '--dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') + [CompletionResult]::new('--dump-bootstrap-shims', '--dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') + [CompletionResult]::new('--json-output', '--json-output', [CompletionResultType]::ParameterName, 'use message-format=json') + [CompletionResult]::new('--bypass-bootstrap-lock', '--bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') + [CompletionResult]::new('--llvm-profile-generate', '--llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') + [CompletionResult]::new('--enable-bolt-settings', '--enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') + [CompletionResult]::new('--skip-stage0-validation', '--skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') + [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') [CompletionResult]::new('build', 'build', [CompletionResultType]::ParameterValue, 'Compile either the compiler or libraries') [CompletionResult]::new('check', 'check', [CompletionResultType]::ParameterValue, 'Compile either the compiler or libraries, using cargo check') [CompletionResult]::new('clippy', 'clippy', [CompletionResultType]::ParameterValue, 'Run Clippy (uses rustup/cargo-installed clippy binary)') @@ -79,735 +79,735 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { break } 'x.py;build' { - [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') - [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') - [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build') - [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build') - [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') - [CompletionResult]::new('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip') - [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') - [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') - [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') - [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') - [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') - [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format') - [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') - [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') - [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') - [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') - [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') - [CompletionResult]::new('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') - [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') - [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') - [CompletionResult]::new('--dump-bootstrap-shims', 'dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') - [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json') - [CompletionResult]::new('--bypass-bootstrap-lock', 'bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') - [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') - [CompletionResult]::new('--enable-bolt-settings', 'enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') - [CompletionResult]::new('--skip-stage0-validation', 'skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') - [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') - [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') + [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') + [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') + [CompletionResult]::new('--exclude', '--exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') + [CompletionResult]::new('--skip', '--skip', [CompletionResultType]::ParameterName, 'build paths to skip') + [CompletionResult]::new('--rustc-error-format', '--rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') + [CompletionResult]::new('--on-fail', '--on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') + [CompletionResult]::new('--stage', '--stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') + [CompletionResult]::new('--keep-stage', '--keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--keep-stage-std', '--keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--src', '--src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') + [CompletionResult]::new('-j', '-j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--jobs', '--jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') + [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format') + [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') + [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') + [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') + [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') + [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') + [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--incremental', '--incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--include-default-paths', '--include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') + [CompletionResult]::new('--dry-run', '--dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') + [CompletionResult]::new('--dump-bootstrap-shims', '--dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') + [CompletionResult]::new('--json-output', '--json-output', [CompletionResultType]::ParameterName, 'use message-format=json') + [CompletionResult]::new('--bypass-bootstrap-lock', '--bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') + [CompletionResult]::new('--llvm-profile-generate', '--llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') + [CompletionResult]::new('--enable-bolt-settings', '--enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') + [CompletionResult]::new('--skip-stage0-validation', '--skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') + [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') break } 'x.py;check' { - [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') - [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') - [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build') - [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build') - [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') - [CompletionResult]::new('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip') - [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') - [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') - [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') - [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') - [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') - [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format') - [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') - [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') - [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') - [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') - [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') - [CompletionResult]::new('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') - [CompletionResult]::new('--all-targets', 'all-targets', [CompletionResultType]::ParameterName, 'Check all targets') - [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') - [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') - [CompletionResult]::new('--dump-bootstrap-shims', 'dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') - [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json') - [CompletionResult]::new('--bypass-bootstrap-lock', 'bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') - [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') - [CompletionResult]::new('--enable-bolt-settings', 'enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') - [CompletionResult]::new('--skip-stage0-validation', 'skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') - [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') - [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') + [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') + [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') + [CompletionResult]::new('--exclude', '--exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') + [CompletionResult]::new('--skip', '--skip', [CompletionResultType]::ParameterName, 'build paths to skip') + [CompletionResult]::new('--rustc-error-format', '--rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') + [CompletionResult]::new('--on-fail', '--on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') + [CompletionResult]::new('--stage', '--stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') + [CompletionResult]::new('--keep-stage', '--keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--keep-stage-std', '--keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--src', '--src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') + [CompletionResult]::new('-j', '-j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--jobs', '--jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') + [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format') + [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') + [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') + [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') + [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') + [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') + [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--all-targets', '--all-targets', [CompletionResultType]::ParameterName, 'Check all targets') + [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--incremental', '--incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--include-default-paths', '--include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') + [CompletionResult]::new('--dry-run', '--dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') + [CompletionResult]::new('--dump-bootstrap-shims', '--dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') + [CompletionResult]::new('--json-output', '--json-output', [CompletionResultType]::ParameterName, 'use message-format=json') + [CompletionResult]::new('--bypass-bootstrap-lock', '--bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') + [CompletionResult]::new('--llvm-profile-generate', '--llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') + [CompletionResult]::new('--enable-bolt-settings', '--enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') + [CompletionResult]::new('--skip-stage0-validation', '--skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') + [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') break } 'x.py;clippy' { - [CompletionResult]::new('-A', 'A ', [CompletionResultType]::ParameterName, 'clippy lints to allow') - [CompletionResult]::new('-D', 'D ', [CompletionResultType]::ParameterName, 'clippy lints to deny') - [CompletionResult]::new('-W', 'W ', [CompletionResultType]::ParameterName, 'clippy lints to warn on') - [CompletionResult]::new('-F', 'F ', [CompletionResultType]::ParameterName, 'clippy lints to forbid') - [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') - [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') - [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build') - [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build') - [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') - [CompletionResult]::new('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip') - [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') - [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') - [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') - [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') - [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') - [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format') - [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') - [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') - [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') - [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') - [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') - [CompletionResult]::new('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') - [CompletionResult]::new('--fix', 'fix', [CompletionResultType]::ParameterName, 'fix') - [CompletionResult]::new('--allow-dirty', 'allow-dirty', [CompletionResultType]::ParameterName, 'allow-dirty') - [CompletionResult]::new('--allow-staged', 'allow-staged', [CompletionResultType]::ParameterName, 'allow-staged') - [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') - [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') - [CompletionResult]::new('--dump-bootstrap-shims', 'dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') - [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json') - [CompletionResult]::new('--bypass-bootstrap-lock', 'bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') - [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') - [CompletionResult]::new('--enable-bolt-settings', 'enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') - [CompletionResult]::new('--skip-stage0-validation', 'skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') - [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') - [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('-A', '-A ', [CompletionResultType]::ParameterName, 'clippy lints to allow') + [CompletionResult]::new('-D', '-D ', [CompletionResultType]::ParameterName, 'clippy lints to deny') + [CompletionResult]::new('-W', '-W ', [CompletionResultType]::ParameterName, 'clippy lints to warn on') + [CompletionResult]::new('-F', '-F ', [CompletionResultType]::ParameterName, 'clippy lints to forbid') + [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') + [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') + [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') + [CompletionResult]::new('--exclude', '--exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') + [CompletionResult]::new('--skip', '--skip', [CompletionResultType]::ParameterName, 'build paths to skip') + [CompletionResult]::new('--rustc-error-format', '--rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') + [CompletionResult]::new('--on-fail', '--on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') + [CompletionResult]::new('--stage', '--stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') + [CompletionResult]::new('--keep-stage', '--keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--keep-stage-std', '--keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--src', '--src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') + [CompletionResult]::new('-j', '-j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--jobs', '--jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') + [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format') + [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') + [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') + [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') + [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') + [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') + [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--fix', '--fix', [CompletionResultType]::ParameterName, 'fix') + [CompletionResult]::new('--allow-dirty', '--allow-dirty', [CompletionResultType]::ParameterName, 'allow-dirty') + [CompletionResult]::new('--allow-staged', '--allow-staged', [CompletionResultType]::ParameterName, 'allow-staged') + [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--incremental', '--incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--include-default-paths', '--include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') + [CompletionResult]::new('--dry-run', '--dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') + [CompletionResult]::new('--dump-bootstrap-shims', '--dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') + [CompletionResult]::new('--json-output', '--json-output', [CompletionResultType]::ParameterName, 'use message-format=json') + [CompletionResult]::new('--bypass-bootstrap-lock', '--bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') + [CompletionResult]::new('--llvm-profile-generate', '--llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') + [CompletionResult]::new('--enable-bolt-settings', '--enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') + [CompletionResult]::new('--skip-stage0-validation', '--skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') + [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') break } 'x.py;fix' { - [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') - [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') - [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build') - [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build') - [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') - [CompletionResult]::new('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip') - [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') - [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') - [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') - [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') - [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') - [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format') - [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') - [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') - [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') - [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') - [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') - [CompletionResult]::new('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') - [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') - [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') - [CompletionResult]::new('--dump-bootstrap-shims', 'dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') - [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json') - [CompletionResult]::new('--bypass-bootstrap-lock', 'bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') - [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') - [CompletionResult]::new('--enable-bolt-settings', 'enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') - [CompletionResult]::new('--skip-stage0-validation', 'skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') - [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') - [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') + [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') + [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') + [CompletionResult]::new('--exclude', '--exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') + [CompletionResult]::new('--skip', '--skip', [CompletionResultType]::ParameterName, 'build paths to skip') + [CompletionResult]::new('--rustc-error-format', '--rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') + [CompletionResult]::new('--on-fail', '--on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') + [CompletionResult]::new('--stage', '--stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') + [CompletionResult]::new('--keep-stage', '--keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--keep-stage-std', '--keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--src', '--src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') + [CompletionResult]::new('-j', '-j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--jobs', '--jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') + [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format') + [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') + [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') + [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') + [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') + [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') + [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--incremental', '--incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--include-default-paths', '--include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') + [CompletionResult]::new('--dry-run', '--dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') + [CompletionResult]::new('--dump-bootstrap-shims', '--dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') + [CompletionResult]::new('--json-output', '--json-output', [CompletionResultType]::ParameterName, 'use message-format=json') + [CompletionResult]::new('--bypass-bootstrap-lock', '--bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') + [CompletionResult]::new('--llvm-profile-generate', '--llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') + [CompletionResult]::new('--enable-bolt-settings', '--enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') + [CompletionResult]::new('--skip-stage0-validation', '--skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') + [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') break } 'x.py;fmt' { - [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') - [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') - [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build') - [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build') - [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') - [CompletionResult]::new('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip') - [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') - [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') - [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') - [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') - [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') - [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format') - [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') - [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') - [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') - [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') - [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') - [CompletionResult]::new('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') - [CompletionResult]::new('--check', 'check', [CompletionResultType]::ParameterName, 'check formatting instead of applying') - [CompletionResult]::new('--all', 'all', [CompletionResultType]::ParameterName, 'apply to all appropriate files, not just those that have been modified') - [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') - [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') - [CompletionResult]::new('--dump-bootstrap-shims', 'dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') - [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json') - [CompletionResult]::new('--bypass-bootstrap-lock', 'bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') - [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') - [CompletionResult]::new('--enable-bolt-settings', 'enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') - [CompletionResult]::new('--skip-stage0-validation', 'skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') - [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') - [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') + [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') + [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') + [CompletionResult]::new('--exclude', '--exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') + [CompletionResult]::new('--skip', '--skip', [CompletionResultType]::ParameterName, 'build paths to skip') + [CompletionResult]::new('--rustc-error-format', '--rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') + [CompletionResult]::new('--on-fail', '--on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') + [CompletionResult]::new('--stage', '--stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') + [CompletionResult]::new('--keep-stage', '--keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--keep-stage-std', '--keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--src', '--src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') + [CompletionResult]::new('-j', '-j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--jobs', '--jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') + [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format') + [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') + [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') + [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') + [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') + [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') + [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--check', '--check', [CompletionResultType]::ParameterName, 'check formatting instead of applying') + [CompletionResult]::new('--all', '--all', [CompletionResultType]::ParameterName, 'apply to all appropriate files, not just those that have been modified') + [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--incremental', '--incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--include-default-paths', '--include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') + [CompletionResult]::new('--dry-run', '--dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') + [CompletionResult]::new('--dump-bootstrap-shims', '--dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') + [CompletionResult]::new('--json-output', '--json-output', [CompletionResultType]::ParameterName, 'use message-format=json') + [CompletionResult]::new('--bypass-bootstrap-lock', '--bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') + [CompletionResult]::new('--llvm-profile-generate', '--llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') + [CompletionResult]::new('--enable-bolt-settings', '--enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') + [CompletionResult]::new('--skip-stage0-validation', '--skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') + [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') break } 'x.py;doc' { - [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') - [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') - [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build') - [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build') - [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') - [CompletionResult]::new('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip') - [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') - [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') - [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') - [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') - [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') - [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format') - [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') - [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') - [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') - [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') - [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') - [CompletionResult]::new('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') - [CompletionResult]::new('--open', 'open', [CompletionResultType]::ParameterName, 'open the docs in a browser') - [CompletionResult]::new('--json', 'json', [CompletionResultType]::ParameterName, 'render the documentation in JSON format in addition to the usual HTML format') - [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') - [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') - [CompletionResult]::new('--dump-bootstrap-shims', 'dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') - [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json') - [CompletionResult]::new('--bypass-bootstrap-lock', 'bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') - [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') - [CompletionResult]::new('--enable-bolt-settings', 'enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') - [CompletionResult]::new('--skip-stage0-validation', 'skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') - [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') - [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') + [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') + [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') + [CompletionResult]::new('--exclude', '--exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') + [CompletionResult]::new('--skip', '--skip', [CompletionResultType]::ParameterName, 'build paths to skip') + [CompletionResult]::new('--rustc-error-format', '--rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') + [CompletionResult]::new('--on-fail', '--on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') + [CompletionResult]::new('--stage', '--stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') + [CompletionResult]::new('--keep-stage', '--keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--keep-stage-std', '--keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--src', '--src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') + [CompletionResult]::new('-j', '-j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--jobs', '--jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') + [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format') + [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') + [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') + [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') + [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') + [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') + [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--open', '--open', [CompletionResultType]::ParameterName, 'open the docs in a browser') + [CompletionResult]::new('--json', '--json', [CompletionResultType]::ParameterName, 'render the documentation in JSON format in addition to the usual HTML format') + [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--incremental', '--incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--include-default-paths', '--include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') + [CompletionResult]::new('--dry-run', '--dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') + [CompletionResult]::new('--dump-bootstrap-shims', '--dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') + [CompletionResult]::new('--json-output', '--json-output', [CompletionResultType]::ParameterName, 'use message-format=json') + [CompletionResult]::new('--bypass-bootstrap-lock', '--bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') + [CompletionResult]::new('--llvm-profile-generate', '--llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') + [CompletionResult]::new('--enable-bolt-settings', '--enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') + [CompletionResult]::new('--skip-stage0-validation', '--skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') + [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') break } 'x.py;test' { - [CompletionResult]::new('--test-args', 'test-args', [CompletionResultType]::ParameterName, 'extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)') - [CompletionResult]::new('--compiletest-rustc-args', 'compiletest-rustc-args', [CompletionResultType]::ParameterName, 'extra options to pass the compiler when running compiletest tests') - [CompletionResult]::new('--extra-checks', 'extra-checks', [CompletionResultType]::ParameterName, 'comma-separated list of other files types to check (accepts py, py:lint, py:fmt, shell)') - [CompletionResult]::new('--compare-mode', 'compare-mode', [CompletionResultType]::ParameterName, 'mode describing what file the actual ui output will be compared to') - [CompletionResult]::new('--pass', 'pass', [CompletionResultType]::ParameterName, 'force {check,build,run}-pass tests to this mode') - [CompletionResult]::new('--run', 'run', [CompletionResultType]::ParameterName, 'whether to execute run-* tests') - [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') - [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') - [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build') - [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build') - [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') - [CompletionResult]::new('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip') - [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') - [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') - [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') - [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') - [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') - [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format') - [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') - [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') - [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') - [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') - [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') - [CompletionResult]::new('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') - [CompletionResult]::new('--no-fail-fast', 'no-fail-fast', [CompletionResultType]::ParameterName, 'run all tests regardless of failure') - [CompletionResult]::new('--no-doc', 'no-doc', [CompletionResultType]::ParameterName, 'do not run doc tests') - [CompletionResult]::new('--doc', 'doc', [CompletionResultType]::ParameterName, 'only run doc tests') - [CompletionResult]::new('--bless', 'bless', [CompletionResultType]::ParameterName, 'whether to automatically update stderr/stdout files') - [CompletionResult]::new('--force-rerun', 'force-rerun', [CompletionResultType]::ParameterName, 'rerun tests even if the inputs are unchanged') - [CompletionResult]::new('--only-modified', 'only-modified', [CompletionResultType]::ParameterName, 'only run tests that result has been changed') - [CompletionResult]::new('--rustfix-coverage', 'rustfix-coverage', [CompletionResultType]::ParameterName, 'enable this to generate a Rustfix coverage file, which is saved in `//rustfix_missing_coverage.txt`') - [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') - [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') - [CompletionResult]::new('--dump-bootstrap-shims', 'dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') - [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json') - [CompletionResult]::new('--bypass-bootstrap-lock', 'bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') - [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') - [CompletionResult]::new('--enable-bolt-settings', 'enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') - [CompletionResult]::new('--skip-stage0-validation', 'skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') - [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') - [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--test-args', '--test-args', [CompletionResultType]::ParameterName, 'extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)') + [CompletionResult]::new('--compiletest-rustc-args', '--compiletest-rustc-args', [CompletionResultType]::ParameterName, 'extra options to pass the compiler when running compiletest tests') + [CompletionResult]::new('--extra-checks', '--extra-checks', [CompletionResultType]::ParameterName, 'comma-separated list of other files types to check (accepts py, py:lint, py:fmt, shell)') + [CompletionResult]::new('--compare-mode', '--compare-mode', [CompletionResultType]::ParameterName, 'mode describing what file the actual ui output will be compared to') + [CompletionResult]::new('--pass', '--pass', [CompletionResultType]::ParameterName, 'force {check,build,run}-pass tests to this mode') + [CompletionResult]::new('--run', '--run', [CompletionResultType]::ParameterName, 'whether to execute run-* tests') + [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') + [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') + [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') + [CompletionResult]::new('--exclude', '--exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') + [CompletionResult]::new('--skip', '--skip', [CompletionResultType]::ParameterName, 'build paths to skip') + [CompletionResult]::new('--rustc-error-format', '--rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') + [CompletionResult]::new('--on-fail', '--on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') + [CompletionResult]::new('--stage', '--stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') + [CompletionResult]::new('--keep-stage', '--keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--keep-stage-std', '--keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--src', '--src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') + [CompletionResult]::new('-j', '-j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--jobs', '--jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') + [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format') + [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') + [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') + [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') + [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') + [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') + [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--no-fail-fast', '--no-fail-fast', [CompletionResultType]::ParameterName, 'run all tests regardless of failure') + [CompletionResult]::new('--no-doc', '--no-doc', [CompletionResultType]::ParameterName, 'do not run doc tests') + [CompletionResult]::new('--doc', '--doc', [CompletionResultType]::ParameterName, 'only run doc tests') + [CompletionResult]::new('--bless', '--bless', [CompletionResultType]::ParameterName, 'whether to automatically update stderr/stdout files') + [CompletionResult]::new('--force-rerun', '--force-rerun', [CompletionResultType]::ParameterName, 'rerun tests even if the inputs are unchanged') + [CompletionResult]::new('--only-modified', '--only-modified', [CompletionResultType]::ParameterName, 'only run tests that result has been changed') + [CompletionResult]::new('--rustfix-coverage', '--rustfix-coverage', [CompletionResultType]::ParameterName, 'enable this to generate a Rustfix coverage file, which is saved in `//rustfix_missing_coverage.txt`') + [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--incremental', '--incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--include-default-paths', '--include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') + [CompletionResult]::new('--dry-run', '--dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') + [CompletionResult]::new('--dump-bootstrap-shims', '--dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') + [CompletionResult]::new('--json-output', '--json-output', [CompletionResultType]::ParameterName, 'use message-format=json') + [CompletionResult]::new('--bypass-bootstrap-lock', '--bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') + [CompletionResult]::new('--llvm-profile-generate', '--llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') + [CompletionResult]::new('--enable-bolt-settings', '--enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') + [CompletionResult]::new('--skip-stage0-validation', '--skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') + [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') break } 'x.py;miri' { - [CompletionResult]::new('--test-args', 'test-args', [CompletionResultType]::ParameterName, 'extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)') - [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') - [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') - [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build') - [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build') - [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') - [CompletionResult]::new('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip') - [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') - [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') - [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') - [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') - [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') - [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format') - [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') - [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') - [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') - [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') - [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') - [CompletionResult]::new('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') - [CompletionResult]::new('--no-fail-fast', 'no-fail-fast', [CompletionResultType]::ParameterName, 'run all tests regardless of failure') - [CompletionResult]::new('--no-doc', 'no-doc', [CompletionResultType]::ParameterName, 'do not run doc tests') - [CompletionResult]::new('--doc', 'doc', [CompletionResultType]::ParameterName, 'only run doc tests') - [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') - [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') - [CompletionResult]::new('--dump-bootstrap-shims', 'dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') - [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json') - [CompletionResult]::new('--bypass-bootstrap-lock', 'bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') - [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') - [CompletionResult]::new('--enable-bolt-settings', 'enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') - [CompletionResult]::new('--skip-stage0-validation', 'skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') - [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') - [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--test-args', '--test-args', [CompletionResultType]::ParameterName, 'extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)') + [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') + [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') + [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') + [CompletionResult]::new('--exclude', '--exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') + [CompletionResult]::new('--skip', '--skip', [CompletionResultType]::ParameterName, 'build paths to skip') + [CompletionResult]::new('--rustc-error-format', '--rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') + [CompletionResult]::new('--on-fail', '--on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') + [CompletionResult]::new('--stage', '--stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') + [CompletionResult]::new('--keep-stage', '--keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--keep-stage-std', '--keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--src', '--src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') + [CompletionResult]::new('-j', '-j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--jobs', '--jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') + [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format') + [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') + [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') + [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') + [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') + [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') + [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--no-fail-fast', '--no-fail-fast', [CompletionResultType]::ParameterName, 'run all tests regardless of failure') + [CompletionResult]::new('--no-doc', '--no-doc', [CompletionResultType]::ParameterName, 'do not run doc tests') + [CompletionResult]::new('--doc', '--doc', [CompletionResultType]::ParameterName, 'only run doc tests') + [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--incremental', '--incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--include-default-paths', '--include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') + [CompletionResult]::new('--dry-run', '--dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') + [CompletionResult]::new('--dump-bootstrap-shims', '--dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') + [CompletionResult]::new('--json-output', '--json-output', [CompletionResultType]::ParameterName, 'use message-format=json') + [CompletionResult]::new('--bypass-bootstrap-lock', '--bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') + [CompletionResult]::new('--llvm-profile-generate', '--llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') + [CompletionResult]::new('--enable-bolt-settings', '--enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') + [CompletionResult]::new('--skip-stage0-validation', '--skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') + [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') break } 'x.py;bench' { - [CompletionResult]::new('--test-args', 'test-args', [CompletionResultType]::ParameterName, 'test-args') - [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') - [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') - [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build') - [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build') - [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') - [CompletionResult]::new('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip') - [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') - [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') - [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') - [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') - [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') - [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format') - [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') - [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') - [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') - [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') - [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') - [CompletionResult]::new('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') - [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') - [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') - [CompletionResult]::new('--dump-bootstrap-shims', 'dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') - [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json') - [CompletionResult]::new('--bypass-bootstrap-lock', 'bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') - [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') - [CompletionResult]::new('--enable-bolt-settings', 'enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') - [CompletionResult]::new('--skip-stage0-validation', 'skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') - [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') - [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--test-args', '--test-args', [CompletionResultType]::ParameterName, 'test-args') + [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') + [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') + [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') + [CompletionResult]::new('--exclude', '--exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') + [CompletionResult]::new('--skip', '--skip', [CompletionResultType]::ParameterName, 'build paths to skip') + [CompletionResult]::new('--rustc-error-format', '--rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') + [CompletionResult]::new('--on-fail', '--on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') + [CompletionResult]::new('--stage', '--stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') + [CompletionResult]::new('--keep-stage', '--keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--keep-stage-std', '--keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--src', '--src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') + [CompletionResult]::new('-j', '-j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--jobs', '--jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') + [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format') + [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') + [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') + [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') + [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') + [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') + [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--incremental', '--incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--include-default-paths', '--include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') + [CompletionResult]::new('--dry-run', '--dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') + [CompletionResult]::new('--dump-bootstrap-shims', '--dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') + [CompletionResult]::new('--json-output', '--json-output', [CompletionResultType]::ParameterName, 'use message-format=json') + [CompletionResult]::new('--bypass-bootstrap-lock', '--bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') + [CompletionResult]::new('--llvm-profile-generate', '--llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') + [CompletionResult]::new('--enable-bolt-settings', '--enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') + [CompletionResult]::new('--skip-stage0-validation', '--skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') + [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') break } 'x.py;clean' { - [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'Clean a specific stage without touching other artifacts. By default, every stage is cleaned if this option is not used') - [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') - [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') - [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build') - [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build') - [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') - [CompletionResult]::new('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip') - [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') - [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') - [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') - [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') - [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format') - [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') - [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') - [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') - [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') - [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') - [CompletionResult]::new('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') - [CompletionResult]::new('--all', 'all', [CompletionResultType]::ParameterName, 'Clean the entire build directory (not used by default)') - [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') - [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') - [CompletionResult]::new('--dump-bootstrap-shims', 'dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') - [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json') - [CompletionResult]::new('--bypass-bootstrap-lock', 'bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') - [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') - [CompletionResult]::new('--enable-bolt-settings', 'enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') - [CompletionResult]::new('--skip-stage0-validation', 'skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') - [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') - [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--stage', '--stage', [CompletionResultType]::ParameterName, 'Clean a specific stage without touching other artifacts. By default, every stage is cleaned if this option is not used') + [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') + [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') + [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') + [CompletionResult]::new('--exclude', '--exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') + [CompletionResult]::new('--skip', '--skip', [CompletionResultType]::ParameterName, 'build paths to skip') + [CompletionResult]::new('--rustc-error-format', '--rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') + [CompletionResult]::new('--on-fail', '--on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') + [CompletionResult]::new('--keep-stage', '--keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--keep-stage-std', '--keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--src', '--src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') + [CompletionResult]::new('-j', '-j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--jobs', '--jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') + [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format') + [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') + [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') + [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') + [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') + [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') + [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--all', '--all', [CompletionResultType]::ParameterName, 'Clean the entire build directory (not used by default)') + [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--incremental', '--incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--include-default-paths', '--include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') + [CompletionResult]::new('--dry-run', '--dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') + [CompletionResult]::new('--dump-bootstrap-shims', '--dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') + [CompletionResult]::new('--json-output', '--json-output', [CompletionResultType]::ParameterName, 'use message-format=json') + [CompletionResult]::new('--bypass-bootstrap-lock', '--bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') + [CompletionResult]::new('--llvm-profile-generate', '--llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') + [CompletionResult]::new('--enable-bolt-settings', '--enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') + [CompletionResult]::new('--skip-stage0-validation', '--skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') + [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') break } 'x.py;dist' { - [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') - [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') - [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build') - [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build') - [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') - [CompletionResult]::new('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip') - [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') - [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') - [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') - [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') - [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') - [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format') - [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') - [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') - [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') - [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') - [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') - [CompletionResult]::new('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') - [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') - [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') - [CompletionResult]::new('--dump-bootstrap-shims', 'dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') - [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json') - [CompletionResult]::new('--bypass-bootstrap-lock', 'bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') - [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') - [CompletionResult]::new('--enable-bolt-settings', 'enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') - [CompletionResult]::new('--skip-stage0-validation', 'skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') - [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') - [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') + [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') + [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') + [CompletionResult]::new('--exclude', '--exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') + [CompletionResult]::new('--skip', '--skip', [CompletionResultType]::ParameterName, 'build paths to skip') + [CompletionResult]::new('--rustc-error-format', '--rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') + [CompletionResult]::new('--on-fail', '--on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') + [CompletionResult]::new('--stage', '--stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') + [CompletionResult]::new('--keep-stage', '--keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--keep-stage-std', '--keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--src', '--src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') + [CompletionResult]::new('-j', '-j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--jobs', '--jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') + [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format') + [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') + [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') + [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') + [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') + [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') + [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--incremental', '--incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--include-default-paths', '--include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') + [CompletionResult]::new('--dry-run', '--dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') + [CompletionResult]::new('--dump-bootstrap-shims', '--dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') + [CompletionResult]::new('--json-output', '--json-output', [CompletionResultType]::ParameterName, 'use message-format=json') + [CompletionResult]::new('--bypass-bootstrap-lock', '--bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') + [CompletionResult]::new('--llvm-profile-generate', '--llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') + [CompletionResult]::new('--enable-bolt-settings', '--enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') + [CompletionResult]::new('--skip-stage0-validation', '--skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') + [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') break } 'x.py;install' { - [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') - [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') - [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build') - [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build') - [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') - [CompletionResult]::new('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip') - [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') - [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') - [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') - [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') - [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') - [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format') - [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') - [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') - [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') - [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') - [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') - [CompletionResult]::new('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') - [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') - [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') - [CompletionResult]::new('--dump-bootstrap-shims', 'dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') - [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json') - [CompletionResult]::new('--bypass-bootstrap-lock', 'bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') - [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') - [CompletionResult]::new('--enable-bolt-settings', 'enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') - [CompletionResult]::new('--skip-stage0-validation', 'skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') - [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') - [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') + [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') + [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') + [CompletionResult]::new('--exclude', '--exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') + [CompletionResult]::new('--skip', '--skip', [CompletionResultType]::ParameterName, 'build paths to skip') + [CompletionResult]::new('--rustc-error-format', '--rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') + [CompletionResult]::new('--on-fail', '--on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') + [CompletionResult]::new('--stage', '--stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') + [CompletionResult]::new('--keep-stage', '--keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--keep-stage-std', '--keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--src', '--src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') + [CompletionResult]::new('-j', '-j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--jobs', '--jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') + [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format') + [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') + [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') + [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') + [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') + [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') + [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--incremental', '--incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--include-default-paths', '--include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') + [CompletionResult]::new('--dry-run', '--dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') + [CompletionResult]::new('--dump-bootstrap-shims', '--dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') + [CompletionResult]::new('--json-output', '--json-output', [CompletionResultType]::ParameterName, 'use message-format=json') + [CompletionResult]::new('--bypass-bootstrap-lock', '--bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') + [CompletionResult]::new('--llvm-profile-generate', '--llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') + [CompletionResult]::new('--enable-bolt-settings', '--enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') + [CompletionResult]::new('--skip-stage0-validation', '--skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') + [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') break } 'x.py;run' { - [CompletionResult]::new('--args', 'args', [CompletionResultType]::ParameterName, 'arguments for the tool') - [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') - [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') - [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build') - [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build') - [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') - [CompletionResult]::new('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip') - [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') - [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') - [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') - [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') - [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') - [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format') - [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') - [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') - [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') - [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') - [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') - [CompletionResult]::new('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') - [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') - [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') - [CompletionResult]::new('--dump-bootstrap-shims', 'dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') - [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json') - [CompletionResult]::new('--bypass-bootstrap-lock', 'bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') - [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') - [CompletionResult]::new('--enable-bolt-settings', 'enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') - [CompletionResult]::new('--skip-stage0-validation', 'skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') - [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') - [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--args', '--args', [CompletionResultType]::ParameterName, 'arguments for the tool') + [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') + [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') + [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') + [CompletionResult]::new('--exclude', '--exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') + [CompletionResult]::new('--skip', '--skip', [CompletionResultType]::ParameterName, 'build paths to skip') + [CompletionResult]::new('--rustc-error-format', '--rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') + [CompletionResult]::new('--on-fail', '--on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') + [CompletionResult]::new('--stage', '--stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') + [CompletionResult]::new('--keep-stage', '--keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--keep-stage-std', '--keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--src', '--src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') + [CompletionResult]::new('-j', '-j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--jobs', '--jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') + [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format') + [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') + [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') + [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') + [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') + [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') + [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--incremental', '--incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--include-default-paths', '--include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') + [CompletionResult]::new('--dry-run', '--dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') + [CompletionResult]::new('--dump-bootstrap-shims', '--dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') + [CompletionResult]::new('--json-output', '--json-output', [CompletionResultType]::ParameterName, 'use message-format=json') + [CompletionResult]::new('--bypass-bootstrap-lock', '--bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') + [CompletionResult]::new('--llvm-profile-generate', '--llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') + [CompletionResult]::new('--enable-bolt-settings', '--enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') + [CompletionResult]::new('--skip-stage0-validation', '--skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') + [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') break } 'x.py;setup' { - [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') - [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') - [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build') - [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build') - [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') - [CompletionResult]::new('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip') - [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') - [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') - [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') - [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') - [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') - [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format') - [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') - [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') - [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') - [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') - [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') - [CompletionResult]::new('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') - [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') - [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') - [CompletionResult]::new('--dump-bootstrap-shims', 'dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') - [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json') - [CompletionResult]::new('--bypass-bootstrap-lock', 'bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') - [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') - [CompletionResult]::new('--enable-bolt-settings', 'enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') - [CompletionResult]::new('--skip-stage0-validation', 'skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') - [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') - [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') + [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') + [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') + [CompletionResult]::new('--exclude', '--exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') + [CompletionResult]::new('--skip', '--skip', [CompletionResultType]::ParameterName, 'build paths to skip') + [CompletionResult]::new('--rustc-error-format', '--rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') + [CompletionResult]::new('--on-fail', '--on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') + [CompletionResult]::new('--stage', '--stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') + [CompletionResult]::new('--keep-stage', '--keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--keep-stage-std', '--keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--src', '--src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') + [CompletionResult]::new('-j', '-j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--jobs', '--jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') + [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format') + [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') + [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') + [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') + [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') + [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') + [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--incremental', '--incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--include-default-paths', '--include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') + [CompletionResult]::new('--dry-run', '--dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') + [CompletionResult]::new('--dump-bootstrap-shims', '--dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') + [CompletionResult]::new('--json-output', '--json-output', [CompletionResultType]::ParameterName, 'use message-format=json') + [CompletionResult]::new('--bypass-bootstrap-lock', '--bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') + [CompletionResult]::new('--llvm-profile-generate', '--llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') + [CompletionResult]::new('--enable-bolt-settings', '--enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') + [CompletionResult]::new('--skip-stage0-validation', '--skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') + [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') break } 'x.py;suggest' { - [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') - [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') - [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build') - [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build') - [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') - [CompletionResult]::new('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip') - [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') - [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') - [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') - [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') - [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') - [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format') - [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') - [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') - [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') - [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') - [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') - [CompletionResult]::new('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') - [CompletionResult]::new('--run', 'run', [CompletionResultType]::ParameterName, 'run suggested tests') - [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') - [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') - [CompletionResult]::new('--dump-bootstrap-shims', 'dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') - [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json') - [CompletionResult]::new('--bypass-bootstrap-lock', 'bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') - [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') - [CompletionResult]::new('--enable-bolt-settings', 'enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') - [CompletionResult]::new('--skip-stage0-validation', 'skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') - [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') - [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') + [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') + [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') + [CompletionResult]::new('--exclude', '--exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') + [CompletionResult]::new('--skip', '--skip', [CompletionResultType]::ParameterName, 'build paths to skip') + [CompletionResult]::new('--rustc-error-format', '--rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') + [CompletionResult]::new('--on-fail', '--on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') + [CompletionResult]::new('--stage', '--stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') + [CompletionResult]::new('--keep-stage', '--keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--keep-stage-std', '--keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--src', '--src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') + [CompletionResult]::new('-j', '-j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--jobs', '--jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') + [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format') + [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') + [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') + [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') + [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') + [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') + [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--run', '--run', [CompletionResultType]::ParameterName, 'run suggested tests') + [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--incremental', '--incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--include-default-paths', '--include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') + [CompletionResult]::new('--dry-run', '--dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') + [CompletionResult]::new('--dump-bootstrap-shims', '--dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') + [CompletionResult]::new('--json-output', '--json-output', [CompletionResultType]::ParameterName, 'use message-format=json') + [CompletionResult]::new('--bypass-bootstrap-lock', '--bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') + [CompletionResult]::new('--llvm-profile-generate', '--llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') + [CompletionResult]::new('--enable-bolt-settings', '--enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') + [CompletionResult]::new('--skip-stage0-validation', '--skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') + [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') break } 'x.py;vendor' { - [CompletionResult]::new('--sync', 'sync', [CompletionResultType]::ParameterName, 'Additional `Cargo.toml` to sync and vendor') - [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') - [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') - [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build') - [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build') - [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') - [CompletionResult]::new('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip') - [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') - [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') - [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') - [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') - [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') - [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format') - [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') - [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') - [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') - [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') - [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') - [CompletionResult]::new('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') - [CompletionResult]::new('--versioned-dirs', 'versioned-dirs', [CompletionResultType]::ParameterName, 'Always include version in subdir name') - [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') - [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') - [CompletionResult]::new('--dump-bootstrap-shims', 'dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') - [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json') - [CompletionResult]::new('--bypass-bootstrap-lock', 'bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') - [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') - [CompletionResult]::new('--enable-bolt-settings', 'enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') - [CompletionResult]::new('--skip-stage0-validation', 'skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') - [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') - [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--sync', '--sync', [CompletionResultType]::ParameterName, 'Additional `Cargo.toml` to sync and vendor') + [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') + [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') + [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') + [CompletionResult]::new('--exclude', '--exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') + [CompletionResult]::new('--skip', '--skip', [CompletionResultType]::ParameterName, 'build paths to skip') + [CompletionResult]::new('--rustc-error-format', '--rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') + [CompletionResult]::new('--on-fail', '--on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') + [CompletionResult]::new('--stage', '--stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') + [CompletionResult]::new('--keep-stage', '--keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--keep-stage-std', '--keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--src', '--src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') + [CompletionResult]::new('-j', '-j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--jobs', '--jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') + [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format') + [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') + [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') + [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') + [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') + [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') + [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--versioned-dirs', '--versioned-dirs', [CompletionResultType]::ParameterName, 'Always include version in subdir name') + [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--incremental', '--incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--include-default-paths', '--include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') + [CompletionResult]::new('--dry-run', '--dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') + [CompletionResult]::new('--dump-bootstrap-shims', '--dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') + [CompletionResult]::new('--json-output', '--json-output', [CompletionResultType]::ParameterName, 'use message-format=json') + [CompletionResult]::new('--bypass-bootstrap-lock', '--bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') + [CompletionResult]::new('--llvm-profile-generate', '--llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') + [CompletionResult]::new('--enable-bolt-settings', '--enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') + [CompletionResult]::new('--skip-stage0-validation', '--skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') + [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') break } 'x.py;perf' { - [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') - [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') - [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build') - [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build') - [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') - [CompletionResult]::new('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip') - [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') - [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') - [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') - [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') - [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') - [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') - [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') - [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format') - [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') - [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') - [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') - [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') - [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') - [CompletionResult]::new('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') - [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') - [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') - [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') - [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') - [CompletionResult]::new('--dump-bootstrap-shims', 'dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') - [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json') - [CompletionResult]::new('--bypass-bootstrap-lock', 'bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') - [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') - [CompletionResult]::new('--enable-bolt-settings', 'enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') - [CompletionResult]::new('--skip-stage0-validation', 'skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') - [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') - [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') + [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') + [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') + [CompletionResult]::new('--exclude', '--exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') + [CompletionResult]::new('--skip', '--skip', [CompletionResultType]::ParameterName, 'build paths to skip') + [CompletionResult]::new('--rustc-error-format', '--rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') + [CompletionResult]::new('--on-fail', '--on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') + [CompletionResult]::new('--stage', '--stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') + [CompletionResult]::new('--keep-stage', '--keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--keep-stage-std', '--keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--src', '--src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') + [CompletionResult]::new('-j', '-j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--jobs', '--jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') + [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format') + [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') + [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') + [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') + [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') + [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') + [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--incremental', '--incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--include-default-paths', '--include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') + [CompletionResult]::new('--dry-run', '--dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') + [CompletionResult]::new('--dump-bootstrap-shims', '--dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') + [CompletionResult]::new('--json-output', '--json-output', [CompletionResultType]::ParameterName, 'use message-format=json') + [CompletionResult]::new('--bypass-bootstrap-lock', '--bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') + [CompletionResult]::new('--llvm-profile-generate', '--llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') + [CompletionResult]::new('--enable-bolt-settings', '--enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') + [CompletionResult]::new('--skip-stage0-validation', '--skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') + [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') break } }) diff --git a/src/etc/completions/x.py.sh b/src/etc/completions/x.py.sh index 60ba8d3ba70..b1730e5c6d8 100644 --- a/src/etc/completions/x.py.sh +++ b/src/etc/completions/x.py.sh @@ -12,56 +12,56 @@ _x.py() { ",$1") cmd="x.py" ;; - bootstrap,bench) - cmd="bootstrap__bench" + x.py,bench) + cmd="x.py__bench" ;; - bootstrap,build) - cmd="bootstrap__build" + x.py,build) + cmd="x.py__build" ;; - bootstrap,check) - cmd="bootstrap__check" + x.py,check) + cmd="x.py__check" ;; - bootstrap,clean) - cmd="bootstrap__clean" + x.py,clean) + cmd="x.py__clean" ;; - bootstrap,clippy) - cmd="bootstrap__clippy" + x.py,clippy) + cmd="x.py__clippy" ;; - bootstrap,dist) - cmd="bootstrap__dist" + x.py,dist) + cmd="x.py__dist" ;; - bootstrap,doc) - cmd="bootstrap__doc" + x.py,doc) + cmd="x.py__doc" ;; - bootstrap,fix) - cmd="bootstrap__fix" + x.py,fix) + cmd="x.py__fix" ;; - bootstrap,fmt) - cmd="bootstrap__fmt" + x.py,fmt) + cmd="x.py__fmt" ;; - bootstrap,install) - cmd="bootstrap__install" + x.py,install) + cmd="x.py__install" ;; - bootstrap,miri) - cmd="bootstrap__miri" + x.py,miri) + cmd="x.py__miri" ;; - bootstrap,perf) - cmd="bootstrap__perf" + x.py,perf) + cmd="x.py__perf" ;; - bootstrap,run) - cmd="bootstrap__run" + x.py,run) + cmd="x.py__run" ;; - bootstrap,setup) - cmd="bootstrap__setup" + x.py,setup) + cmd="x.py__setup" ;; - bootstrap,suggest) - cmd="bootstrap__suggest" + x.py,suggest) + cmd="x.py__suggest" ;; - bootstrap,test) - cmd="bootstrap__test" + x.py,test) + cmd="x.py__test" ;; - bootstrap,vendor) - cmd="bootstrap__vendor" + x.py,vendor) + cmd="x.py__vendor" ;; *) ;; @@ -77,23 +77,46 @@ _x.py() { fi case "${prev}" in --config) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --build-dir) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --build) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --host) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --target) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --exclude) @@ -106,6 +129,9 @@ _x.py() { ;; --rustc-error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --on-fail) @@ -114,26 +140,44 @@ _x.py() { ;; --stage) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --keep-stage) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --keep-stage-std) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --src) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --jobs) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; -j) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --warnings) @@ -142,6 +186,9 @@ _x.py() { ;; --error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --color) @@ -153,15 +200,48 @@ _x.py() { return 0 ;; --rust-profile-generate) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --rust-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --llvm-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --reproducible-artifact) @@ -170,6 +250,9 @@ _x.py() { ;; --set) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; *) @@ -191,23 +274,46 @@ _x.py() { return 0 ;; --config) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --build-dir) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --build) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --host) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --target) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --exclude) @@ -220,6 +326,9 @@ _x.py() { ;; --rustc-error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --on-fail) @@ -228,26 +337,44 @@ _x.py() { ;; --stage) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --keep-stage) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --keep-stage-std) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --src) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --jobs) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; -j) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --warnings) @@ -256,6 +383,9 @@ _x.py() { ;; --error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --color) @@ -267,15 +397,48 @@ _x.py() { return 0 ;; --rust-profile-generate) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --rust-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --llvm-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --reproducible-artifact) @@ -284,6 +447,9 @@ _x.py() { ;; --set) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; *) @@ -301,23 +467,46 @@ _x.py() { fi case "${prev}" in --config) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --build-dir) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --build) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --host) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --target) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --exclude) @@ -330,6 +519,9 @@ _x.py() { ;; --rustc-error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --on-fail) @@ -338,26 +530,44 @@ _x.py() { ;; --stage) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --keep-stage) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --keep-stage-std) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --src) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --jobs) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; -j) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --warnings) @@ -366,6 +576,9 @@ _x.py() { ;; --error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --color) @@ -377,15 +590,48 @@ _x.py() { return 0 ;; --rust-profile-generate) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --rust-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --llvm-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --reproducible-artifact) @@ -394,6 +640,9 @@ _x.py() { ;; --set) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; *) @@ -411,23 +660,46 @@ _x.py() { fi case "${prev}" in --config) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --build-dir) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --build) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --host) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --target) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --exclude) @@ -440,6 +712,9 @@ _x.py() { ;; --rustc-error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --on-fail) @@ -448,26 +723,44 @@ _x.py() { ;; --stage) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --keep-stage) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --keep-stage-std) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --src) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --jobs) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; -j) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --warnings) @@ -476,6 +769,9 @@ _x.py() { ;; --error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --color) @@ -487,15 +783,48 @@ _x.py() { return 0 ;; --rust-profile-generate) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --rust-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --llvm-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --reproducible-artifact) @@ -504,6 +833,9 @@ _x.py() { ;; --set) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; *) @@ -525,23 +857,46 @@ _x.py() { return 0 ;; --config) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --build-dir) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --build) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --host) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --target) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --exclude) @@ -554,6 +909,9 @@ _x.py() { ;; --rustc-error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --on-fail) @@ -562,22 +920,37 @@ _x.py() { ;; --keep-stage) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --keep-stage-std) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --src) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --jobs) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; -j) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --warnings) @@ -586,6 +959,9 @@ _x.py() { ;; --error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --color) @@ -597,15 +973,48 @@ _x.py() { return 0 ;; --rust-profile-generate) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --rust-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --llvm-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --reproducible-artifact) @@ -614,6 +1023,9 @@ _x.py() { ;; --set) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; *) @@ -647,23 +1059,46 @@ _x.py() { return 0 ;; --config) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --build-dir) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --build) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --host) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --target) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --exclude) @@ -676,6 +1111,9 @@ _x.py() { ;; --rustc-error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --on-fail) @@ -684,26 +1122,44 @@ _x.py() { ;; --stage) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --keep-stage) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --keep-stage-std) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --src) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --jobs) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; -j) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --warnings) @@ -712,6 +1168,9 @@ _x.py() { ;; --error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --color) @@ -723,15 +1182,48 @@ _x.py() { return 0 ;; --rust-profile-generate) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --rust-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --llvm-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --reproducible-artifact) @@ -740,6 +1232,9 @@ _x.py() { ;; --set) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; *) @@ -757,23 +1252,46 @@ _x.py() { fi case "${prev}" in --config) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --build-dir) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --build) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --host) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --target) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --exclude) @@ -786,6 +1304,9 @@ _x.py() { ;; --rustc-error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --on-fail) @@ -794,26 +1315,44 @@ _x.py() { ;; --stage) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --keep-stage) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --keep-stage-std) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --src) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --jobs) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; -j) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --warnings) @@ -822,6 +1361,9 @@ _x.py() { ;; --error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --color) @@ -833,15 +1375,48 @@ _x.py() { return 0 ;; --rust-profile-generate) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --rust-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --llvm-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --reproducible-artifact) @@ -850,6 +1425,9 @@ _x.py() { ;; --set) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; *) @@ -867,23 +1445,46 @@ _x.py() { fi case "${prev}" in --config) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --build-dir) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --build) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --host) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --target) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --exclude) @@ -896,6 +1497,9 @@ _x.py() { ;; --rustc-error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --on-fail) @@ -904,26 +1508,44 @@ _x.py() { ;; --stage) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --keep-stage) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --keep-stage-std) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --src) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --jobs) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; -j) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --warnings) @@ -932,6 +1554,9 @@ _x.py() { ;; --error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --color) @@ -943,15 +1568,48 @@ _x.py() { return 0 ;; --rust-profile-generate) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --rust-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --llvm-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --reproducible-artifact) @@ -960,6 +1618,9 @@ _x.py() { ;; --set) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; *) @@ -977,23 +1638,46 @@ _x.py() { fi case "${prev}" in --config) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --build-dir) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --build) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --host) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --target) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --exclude) @@ -1006,6 +1690,9 @@ _x.py() { ;; --rustc-error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --on-fail) @@ -1014,26 +1701,44 @@ _x.py() { ;; --stage) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --keep-stage) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --keep-stage-std) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --src) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --jobs) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; -j) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --warnings) @@ -1042,6 +1747,9 @@ _x.py() { ;; --error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --color) @@ -1053,15 +1761,48 @@ _x.py() { return 0 ;; --rust-profile-generate) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --rust-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --llvm-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --reproducible-artifact) @@ -1070,6 +1811,9 @@ _x.py() { ;; --set) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; *) @@ -1087,23 +1831,46 @@ _x.py() { fi case "${prev}" in --config) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --build-dir) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --build) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --host) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --target) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --exclude) @@ -1116,6 +1883,9 @@ _x.py() { ;; --rustc-error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --on-fail) @@ -1124,26 +1894,44 @@ _x.py() { ;; --stage) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --keep-stage) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --keep-stage-std) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --src) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --jobs) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; -j) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --warnings) @@ -1152,6 +1940,9 @@ _x.py() { ;; --error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --color) @@ -1163,15 +1954,48 @@ _x.py() { return 0 ;; --rust-profile-generate) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --rust-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --llvm-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --reproducible-artifact) @@ -1180,6 +2004,9 @@ _x.py() { ;; --set) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; *) @@ -1197,23 +2024,46 @@ _x.py() { fi case "${prev}" in --config) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --build-dir) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --build) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --host) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --target) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --exclude) @@ -1226,6 +2076,9 @@ _x.py() { ;; --rustc-error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --on-fail) @@ -1234,26 +2087,44 @@ _x.py() { ;; --stage) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --keep-stage) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --keep-stage-std) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --src) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --jobs) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; -j) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --warnings) @@ -1262,6 +2133,9 @@ _x.py() { ;; --error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --color) @@ -1273,15 +2147,48 @@ _x.py() { return 0 ;; --rust-profile-generate) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --rust-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --llvm-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --reproducible-artifact) @@ -1290,6 +2197,9 @@ _x.py() { ;; --set) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; *) @@ -1311,23 +2221,46 @@ _x.py() { return 0 ;; --config) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --build-dir) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --build) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --host) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --target) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --exclude) @@ -1340,6 +2273,9 @@ _x.py() { ;; --rustc-error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --on-fail) @@ -1348,26 +2284,44 @@ _x.py() { ;; --stage) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --keep-stage) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --keep-stage-std) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --src) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --jobs) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; -j) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --warnings) @@ -1376,6 +2330,9 @@ _x.py() { ;; --error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --color) @@ -1387,15 +2344,48 @@ _x.py() { return 0 ;; --rust-profile-generate) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --rust-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --llvm-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --reproducible-artifact) @@ -1404,6 +2394,9 @@ _x.py() { ;; --set) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; *) @@ -1421,23 +2414,46 @@ _x.py() { fi case "${prev}" in --config) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --build-dir) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --build) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --host) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --target) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --exclude) @@ -1450,6 +2466,9 @@ _x.py() { ;; --rustc-error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --on-fail) @@ -1458,26 +2477,44 @@ _x.py() { ;; --stage) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --keep-stage) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --keep-stage-std) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --src) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --jobs) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; -j) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --warnings) @@ -1486,6 +2523,9 @@ _x.py() { ;; --error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --color) @@ -1497,15 +2537,48 @@ _x.py() { return 0 ;; --rust-profile-generate) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --rust-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --llvm-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --reproducible-artifact) @@ -1514,6 +2587,9 @@ _x.py() { ;; --set) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; *) @@ -1535,23 +2611,46 @@ _x.py() { return 0 ;; --config) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --build-dir) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --build) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --host) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --target) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --exclude) @@ -1564,6 +2663,9 @@ _x.py() { ;; --rustc-error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --on-fail) @@ -1572,26 +2674,44 @@ _x.py() { ;; --stage) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --keep-stage) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --keep-stage-std) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --src) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --jobs) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; -j) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --warnings) @@ -1600,6 +2720,9 @@ _x.py() { ;; --error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --color) @@ -1611,15 +2734,48 @@ _x.py() { return 0 ;; --rust-profile-generate) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --rust-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --llvm-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --reproducible-artifact) @@ -1628,6 +2784,9 @@ _x.py() { ;; --set) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; *) @@ -1645,23 +2804,46 @@ _x.py() { fi case "${prev}" in --config) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --build-dir) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --build) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --host) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --target) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --exclude) @@ -1674,6 +2856,9 @@ _x.py() { ;; --rustc-error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --on-fail) @@ -1682,26 +2867,44 @@ _x.py() { ;; --stage) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --keep-stage) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --keep-stage-std) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --src) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --jobs) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; -j) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --warnings) @@ -1710,6 +2913,9 @@ _x.py() { ;; --error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --color) @@ -1721,15 +2927,48 @@ _x.py() { return 0 ;; --rust-profile-generate) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --rust-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --llvm-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --reproducible-artifact) @@ -1738,6 +2977,9 @@ _x.py() { ;; --set) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; *) @@ -1755,23 +2997,46 @@ _x.py() { fi case "${prev}" in --config) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --build-dir) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --build) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --host) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --target) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --exclude) @@ -1784,6 +3049,9 @@ _x.py() { ;; --rustc-error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --on-fail) @@ -1792,26 +3060,44 @@ _x.py() { ;; --stage) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --keep-stage) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --keep-stage-std) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --src) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --jobs) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; -j) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --warnings) @@ -1820,6 +3106,9 @@ _x.py() { ;; --error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --color) @@ -1831,15 +3120,48 @@ _x.py() { return 0 ;; --rust-profile-generate) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --rust-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --llvm-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --reproducible-artifact) @@ -1848,6 +3170,9 @@ _x.py() { ;; --set) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; *) @@ -1889,23 +3214,46 @@ _x.py() { return 0 ;; --config) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --build-dir) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --build) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --host) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --target) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --exclude) @@ -1918,6 +3266,9 @@ _x.py() { ;; --rustc-error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --on-fail) @@ -1926,26 +3277,44 @@ _x.py() { ;; --stage) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --keep-stage) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --keep-stage-std) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --src) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --jobs) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; -j) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --warnings) @@ -1954,6 +3323,9 @@ _x.py() { ;; --error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --color) @@ -1965,15 +3337,48 @@ _x.py() { return 0 ;; --rust-profile-generate) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --rust-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --llvm-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --reproducible-artifact) @@ -1982,6 +3387,9 @@ _x.py() { ;; --set) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; *) @@ -2003,23 +3411,46 @@ _x.py() { return 0 ;; --config) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --build-dir) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --build) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --host) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --target) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --exclude) @@ -2032,6 +3463,9 @@ _x.py() { ;; --rustc-error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --on-fail) @@ -2040,26 +3474,44 @@ _x.py() { ;; --stage) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --keep-stage) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --keep-stage-std) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --src) - COMPREPLY=($(compgen -f "${cur}")) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi return 0 ;; --jobs) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; -j) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --warnings) @@ -2068,6 +3520,9 @@ _x.py() { ;; --error-format) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; --color) @@ -2079,15 +3534,48 @@ _x.py() { return 0 ;; --rust-profile-generate) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --rust-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --llvm-profile-use) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --reproducible-artifact) @@ -2096,6 +3584,9 @@ _x.py() { ;; --set) COMPREPLY=("${cur}") + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o nospace + fi return 0 ;; *) diff --git a/src/etc/completions/x.py.zsh b/src/etc/completions/x.py.zsh index 688f692da24..ae076b88345 100644 --- a/src/etc/completions/x.py.zsh +++ b/src/etc/completions/x.py.zsh @@ -14,7 +14,7 @@ _x.py() { fi local context curcontext="$curcontext" state line - _arguments "${_arguments_options[@]}" \ + _arguments "${_arguments_options[@]}" : \ '--config=[TOML configuration file for build]:FILE:_files' \ '--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:( )' \ @@ -65,7 +65,7 @@ _x.py() { curcontext="${curcontext%:*:*}:x.py-command-$line[3]:" case $line[3] in (build) -_arguments "${_arguments_options[@]}" \ +_arguments "${_arguments_options[@]}" : \ '--config=[TOML configuration file for build]:FILE:_files' \ '--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:( )' \ @@ -108,7 +108,7 @@ _arguments "${_arguments_options[@]}" \ && ret=0 ;; (check) -_arguments "${_arguments_options[@]}" \ +_arguments "${_arguments_options[@]}" : \ '--config=[TOML configuration file for build]:FILE:_files' \ '--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:( )' \ @@ -152,7 +152,7 @@ _arguments "${_arguments_options[@]}" \ && ret=0 ;; (clippy) -_arguments "${_arguments_options[@]}" \ +_arguments "${_arguments_options[@]}" : \ '*-A+[clippy lints to allow]:LINT: ' \ '*-D+[clippy lints to deny]:LINT: ' \ '*-W+[clippy lints to warn on]:LINT: ' \ @@ -202,7 +202,7 @@ _arguments "${_arguments_options[@]}" \ && ret=0 ;; (fix) -_arguments "${_arguments_options[@]}" \ +_arguments "${_arguments_options[@]}" : \ '--config=[TOML configuration file for build]:FILE:_files' \ '--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:( )' \ @@ -245,7 +245,7 @@ _arguments "${_arguments_options[@]}" \ && ret=0 ;; (fmt) -_arguments "${_arguments_options[@]}" \ +_arguments "${_arguments_options[@]}" : \ '--config=[TOML configuration file for build]:FILE:_files' \ '--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:( )' \ @@ -290,7 +290,7 @@ _arguments "${_arguments_options[@]}" \ && ret=0 ;; (doc) -_arguments "${_arguments_options[@]}" \ +_arguments "${_arguments_options[@]}" : \ '--config=[TOML configuration file for build]:FILE:_files' \ '--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:( )' \ @@ -335,7 +335,7 @@ _arguments "${_arguments_options[@]}" \ && ret=0 ;; (test) -_arguments "${_arguments_options[@]}" \ +_arguments "${_arguments_options[@]}" : \ '*--test-args=[extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)]:ARGS: ' \ '*--compiletest-rustc-args=[extra options to pass the compiler when running compiletest tests]:ARGS: ' \ '--extra-checks=[comma-separated list of other files types to check (accepts py, py\:lint, py\:fmt, shell)]:EXTRA_CHECKS: ' \ @@ -391,7 +391,7 @@ _arguments "${_arguments_options[@]}" \ && ret=0 ;; (miri) -_arguments "${_arguments_options[@]}" \ +_arguments "${_arguments_options[@]}" : \ '*--test-args=[extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)]:ARGS: ' \ '--config=[TOML configuration file for build]:FILE:_files' \ '--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ @@ -438,7 +438,7 @@ _arguments "${_arguments_options[@]}" \ && ret=0 ;; (bench) -_arguments "${_arguments_options[@]}" \ +_arguments "${_arguments_options[@]}" : \ '*--test-args=[]:TEST_ARGS: ' \ '--config=[TOML configuration file for build]:FILE:_files' \ '--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ @@ -482,7 +482,7 @@ _arguments "${_arguments_options[@]}" \ && ret=0 ;; (clean) -_arguments "${_arguments_options[@]}" \ +_arguments "${_arguments_options[@]}" : \ '--stage=[Clean a specific stage without touching other artifacts. By default, every stage is cleaned if this option is not used]:N: ' \ '--config=[TOML configuration file for build]:FILE:_files' \ '--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ @@ -526,7 +526,7 @@ _arguments "${_arguments_options[@]}" \ && ret=0 ;; (dist) -_arguments "${_arguments_options[@]}" \ +_arguments "${_arguments_options[@]}" : \ '--config=[TOML configuration file for build]:FILE:_files' \ '--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:( )' \ @@ -569,7 +569,7 @@ _arguments "${_arguments_options[@]}" \ && ret=0 ;; (install) -_arguments "${_arguments_options[@]}" \ +_arguments "${_arguments_options[@]}" : \ '--config=[TOML configuration file for build]:FILE:_files' \ '--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:( )' \ @@ -612,7 +612,7 @@ _arguments "${_arguments_options[@]}" \ && ret=0 ;; (run) -_arguments "${_arguments_options[@]}" \ +_arguments "${_arguments_options[@]}" : \ '*--args=[arguments for the tool]:ARGS: ' \ '--config=[TOML configuration file for build]:FILE:_files' \ '--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ @@ -656,7 +656,7 @@ _arguments "${_arguments_options[@]}" \ && ret=0 ;; (setup) -_arguments "${_arguments_options[@]}" \ +_arguments "${_arguments_options[@]}" : \ '--config=[TOML configuration file for build]:FILE:_files' \ '--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:( )' \ @@ -700,7 +700,7 @@ _arguments "${_arguments_options[@]}" \ && ret=0 ;; (suggest) -_arguments "${_arguments_options[@]}" \ +_arguments "${_arguments_options[@]}" : \ '--config=[TOML configuration file for build]:FILE:_files' \ '--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:( )' \ @@ -744,7 +744,7 @@ _arguments "${_arguments_options[@]}" \ && ret=0 ;; (vendor) -_arguments "${_arguments_options[@]}" \ +_arguments "${_arguments_options[@]}" : \ '*--sync=[Additional \`Cargo.toml\` to sync and vendor]:SYNC:_files' \ '--config=[TOML configuration file for build]:FILE:_files' \ '--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ @@ -789,7 +789,7 @@ _arguments "${_arguments_options[@]}" \ && ret=0 ;; (perf) -_arguments "${_arguments_options[@]}" \ +_arguments "${_arguments_options[@]}" : \ '--config=[TOML configuration file for build]:FILE:_files' \ '--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:( )' \ diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index b3fccbf6456..34332de80b3 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -12,7 +12,7 @@ rinja = { version = "0.3", default-features = false, features = ["config"] } base64 = "0.21.7" itertools = "0.12" indexmap = "2" -minifier = "0.3.0" +minifier = "0.3.1" pulldown-cmark-old = { version = "0.9.6", package = "pulldown-cmark", default-features = false } regex = "1" rustdoc-json-types = { path = "../rustdoc-json-types" } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index cffadc7c10a..5260e363dd6 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -272,7 +272,7 @@ fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) -> | rbv::ResolvedArg::LateBound(_, _, did) | rbv::ResolvedArg::Free(_, did), ) = cx.tcx.named_bound_var(lifetime.hir_id) - && let Some(lt) = cx.args.get(&did).and_then(|arg| arg.as_lt()) + && let Some(lt) = cx.args.get(&did.to_def_id()).and_then(|arg| arg.as_lt()) { return lt.clone(); } @@ -2069,7 +2069,7 @@ pub(crate) fn clean_middle_ty<'tcx>( Some(ContainerTy::Ref(r)), )), }, - ty::FnDef(..) | ty::FnPtr(_) => { + ty::FnDef(..) | ty::FnPtr(..) => { // FIXME: should we merge the outer and inner binders somehow? let sig = bound_ty.skip_binder().fn_sig(cx.tcx); let decl = clean_poly_fn_sig(cx, None, sig); @@ -3094,16 +3094,10 @@ fn clean_maybe_renamed_foreign_item<'tcx>( let def_id = item.owner_id.to_def_id(); cx.with_param_env(def_id, |cx| { let kind = match item.kind { - hir::ForeignItemKind::Fn(decl, names, generics, safety) => { - let (generics, decl) = enter_impl_trait(cx, |cx| { - // NOTE: generics must be cleaned before args - let generics = clean_generics(generics, cx); - let args = clean_args_from_types_and_names(cx, decl.inputs, names); - let decl = clean_fn_decl_with_args(cx, decl, None, args); - (generics, decl) - }); - ForeignFunctionItem(Box::new(Function { decl, generics }), safety) - } + hir::ForeignItemKind::Fn(sig, names, generics) => ForeignFunctionItem( + clean_function(cx, &sig, generics, FunctionArgs::Names(names)), + sig.header.safety, + ), hir::ForeignItemKind::Static(ty, mutability, safety) => ForeignStaticItem( Static { type_: Box::new(clean_ty(ty, cx)), mutability, expr: None }, safety, diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index ff5c16f2b3e..63d71a73cdf 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -12,7 +12,7 @@ use rustc_attr::{ConstStability, Deprecation, Stability, StabilityLevel, StableS use rustc_const_eval::const_eval::is_unstable_const_fn; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::def::{CtorKind, DefKind, Res}; -use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; use rustc_hir::lang_items::LangItem; use rustc_hir::{BodyId, Mutability}; use rustc_hir_analysis::check::intrinsic::intrinsic_operation_unsafety; @@ -88,6 +88,11 @@ impl ItemId { } } + #[inline] + pub(crate) fn as_local_def_id(self) -> Option { + self.as_def_id().and_then(|id| id.as_local()) + } + #[inline] pub(crate) fn krate(self) -> CrateNum { match self { diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 9c7a9f8467f..9e9d8f02a2e 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -286,6 +286,9 @@ pub(crate) struct RenderOptions { pub(crate) no_emit_shared: bool, /// If `true`, HTML source code pages won't be generated. pub(crate) html_no_source: bool, + /// This field is only used for the JSON output. If it's set to true, no file will be created + /// and content will be displayed in stdout directly. + pub(crate) output_to_stdout: bool, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -548,16 +551,17 @@ impl Options { dcx.fatal("the `--test` flag must be passed to enable `--no-run`"); } + let mut output_to_stdout = false; let test_builder_wrappers = matches.opt_strs("test-builder-wrapper").iter().map(PathBuf::from).collect(); - let out_dir = matches.opt_str("out-dir").map(|s| PathBuf::from(&s)); - let output = matches.opt_str("output").map(|s| PathBuf::from(&s)); - let output = match (out_dir, output) { + let output = match (matches.opt_str("out-dir"), matches.opt_str("output")) { (Some(_), Some(_)) => { dcx.fatal("cannot use both 'out-dir' and 'output' at once"); } - (Some(out_dir), None) => out_dir, - (None, Some(output)) => output, + (Some(out_dir), None) | (None, Some(out_dir)) => { + output_to_stdout = out_dir == "-"; + PathBuf::from(out_dir) + } (None, None) => PathBuf::from("doc"), }; @@ -733,9 +737,11 @@ impl Options { let html_no_source = matches.opt_present("html-no-source"); if generate_link_to_definition && (show_coverage || output_format != OutputFormat::Html) { - dcx.fatal( - "--generate-link-to-definition option can only be used with HTML output format", - ); + dcx.struct_warn( + "`--generate-link-to-definition` option can only be used with HTML output format", + ) + .with_note("`--generate-link-to-definition` option will be ignored") + .emit(); } let scrape_examples_options = ScrapeExamplesOptions::new(matches, dcx); @@ -816,6 +822,7 @@ impl Options { call_locations, no_emit_shared: false, html_no_source, + output_to_stdout, }; Some((options, render_options)) } diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 08d6a5a52b2..743c1ed507e 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -1,5 +1,6 @@ mod make; mod markdown; +mod runner; mod rust; use std::fs::File; @@ -10,7 +11,7 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::{Arc, Mutex}; use std::{panic, str}; -pub(crate) use make::make_test; +pub(crate) use make::DocTestBuilder; pub(crate) use markdown::test as test_markdown; use rustc_ast as ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -150,8 +151,6 @@ pub(crate) fn run(dcx: DiagCtxtHandle<'_>, options: RustdocOptions) -> Result<() expanded_args: options.expanded_args.clone(), }; - let test_args = options.test_args.clone(); - let nocapture = options.nocapture; let externs = options.externs.clone(); let json_unused_externs = options.json_unused_externs; @@ -164,39 +163,46 @@ pub(crate) fn run(dcx: DiagCtxtHandle<'_>, options: RustdocOptions) -> Result<() let args_path = temp_dir.path().join("rustdoc-cfgs"); crate::wrap_return(dcx, generate_args_file(&args_path, &options))?; - let (tests, unused_extern_reports, compiling_test_count) = - interface::run_compiler(config, |compiler| { - compiler.enter(|queries| { - let collector = queries.global_ctxt()?.enter(|tcx| { - let crate_name = tcx.crate_name(LOCAL_CRATE).to_string(); - let crate_attrs = tcx.hir().attrs(CRATE_HIR_ID); - let opts = scrape_test_config(crate_name, crate_attrs, args_path); - let enable_per_target_ignores = options.enable_per_target_ignores; + let CreateRunnableDocTests { + standalone_tests, + mergeable_tests, + rustdoc_options, + opts, + unused_extern_reports, + compiling_test_count, + .. + } = interface::run_compiler(config, |compiler| { + compiler.enter(|queries| { + let collector = queries.global_ctxt()?.enter(|tcx| { + let crate_name = tcx.crate_name(LOCAL_CRATE).to_string(); + let crate_attrs = tcx.hir().attrs(CRATE_HIR_ID); + let opts = scrape_test_config(crate_name, crate_attrs, args_path); + let enable_per_target_ignores = options.enable_per_target_ignores; - let mut collector = CreateRunnableDoctests::new(options, opts); - let hir_collector = HirCollector::new( - &compiler.sess, - tcx.hir(), - ErrorCodes::from(compiler.sess.opts.unstable_features.is_nightly_build()), - enable_per_target_ignores, - tcx, - ); - let tests = hir_collector.collect_crate(); - tests.into_iter().for_each(|t| collector.add_test(t)); + let mut collector = CreateRunnableDocTests::new(options, opts); + let hir_collector = HirCollector::new( + &compiler.sess, + tcx.hir(), + ErrorCodes::from(compiler.sess.opts.unstable_features.is_nightly_build()), + enable_per_target_ignores, + tcx, + ); + let tests = hir_collector.collect_crate(); + tests.into_iter().for_each(|t| collector.add_test(t)); - collector - }); - if compiler.sess.dcx().has_errors().is_some() { - FatalError.raise(); - } + collector + }); + if compiler.sess.dcx().has_errors().is_some() { + FatalError.raise(); + } - let unused_extern_reports = collector.unused_extern_reports.clone(); - let compiling_test_count = collector.compiling_test_count.load(Ordering::SeqCst); - Ok((collector.tests, unused_extern_reports, compiling_test_count)) - }) - })?; + Ok(collector) + }) + })?; - run_tests(test_args, nocapture, tests); + run_tests(opts, &rustdoc_options, &unused_extern_reports, standalone_tests, mergeable_tests); + + let compiling_test_count = compiling_test_count.load(Ordering::SeqCst); // Collect and warn about unused externs, but only if we've gotten // reports for each doctest @@ -240,16 +246,83 @@ pub(crate) fn run(dcx: DiagCtxtHandle<'_>, options: RustdocOptions) -> Result<() } pub(crate) fn run_tests( - mut test_args: Vec, - nocapture: bool, - mut tests: Vec, + opts: GlobalTestOptions, + rustdoc_options: &Arc, + unused_extern_reports: &Arc>>, + mut standalone_tests: Vec, + mergeable_tests: FxHashMap>, ) { + let mut test_args = Vec::with_capacity(rustdoc_options.test_args.len() + 1); test_args.insert(0, "rustdoctest".to_string()); - if nocapture { + test_args.extend_from_slice(&rustdoc_options.test_args); + if rustdoc_options.nocapture { test_args.push("--nocapture".to_string()); } - tests.sort_by(|a, b| a.desc.name.as_slice().cmp(&b.desc.name.as_slice())); - test::test_main(&test_args, tests, None); + + let mut nb_errors = 0; + let mut ran_edition_tests = 0; + let target_str = rustdoc_options.target.to_string(); + + for (edition, mut doctests) in mergeable_tests { + if doctests.is_empty() { + continue; + } + doctests.sort_by(|(_, a), (_, b)| a.name.cmp(&b.name)); + + let mut tests_runner = runner::DocTestRunner::new(); + + let rustdoc_test_options = IndividualTestOptions::new( + &rustdoc_options, + &Some(format!("merged_doctest_{edition}")), + PathBuf::from(format!("doctest_{edition}.rs")), + ); + + for (doctest, scraped_test) in &doctests { + tests_runner.add_test(doctest, scraped_test, &target_str); + } + if let Ok(success) = tests_runner.run_merged_tests( + rustdoc_test_options, + edition, + &opts, + &test_args, + rustdoc_options, + ) { + ran_edition_tests += 1; + if !success { + nb_errors += 1; + } + continue; + } + // We failed to compile all compatible tests as one so we push them into the + // `standalone_tests` doctests. + debug!("Failed to compile compatible doctests for edition {} all at once", edition); + for (doctest, scraped_test) in doctests { + doctest.generate_unique_doctest( + &scraped_test.text, + scraped_test.langstr.test_harness, + &opts, + Some(&opts.crate_name), + ); + standalone_tests.push(generate_test_desc_and_fn( + doctest, + scraped_test, + opts.clone(), + Arc::clone(&rustdoc_options), + unused_extern_reports.clone(), + )); + } + } + + // We need to call `test_main` even if there is no doctest to run to get the output + // `running 0 tests...`. + if ran_edition_tests == 0 || !standalone_tests.is_empty() { + standalone_tests.sort_by(|a, b| a.desc.name.as_slice().cmp(&b.desc.name.as_slice())); + test::test_main(&test_args, standalone_tests, None); + } + if nb_errors != 0 { + // libtest::ERROR_EXIT_CODE is not public but it's the same value. + std::process::exit(101); + } } // Look for `#![doc(test(no_crate_inject))]`, used by crates in the std facade. @@ -330,7 +403,7 @@ impl DirState { // We could unify this struct the one in rustc but they have different // ownership semantics, so doing so would create wasteful allocations. #[derive(serde::Serialize, serde::Deserialize)] -struct UnusedExterns { +pub(crate) struct UnusedExterns { /// Lint level of the unused_crate_dependencies lint lint_level: String, /// List of unused externs by their names. @@ -359,22 +432,41 @@ fn wrapped_rustc_command(rustc_wrappers: &[PathBuf], rustc_binary: &Path) -> Com command } -struct RunnableDoctest { +/// Information needed for running a bundle of doctests. +/// +/// This data structure contains the "full" test code, including the wrappers +/// (if multiple doctests are merged), `main` function, +/// and everything needed to calculate the compiler's command-line arguments. +/// The `# ` prefix on boring lines has also been stripped. +pub(crate) struct RunnableDocTest { full_test_code: String, full_test_line_offset: usize, test_opts: IndividualTestOptions, global_opts: GlobalTestOptions, - scraped_test: ScrapedDoctest, + langstr: LangString, + line: usize, + edition: Edition, + no_run: bool, + is_multiple_tests: bool, } +impl RunnableDocTest { + fn path_for_merged_doctest(&self) -> PathBuf { + self.test_opts.outdir.path().join(&format!("doctest_{}.rs", self.edition)) + } +} + +/// Execute a `RunnableDoctest`. +/// +/// This is the function that calculates the compiler command line, invokes the compiler, then +/// invokes the test or tests in a separate executable (if applicable). fn run_test( - doctest: RunnableDoctest, + doctest: RunnableDocTest, rustdoc_options: &RustdocOptions, supports_color: bool, report_unused_externs: impl Fn(UnusedExterns), ) -> Result<(), TestFailure> { - let scraped_test = &doctest.scraped_test; - let langstr = &scraped_test.langstr; + let langstr = &doctest.langstr; // Make sure we emit well-formed executable names for our target. let rust_out = add_exe_suffix("rust_out".to_owned(), &rustdoc_options.target); let output_file = doctest.test_opts.outdir.path().join(rust_out); @@ -391,12 +483,15 @@ fn run_test( compiler.arg(format!("--sysroot={}", sysroot.display())); } - compiler.arg("--edition").arg(&scraped_test.edition(rustdoc_options).to_string()); - compiler.env("UNSTABLE_RUSTDOC_TEST_PATH", &doctest.test_opts.path); - compiler.env( - "UNSTABLE_RUSTDOC_TEST_LINE", - format!("{}", scraped_test.line as isize - doctest.full_test_line_offset as isize), - ); + compiler.arg("--edition").arg(&doctest.edition.to_string()); + if !doctest.is_multiple_tests { + // Setting these environment variables is unneeded if this is a merged doctest. + compiler.env("UNSTABLE_RUSTDOC_TEST_PATH", &doctest.test_opts.path); + compiler.env( + "UNSTABLE_RUSTDOC_TEST_LINE", + format!("{}", doctest.line as isize - doctest.full_test_line_offset as isize), + ); + } compiler.arg("-o").arg(&output_file); if langstr.test_harness { compiler.arg("--test"); @@ -408,10 +503,7 @@ fn run_test( compiler.arg("-Z").arg("unstable-options"); } - if scraped_test.no_run(rustdoc_options) - && !langstr.compile_fail - && rustdoc_options.persist_doctests.is_none() - { + if doctest.no_run && !langstr.compile_fail && rustdoc_options.persist_doctests.is_none() { // FIXME: why does this code check if it *shouldn't* persist doctests // -- shouldn't it be the negation? compiler.arg("--emit=metadata"); @@ -442,18 +534,40 @@ fn run_test( } } - compiler.arg("-"); - compiler.stdin(Stdio::piped()); - compiler.stderr(Stdio::piped()); + // If this is a merged doctest, we need to write it into a file instead of using stdin + // because if the size of the merged doctests is too big, it'll simply break stdin. + if doctest.is_multiple_tests { + // It makes the compilation failure much faster if it is for a combined doctest. + compiler.arg("--error-format=short"); + let input_file = doctest.path_for_merged_doctest(); + if std::fs::write(&input_file, &doctest.full_test_code).is_err() { + // If we cannot write this file for any reason, we leave. All combined tests will be + // tested as standalone tests. + return Err(TestFailure::CompileError); + } + compiler.arg(input_file); + if !rustdoc_options.nocapture { + // If `nocapture` is disabled, then we don't display rustc's output when compiling + // the merged doctests. + compiler.stderr(Stdio::null()); + } + } else { + compiler.arg("-"); + compiler.stdin(Stdio::piped()); + compiler.stderr(Stdio::piped()); + } debug!("compiler invocation for doctest: {compiler:?}"); let mut child = compiler.spawn().expect("Failed to spawn rustc process"); - { + let output = if doctest.is_multiple_tests { + let status = child.wait().expect("Failed to wait"); + process::Output { status, stdout: Vec::new(), stderr: Vec::new() } + } else { let stdin = child.stdin.as_mut().expect("Failed to open stdin"); stdin.write_all(doctest.full_test_code.as_bytes()).expect("could write out test sources"); - } - let output = child.wait_with_output().expect("Failed to read stdout"); + child.wait_with_output().expect("Failed to read stdout") + }; struct Bomb<'a>(&'a str); impl Drop for Bomb<'_> { @@ -492,8 +606,7 @@ fn run_test( // We used to check if the output contained "error[{}]: " but since we added the // colored output, we can't anymore because of the color escape characters before // the ":". - let missing_codes: Vec = scraped_test - .langstr + let missing_codes: Vec = langstr .error_codes .iter() .filter(|err| !out.contains(&format!("error[{err}]"))) @@ -510,7 +623,7 @@ fn run_test( } } - if scraped_test.no_run(rustdoc_options) { + if doctest.no_run { return Ok(()); } @@ -522,15 +635,19 @@ fn run_test( let tool = make_maybe_absolute_path(tool.into()); cmd = Command::new(tool); cmd.args(&rustdoc_options.runtool_args); - cmd.arg(output_file); + cmd.arg(&output_file); } else { - cmd = Command::new(output_file); + cmd = Command::new(&output_file); + if doctest.is_multiple_tests { + cmd.arg("*doctest-bin-path"); + cmd.arg(&output_file); + } } if let Some(run_directory) = &rustdoc_options.test_run_directory { cmd.current_dir(run_directory); } - let result = if rustdoc_options.nocapture { + let result = if doctest.is_multiple_tests || rustdoc_options.nocapture { cmd.status().map(|status| process::Output { status, stdout: Vec::new(), @@ -568,15 +685,14 @@ fn make_maybe_absolute_path(path: PathBuf) -> PathBuf { } struct IndividualTestOptions { outdir: DirState, - test_id: String, path: PathBuf, } impl IndividualTestOptions { - fn new(options: &RustdocOptions, test_id: String, test_path: PathBuf) -> Self { + fn new(options: &RustdocOptions, test_id: &Option, test_path: PathBuf) -> Self { let outdir = if let Some(ref path) = options.persist_doctests { let mut path = path.clone(); - path.push(&test_id); + path.push(&test_id.as_deref().unwrap_or_else(|| "")); if let Err(err) = std::fs::create_dir_all(&path) { eprintln!("Couldn't create directory for doctest executables: {err}"); @@ -588,20 +704,45 @@ impl IndividualTestOptions { DirState::Temp(get_doctest_dir().expect("rustdoc needs a tempdir")) }; - Self { outdir, test_id, path: test_path } + Self { outdir, path: test_path } } } /// A doctest scraped from the code, ready to be turned into a runnable test. -struct ScrapedDoctest { +/// +/// The pipeline goes: [`clean`] AST -> `ScrapedDoctest` -> `RunnableDoctest`. +/// [`run_merged_tests`] converts a bunch of scraped doctests to a single runnable doctest, +/// while [`generate_unique_doctest`] does the standalones. +/// +/// [`clean`]: crate::clean +/// [`run_merged_tests`]: crate::doctest::runner::DocTestRunner::run_merged_tests +/// [`generate_unique_doctest`]: crate::doctest::make::DocTestBuilder::generate_unique_doctest +pub(crate) struct ScrapedDocTest { filename: FileName, line: usize, - logical_path: Vec, langstr: LangString, text: String, + name: String, } -impl ScrapedDoctest { +impl ScrapedDocTest { + fn new( + filename: FileName, + line: usize, + logical_path: Vec, + langstr: LangString, + text: String, + ) -> Self { + let mut item_path = logical_path.join("::"); + item_path.retain(|c| c != ' '); + if !item_path.is_empty() { + item_path.push(' '); + } + let name = + format!("{} - {item_path}(line {line})", filename.prefer_remapped_unconditionaly()); + + Self { filename, line, langstr, text, name } + } fn edition(&self, opts: &RustdocOptions) -> Edition { self.langstr.edition.unwrap_or(opts.edition) } @@ -609,54 +750,8 @@ impl ScrapedDoctest { fn no_run(&self, opts: &RustdocOptions) -> bool { self.langstr.no_run || opts.no_run } -} - -pub(crate) trait DoctestVisitor { - fn visit_test(&mut self, test: String, config: LangString, rel_line: MdRelLine); - fn visit_header(&mut self, _name: &str, _level: u32) {} -} - -struct CreateRunnableDoctests { - tests: Vec, - - rustdoc_options: Arc, - opts: GlobalTestOptions, - visited_tests: FxHashMap<(String, usize), usize>, - unused_extern_reports: Arc>>, - compiling_test_count: AtomicUsize, -} - -impl CreateRunnableDoctests { - fn new(rustdoc_options: RustdocOptions, opts: GlobalTestOptions) -> CreateRunnableDoctests { - CreateRunnableDoctests { - tests: Vec::new(), - rustdoc_options: Arc::new(rustdoc_options), - opts, - visited_tests: FxHashMap::default(), - unused_extern_reports: Default::default(), - compiling_test_count: AtomicUsize::new(0), - } - } - - fn generate_name(&self, filename: &FileName, line: usize, logical_path: &[String]) -> String { - let mut item_path = logical_path.join("::"); - item_path.retain(|c| c != ' '); - if !item_path.is_empty() { - item_path.push(' '); - } - format!("{} - {item_path}(line {line})", filename.prefer_remapped_unconditionaly()) - } - - fn add_test(&mut self, test: ScrapedDoctest) { - let name = self.generate_name(&test.filename, test.line, &test.logical_path); - let opts = self.opts.clone(); - let target_str = self.rustdoc_options.target.to_string(); - let unused_externs = self.unused_extern_reports.clone(); - if !test.langstr.compile_fail { - self.compiling_test_count.fetch_add(1, Ordering::SeqCst); - } - - let path = match &test.filename { + fn path(&self) -> PathBuf { + match &self.filename { FileName::Real(path) => { if let Some(local_path) = path.local_path() { local_path.to_path_buf() @@ -666,10 +761,45 @@ impl CreateRunnableDoctests { } } _ => PathBuf::from(r"doctest.rs"), - }; + } + } +} +pub(crate) trait DocTestVisitor { + fn visit_test(&mut self, test: String, config: LangString, rel_line: MdRelLine); + fn visit_header(&mut self, _name: &str, _level: u32) {} +} + +struct CreateRunnableDocTests { + standalone_tests: Vec, + mergeable_tests: FxHashMap>, + + rustdoc_options: Arc, + opts: GlobalTestOptions, + visited_tests: FxHashMap<(String, usize), usize>, + unused_extern_reports: Arc>>, + compiling_test_count: AtomicUsize, + can_merge_doctests: bool, +} + +impl CreateRunnableDocTests { + fn new(rustdoc_options: RustdocOptions, opts: GlobalTestOptions) -> CreateRunnableDocTests { + let can_merge_doctests = rustdoc_options.edition >= Edition::Edition2024; + CreateRunnableDocTests { + standalone_tests: Vec::new(), + mergeable_tests: FxHashMap::default(), + rustdoc_options: Arc::new(rustdoc_options), + opts, + visited_tests: FxHashMap::default(), + unused_extern_reports: Default::default(), + compiling_test_count: AtomicUsize::new(0), + can_merge_doctests, + } + } + + fn add_test(&mut self, scraped_test: ScrapedDocTest) { // For example `module/file.rs` would become `module_file_rs` - let file = test + let file = scraped_test .filename .prefer_local() .to_string_lossy() @@ -679,75 +809,134 @@ impl CreateRunnableDoctests { let test_id = format!( "{file}_{line}_{number}", file = file, - line = test.line, + line = scraped_test.line, number = { // Increases the current test number, if this file already // exists or it creates a new entry with a test number of 0. self.visited_tests - .entry((file.clone(), test.line)) + .entry((file.clone(), scraped_test.line)) .and_modify(|v| *v += 1) .or_insert(0) }, ); - let rustdoc_options = self.rustdoc_options.clone(); - let rustdoc_test_options = IndividualTestOptions::new(&self.rustdoc_options, test_id, path); + let edition = scraped_test.edition(&self.rustdoc_options); + let doctest = DocTestBuilder::new( + &scraped_test.text, + Some(&self.opts.crate_name), + edition, + self.can_merge_doctests, + Some(test_id), + Some(&scraped_test.langstr), + ); + let is_standalone = !doctest.can_be_merged + || scraped_test.langstr.compile_fail + || scraped_test.langstr.test_harness + || scraped_test.langstr.standalone + || self.rustdoc_options.nocapture + || self.rustdoc_options.test_args.iter().any(|arg| arg == "--show-output"); + if is_standalone { + let test_desc = self.generate_test_desc_and_fn(doctest, scraped_test); + self.standalone_tests.push(test_desc); + } else { + self.mergeable_tests.entry(edition).or_default().push((doctest, scraped_test)); + } + } - debug!("creating test {name}: {}", test.text); - self.tests.push(test::TestDescAndFn { - desc: test::TestDesc { - name: test::DynTestName(name), - ignore: match test.langstr.ignore { - Ignore::All => true, - Ignore::None => false, - Ignore::Some(ref ignores) => ignores.iter().any(|s| target_str.contains(s)), - }, - ignore_message: None, - source_file: "", - start_line: 0, - start_col: 0, - end_line: 0, - end_col: 0, - // compiler failures are test failures - should_panic: test::ShouldPanic::No, - compile_fail: test.langstr.compile_fail, - no_run: test.no_run(&rustdoc_options), - test_type: test::TestType::DocTest, + fn generate_test_desc_and_fn( + &mut self, + test: DocTestBuilder, + scraped_test: ScrapedDocTest, + ) -> test::TestDescAndFn { + if !scraped_test.langstr.compile_fail { + self.compiling_test_count.fetch_add(1, Ordering::SeqCst); + } + + generate_test_desc_and_fn( + test, + scraped_test, + self.opts.clone(), + Arc::clone(&self.rustdoc_options), + self.unused_extern_reports.clone(), + ) + } +} + +fn generate_test_desc_and_fn( + test: DocTestBuilder, + scraped_test: ScrapedDocTest, + opts: GlobalTestOptions, + rustdoc_options: Arc, + unused_externs: Arc>>, +) -> test::TestDescAndFn { + let target_str = rustdoc_options.target.to_string(); + let rustdoc_test_options = + IndividualTestOptions::new(&rustdoc_options, &test.test_id, scraped_test.path()); + + debug!("creating test {}: {}", scraped_test.name, scraped_test.text); + test::TestDescAndFn { + desc: test::TestDesc { + name: test::DynTestName(scraped_test.name.clone()), + ignore: match scraped_test.langstr.ignore { + Ignore::All => true, + Ignore::None => false, + Ignore::Some(ref ignores) => ignores.iter().any(|s| target_str.contains(s)), }, - testfn: test::DynTestFn(Box::new(move || { - doctest_run_fn(rustdoc_test_options, opts, test, rustdoc_options, unused_externs) - })), - }); + ignore_message: None, + source_file: "", + start_line: 0, + start_col: 0, + end_line: 0, + end_col: 0, + // compiler failures are test failures + should_panic: test::ShouldPanic::No, + compile_fail: scraped_test.langstr.compile_fail, + no_run: scraped_test.no_run(&rustdoc_options), + test_type: test::TestType::DocTest, + }, + testfn: test::DynTestFn(Box::new(move || { + doctest_run_fn( + rustdoc_test_options, + opts, + test, + scraped_test, + rustdoc_options, + unused_externs, + ) + })), } } fn doctest_run_fn( test_opts: IndividualTestOptions, global_opts: GlobalTestOptions, - scraped_test: ScrapedDoctest, + doctest: DocTestBuilder, + scraped_test: ScrapedDocTest, rustdoc_options: Arc, unused_externs: Arc>>, ) -> Result<(), String> { let report_unused_externs = |uext| { unused_externs.lock().unwrap().push(uext); }; - let edition = scraped_test.edition(&rustdoc_options); - let (full_test_code, full_test_line_offset, supports_color) = make_test( + let (full_test_code, full_test_line_offset) = doctest.generate_unique_doctest( &scraped_test.text, - Some(&global_opts.crate_name), scraped_test.langstr.test_harness, &global_opts, - edition, - Some(&test_opts.test_id), + Some(&global_opts.crate_name), ); - let runnable_test = RunnableDoctest { + let runnable_test = RunnableDocTest { full_test_code, full_test_line_offset, test_opts, global_opts, - scraped_test, + langstr: scraped_test.langstr.clone(), + line: scraped_test.line, + edition: scraped_test.edition(&rustdoc_options), + no_run: scraped_test.no_run(&rustdoc_options), + is_multiple_tests: false, }; - let res = run_test(runnable_test, &rustdoc_options, supports_color, report_unused_externs); + let res = + run_test(runnable_test, &rustdoc_options, doctest.supports_color, report_unused_externs); if let Err(err) = res { match err { @@ -804,7 +993,7 @@ fn doctest_run_fn( } #[cfg(test)] // used in tests -impl DoctestVisitor for Vec { +impl DocTestVisitor for Vec { fn visit_test(&mut self, _test: String, _config: LangString, rel_line: MdRelLine) { self.push(1 + rel_line.offset()); } diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs index 74833c11362..aed079e5887 100644 --- a/src/librustdoc/doctest/make.rs +++ b/src/librustdoc/doctest/make.rs @@ -16,250 +16,428 @@ use rustc_span::symbol::sym; use rustc_span::FileName; use super::GlobalTestOptions; +use crate::html::markdown::LangString; -/// Transforms a test into code that can be compiled into a Rust binary, and returns the number of -/// lines before the test code begins as well as if the output stream supports colors or not. -pub(crate) fn make_test( - s: &str, - crate_name: Option<&str>, - dont_insert_main: bool, - opts: &GlobalTestOptions, - edition: Edition, - test_id: Option<&str>, -) -> (String, usize, bool) { - let (crate_attrs, everything_else, crates) = partition_source(s, edition); - let everything_else = everything_else.trim(); - let mut line_offset = 0; - let mut prog = String::new(); - let mut supports_color = false; +/// This struct contains information about the doctest itself which is then used to generate +/// doctest source code appropriately. +pub(crate) struct DocTestBuilder { + pub(crate) supports_color: bool, + pub(crate) already_has_extern_crate: bool, + pub(crate) has_main_fn: bool, + pub(crate) crate_attrs: String, + /// If this is a merged doctest, it will be put into `everything_else`, otherwise it will + /// put into `crate_attrs`. + pub(crate) maybe_crate_attrs: String, + pub(crate) crates: String, + pub(crate) everything_else: String, + pub(crate) test_id: Option, + pub(crate) failed_ast: bool, + pub(crate) can_be_merged: bool, +} - if opts.attrs.is_empty() { - // If there aren't any attributes supplied by #![doc(test(attr(...)))], then allow some - // lints that are commonly triggered in doctests. The crate-level test attributes are - // commonly used to make tests fail in case they trigger warnings, so having this there in - // that case may cause some tests to pass when they shouldn't have. - prog.push_str("#![allow(unused)]\n"); - line_offset += 1; +impl DocTestBuilder { + pub(crate) fn new( + source: &str, + crate_name: Option<&str>, + edition: Edition, + can_merge_doctests: bool, + // If `test_id` is `None`, it means we're generating code for a code example "run" link. + test_id: Option, + lang_str: Option<&LangString>, + ) -> Self { + let can_merge_doctests = can_merge_doctests + && lang_str.is_some_and(|lang_str| { + !lang_str.compile_fail && !lang_str.test_harness && !lang_str.standalone + }); + + let SourceInfo { crate_attrs, maybe_crate_attrs, crates, everything_else } = + partition_source(source, edition); + + // Uses librustc_ast to parse the doctest and find if there's a main fn and the extern + // crate already is included. + let Ok(( + ParseSourceInfo { + has_main_fn, + found_extern_crate, + supports_color, + has_global_allocator, + has_macro_def, + .. + }, + failed_ast, + )) = check_for_main_and_extern_crate( + crate_name, + source, + &everything_else, + &crates, + edition, + can_merge_doctests, + ) + else { + // If the parser panicked due to a fatal error, pass the test code through unchanged. + // The error will be reported during compilation. + return Self { + supports_color: false, + has_main_fn: false, + crate_attrs, + maybe_crate_attrs, + crates, + everything_else, + already_has_extern_crate: false, + test_id, + failed_ast: true, + can_be_merged: false, + }; + }; + // If the AST returned an error, we don't want this doctest to be merged with the + // others. Same if it contains `#[feature]` or `#[no_std]`. + let can_be_merged = can_merge_doctests + && !failed_ast + && !has_global_allocator + && crate_attrs.is_empty() + // If this is a merged doctest and a defined macro uses `$crate`, then the path will + // not work, so better not put it into merged doctests. + && !(has_macro_def && everything_else.contains("$crate")); + Self { + supports_color, + has_main_fn, + crate_attrs, + maybe_crate_attrs, + crates, + everything_else, + already_has_extern_crate: found_extern_crate, + test_id, + failed_ast: false, + can_be_merged, + } } - // Next, any attributes that came from the crate root via #![doc(test(attr(...)))]. - for attr in &opts.attrs { - prog.push_str(&format!("#![{attr}]\n")); - line_offset += 1; - } + /// Transforms a test into code that can be compiled into a Rust binary, and returns the number of + /// lines before the test code begins. + pub(crate) fn generate_unique_doctest( + &self, + test_code: &str, + dont_insert_main: bool, + opts: &GlobalTestOptions, + crate_name: Option<&str>, + ) -> (String, usize) { + if self.failed_ast { + // If the AST failed to compile, no need to go generate a complete doctest, the error + // will be better this way. + return (test_code.to_string(), 0); + } + let mut line_offset = 0; + let mut prog = String::new(); + let everything_else = self.everything_else.trim(); + if opts.attrs.is_empty() { + // If there aren't any attributes supplied by #![doc(test(attr(...)))], then allow some + // lints that are commonly triggered in doctests. The crate-level test attributes are + // commonly used to make tests fail in case they trigger warnings, so having this there in + // that case may cause some tests to pass when they shouldn't have. + prog.push_str("#![allow(unused)]\n"); + line_offset += 1; + } - // Now push any outer attributes from the example, assuming they - // are intended to be crate attributes. - prog.push_str(&crate_attrs); - prog.push_str(&crates); + // Next, any attributes that came from the crate root via #![doc(test(attr(...)))]. + for attr in &opts.attrs { + prog.push_str(&format!("#![{attr}]\n")); + line_offset += 1; + } - // Uses librustc_ast to parse the doctest and find if there's a main fn and the extern - // crate already is included. - let Ok((already_has_main, already_has_extern_crate)) = - check_for_main_and_extern_crate(crate_name, s.to_owned(), edition, &mut supports_color) - else { - // If the parser panicked due to a fatal error, pass the test code through unchanged. - // The error will be reported during compilation. - return (s.to_owned(), 0, false); - }; + // Now push any outer attributes from the example, assuming they + // are intended to be crate attributes. + prog.push_str(&self.crate_attrs); + prog.push_str(&self.maybe_crate_attrs); + prog.push_str(&self.crates); - // Don't inject `extern crate std` because it's already injected by the - // compiler. - if !already_has_extern_crate && !opts.no_crate_inject && crate_name != Some("std") { - if let Some(crate_name) = crate_name { + // Don't inject `extern crate std` because it's already injected by the + // compiler. + if !self.already_has_extern_crate && + !opts.no_crate_inject && + let Some(crate_name) = crate_name && + crate_name != "std" && // Don't inject `extern crate` if the crate is never used. // NOTE: this is terribly inaccurate because it doesn't actually // parse the source, but only has false positives, not false // negatives. - if s.contains(crate_name) { - // rustdoc implicitly inserts an `extern crate` item for the own crate - // which may be unused, so we need to allow the lint. - prog.push_str("#[allow(unused_extern_crates)]\n"); + test_code.contains(crate_name) + { + // rustdoc implicitly inserts an `extern crate` item for the own crate + // which may be unused, so we need to allow the lint. + prog.push_str("#[allow(unused_extern_crates)]\n"); - prog.push_str(&format!("extern crate r#{crate_name};\n")); - line_offset += 1; + prog.push_str(&format!("extern crate r#{crate_name};\n")); + line_offset += 1; + } + + // FIXME: This code cannot yet handle no_std test cases yet + if dont_insert_main || self.has_main_fn || prog.contains("![no_std]") { + prog.push_str(everything_else); + } else { + let returns_result = everything_else.ends_with("(())"); + // Give each doctest main function a unique name. + // This is for example needed for the tooling around `-C instrument-coverage`. + let inner_fn_name = if let Some(ref test_id) = self.test_id { + format!("_doctest_main_{test_id}") + } else { + "_inner".into() + }; + let inner_attr = if self.test_id.is_some() { "#[allow(non_snake_case)] " } else { "" }; + let (main_pre, main_post) = if returns_result { + ( + format!( + "fn main() {{ {inner_attr}fn {inner_fn_name}() -> Result<(), impl core::fmt::Debug> {{\n", + ), + format!("\n}} {inner_fn_name}().unwrap() }}"), + ) + } else if self.test_id.is_some() { + ( + format!("fn main() {{ {inner_attr}fn {inner_fn_name}() {{\n",), + format!("\n}} {inner_fn_name}() }}"), + ) + } else { + ("fn main() {\n".into(), "\n}".into()) + }; + // Note on newlines: We insert a line/newline *before*, and *after* + // the doctest and adjust the `line_offset` accordingly. + // In the case of `-C instrument-coverage`, this means that the generated + // inner `main` function spans from the doctest opening codeblock to the + // closing one. For example + // /// ``` <- start of the inner main + // /// <- code under doctest + // /// ``` <- end of the inner main + line_offset += 1; + + prog.push_str(&main_pre); + + // add extra 4 spaces for each line to offset the code block + if opts.insert_indent_space { + prog.push_str( + &everything_else + .lines() + .map(|line| format!(" {}", line)) + .collect::>() + .join("\n"), + ); + } else { + prog.push_str(everything_else); + }; + prog.push_str(&main_post); + } + + debug!("final doctest:\n{prog}"); + + (prog, line_offset) + } +} + +#[derive(PartialEq, Eq, Debug)] +enum ParsingResult { + Failed, + AstError, + Ok, +} + +fn cancel_error_count(psess: &ParseSess) { + // Reset errors so that they won't be reported as compiler bugs when dropping the + // dcx. Any errors in the tests will be reported when the test file is compiled, + // Note that we still need to cancel the errors above otherwise `Diag` will panic on + // drop. + psess.dcx().reset_err_count(); +} + +fn parse_source( + source: String, + info: &mut ParseSourceInfo, + crate_name: &Option<&str>, +) -> ParsingResult { + use rustc_errors::emitter::{Emitter, HumanEmitter}; + use rustc_errors::DiagCtxt; + use rustc_parse::parser::ForceCollect; + use rustc_span::source_map::FilePathMapping; + + let filename = FileName::anon_source_code(&source); + + // Any errors in parsing should also appear when the doctest is compiled for real, so just + // send all the errors that librustc_ast emits directly into a `Sink` instead of stderr. + let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); + let fallback_bundle = rustc_errors::fallback_fluent_bundle( + rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), + false, + ); + info.supports_color = + HumanEmitter::new(stderr_destination(ColorConfig::Auto), fallback_bundle.clone()) + .supports_color(); + + let emitter = HumanEmitter::new(Box::new(io::sink()), fallback_bundle); + + // FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser + let dcx = DiagCtxt::new(Box::new(emitter)).disable_warnings(); + let psess = ParseSess::with_dcx(dcx, sm); + + let mut parser = match new_parser_from_source_str(&psess, filename, source) { + Ok(p) => p, + Err(errs) => { + errs.into_iter().for_each(|err| err.cancel()); + cancel_error_count(&psess); + return ParsingResult::Failed; + } + }; + let mut parsing_result = ParsingResult::Ok; + + // Recurse through functions body. It is necessary because the doctest source code is + // wrapped in a function to limit the number of AST errors. If we don't recurse into + // functions, we would thing all top-level items (so basically nothing). + fn check_item(item: &ast::Item, info: &mut ParseSourceInfo, crate_name: &Option<&str>) { + if !info.has_global_allocator + && item.attrs.iter().any(|attr| attr.name_or_empty() == sym::global_allocator) + { + info.has_global_allocator = true; + } + match item.kind { + ast::ItemKind::Fn(ref fn_item) if !info.has_main_fn => { + if item.ident.name == sym::main { + info.has_main_fn = true; + } + if let Some(ref body) = fn_item.body { + for stmt in &body.stmts { + match stmt.kind { + ast::StmtKind::Item(ref item) => check_item(item, info, crate_name), + ast::StmtKind::MacCall(..) => info.found_macro = true, + _ => {} + } + } + } } + ast::ItemKind::ExternCrate(original) => { + if !info.found_extern_crate + && let Some(ref crate_name) = crate_name + { + info.found_extern_crate = match original { + Some(name) => name.as_str() == *crate_name, + None => item.ident.as_str() == *crate_name, + }; + } + } + ast::ItemKind::MacCall(..) => info.found_macro = true, + ast::ItemKind::MacroDef(..) => info.has_macro_def = true, + _ => {} } } - // FIXME: This code cannot yet handle no_std test cases yet - if dont_insert_main || already_has_main || prog.contains("![no_std]") { - prog.push_str(everything_else); - } else { - let returns_result = everything_else.trim_end().ends_with("(())"); - // Give each doctest main function a unique name. - // This is for example needed for the tooling around `-C instrument-coverage`. - let inner_fn_name = if let Some(test_id) = test_id { - format!("_doctest_main_{test_id}") - } else { - "_inner".into() - }; - let inner_attr = if test_id.is_some() { "#[allow(non_snake_case)] " } else { "" }; - let (main_pre, main_post) = if returns_result { - ( - format!( - "fn main() {{ {inner_attr}fn {inner_fn_name}() -> Result<(), impl core::fmt::Debug> {{\n", - ), - format!("\n}} {inner_fn_name}().unwrap() }}"), - ) - } else if test_id.is_some() { - ( - format!("fn main() {{ {inner_attr}fn {inner_fn_name}() {{\n",), - format!("\n}} {inner_fn_name}() }}"), - ) - } else { - ("fn main() {\n".into(), "\n}".into()) - }; - // Note on newlines: We insert a line/newline *before*, and *after* - // the doctest and adjust the `line_offset` accordingly. - // In the case of `-C instrument-coverage`, this means that the generated - // inner `main` function spans from the doctest opening codeblock to the - // closing one. For example - // /// ``` <- start of the inner main - // /// <- code under doctest - // /// ``` <- end of the inner main - line_offset += 1; + loop { + match parser.parse_item(ForceCollect::No) { + Ok(Some(item)) => { + check_item(&item, info, crate_name); - // add extra 4 spaces for each line to offset the code block - let content = if opts.insert_indent_space { - everything_else - .lines() - .map(|line| format!(" {}", line)) - .collect::>() - .join("\n") - } else { - everything_else.to_string() - }; - prog.extend([&main_pre, content.as_str(), &main_post].iter().cloned()); + if info.has_main_fn && info.found_extern_crate { + break; + } + } + Ok(None) => break, + Err(e) => { + parsing_result = ParsingResult::AstError; + e.cancel(); + break; + } + } + + // The supplied item is only used for diagnostics, + // which are swallowed here anyway. + parser.maybe_consume_incorrect_semicolon(None); } - debug!("final doctest:\n{prog}"); + cancel_error_count(&psess); + parsing_result +} - (prog, line_offset, supports_color) +#[derive(Default)] +struct ParseSourceInfo { + has_main_fn: bool, + found_extern_crate: bool, + found_macro: bool, + supports_color: bool, + has_global_allocator: bool, + has_macro_def: bool, } fn check_for_main_and_extern_crate( crate_name: Option<&str>, - source: String, + original_source_code: &str, + everything_else: &str, + crates: &str, edition: Edition, - supports_color: &mut bool, -) -> Result<(bool, bool), FatalError> { + can_merge_doctests: bool, +) -> Result<(ParseSourceInfo, bool), FatalError> { let result = rustc_driver::catch_fatal_errors(|| { rustc_span::create_session_if_not_set_then(edition, |_| { - use rustc_errors::emitter::{Emitter, HumanEmitter}; - use rustc_errors::DiagCtxt; - use rustc_parse::parser::ForceCollect; - use rustc_span::source_map::FilePathMapping; + let mut info = + ParseSourceInfo { found_extern_crate: crate_name.is_none(), ..Default::default() }; - let filename = FileName::anon_source_code(&source); - - // Any errors in parsing should also appear when the doctest is compiled for real, so just - // send all the errors that librustc_ast emits directly into a `Sink` instead of stderr. - let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); - let fallback_bundle = rustc_errors::fallback_fluent_bundle( - rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), - false, - ); - *supports_color = - HumanEmitter::new(stderr_destination(ColorConfig::Auto), fallback_bundle.clone()) - .supports_color(); - - let emitter = HumanEmitter::new(Box::new(io::sink()), fallback_bundle); - - // FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser - let dcx = DiagCtxt::new(Box::new(emitter)).disable_warnings(); - let psess = ParseSess::with_dcx(dcx, sm); - - let mut found_main = false; - let mut found_extern_crate = crate_name.is_none(); - let mut found_macro = false; - - let mut parser = match new_parser_from_source_str(&psess, filename, source.clone()) { - Ok(p) => p, - Err(errs) => { - errs.into_iter().for_each(|err| err.cancel()); - return (found_main, found_extern_crate, found_macro); - } - }; - - loop { - match parser.parse_item(ForceCollect::No) { - Ok(Some(item)) => { - if !found_main - && let ast::ItemKind::Fn(..) = item.kind - && item.ident.name == sym::main - { - found_main = true; - } - - if !found_extern_crate - && let ast::ItemKind::ExternCrate(original) = item.kind - { - // This code will never be reached if `crate_name` is none because - // `found_extern_crate` is initialized to `true` if it is none. - let crate_name = crate_name.unwrap(); - - match original { - Some(name) => found_extern_crate = name.as_str() == crate_name, - None => found_extern_crate = item.ident.as_str() == crate_name, - } - } - - if !found_macro && let ast::ItemKind::MacCall(..) = item.kind { - found_macro = true; - } - - if found_main && found_extern_crate { - break; - } - } - Ok(None) => break, - Err(e) => { - e.cancel(); - break; - } - } - - // The supplied item is only used for diagnostics, - // which are swallowed here anyway. - parser.maybe_consume_incorrect_semicolon(None); + let mut parsing_result = + parse_source(format!("{crates}{everything_else}"), &mut info, &crate_name); + // No need to double-check this if the "merged doctests" feature isn't enabled (so + // before the 2024 edition). + if can_merge_doctests && parsing_result != ParsingResult::Ok { + // If we found an AST error, we want to ensure it's because of an expression being + // used outside of a function. + // + // To do so, we wrap in a function in order to make sure that the doctest AST is + // correct. For example, if your doctest is `foo::bar()`, if we don't wrap it in a + // block, it would emit an AST error, which would be problematic for us since we + // want to filter out such errors which aren't "real" errors. + // + // The end goal is to be able to merge as many doctests as possible as one for much + // faster doctests run time. + parsing_result = parse_source( + format!("{crates}\nfn __doctest_wrap(){{{everything_else}\n}}"), + &mut info, + &crate_name, + ); } - // Reset errors so that they won't be reported as compiler bugs when dropping the - // dcx. Any errors in the tests will be reported when the test file is compiled, - // Note that we still need to cancel the errors above otherwise `Diag` will panic on - // drop. - psess.dcx().reset_err_count(); - - (found_main, found_extern_crate, found_macro) + (info, parsing_result) }) }); - let (already_has_main, already_has_extern_crate, found_macro) = result?; + let (mut info, parsing_result) = match result { + Err(..) | Ok((_, ParsingResult::Failed)) => return Err(FatalError), + Ok((info, parsing_result)) => (info, parsing_result), + }; // If a doctest's `fn main` is being masked by a wrapper macro, the parsing loop above won't // see it. In that case, run the old text-based scan to see if they at least have a main // function written inside a macro invocation. See // https://github.com/rust-lang/rust/issues/56898 - let already_has_main = if found_macro && !already_has_main { - source + if info.found_macro + && !info.has_main_fn + && original_source_code .lines() .map(|line| { let comment = line.find("//"); if let Some(comment_begins) = comment { &line[0..comment_begins] } else { line } }) .any(|code| code.contains("fn main")) - } else { - already_has_main - }; + { + info.has_main_fn = true; + } - Ok((already_has_main, already_has_extern_crate)) + Ok((info, parsing_result != ParsingResult::Ok)) } -fn check_if_attr_is_complete(source: &str, edition: Edition) -> bool { +enum AttrKind { + CrateAttr, + Attr, +} + +/// Returns `Some` if the attribute is complete and `Some(true)` if it is an attribute that can be +/// placed at the crate root. +fn check_if_attr_is_complete(source: &str, edition: Edition) -> Option { if source.is_empty() { // Empty content so nothing to check in here... - return true; + return None; } + let not_crate_attrs = [sym::forbid, sym::allow, sym::warn, sym::deny]; + rustc_driver::catch_fatal_errors(|| { rustc_span::create_session_if_not_set_then(edition, |_| { use rustc_errors::emitter::HumanEmitter; @@ -285,32 +463,75 @@ fn check_if_attr_is_complete(source: &str, edition: Edition) -> bool { errs.into_iter().for_each(|err| err.cancel()); // If there is an unclosed delimiter, an error will be returned by the // tokentrees. - return false; + return None; } }; // If a parsing error happened, it's very likely that the attribute is incomplete. - if let Err(e) = parser.parse_attribute(InnerAttrPolicy::Permitted) { - e.cancel(); - return false; - } - true + let ret = match parser.parse_attribute(InnerAttrPolicy::Permitted) { + Ok(attr) => { + let attr_name = attr.name_or_empty(); + + if not_crate_attrs.contains(&attr_name) { + // There is one exception to these attributes: + // `#![allow(internal_features)]`. If this attribute is used, we need to + // consider it only as a crate-level attribute. + if attr_name == sym::allow + && let Some(list) = attr.meta_item_list() + && list.iter().any(|sub_attr| { + sub_attr.name_or_empty().as_str() == "internal_features" + }) + { + Some(AttrKind::CrateAttr) + } else { + Some(AttrKind::Attr) + } + } else { + Some(AttrKind::CrateAttr) + } + } + Err(e) => { + e.cancel(); + None + } + }; + ret }) }) - .unwrap_or(false) + .unwrap_or(None) } -fn partition_source(s: &str, edition: Edition) -> (String, String, String) { +fn handle_attr(mod_attr_pending: &mut String, source_info: &mut SourceInfo, edition: Edition) { + if let Some(attr_kind) = check_if_attr_is_complete(mod_attr_pending, edition) { + let push_to = match attr_kind { + AttrKind::CrateAttr => &mut source_info.crate_attrs, + AttrKind::Attr => &mut source_info.maybe_crate_attrs, + }; + push_to.push_str(mod_attr_pending); + push_to.push('\n'); + // If it's complete, then we can clear the pending content. + mod_attr_pending.clear(); + } else if mod_attr_pending.ends_with('\\') { + mod_attr_pending.push('n'); + } +} + +#[derive(Default)] +struct SourceInfo { + crate_attrs: String, + maybe_crate_attrs: String, + crates: String, + everything_else: String, +} + +fn partition_source(s: &str, edition: Edition) -> SourceInfo { #[derive(Copy, Clone, PartialEq)] enum PartitionState { Attrs, Crates, Other, } + let mut source_info = SourceInfo::default(); let mut state = PartitionState::Attrs; - let mut before = String::new(); - let mut crates = String::new(); - let mut after = String::new(); - let mut mod_attr_pending = String::new(); for line in s.lines() { @@ -321,12 +542,9 @@ fn partition_source(s: &str, edition: Edition) -> (String, String, String) { match state { PartitionState::Attrs => { state = if trimline.starts_with("#![") { - if !check_if_attr_is_complete(line, edition) { - mod_attr_pending = line.to_owned(); - } else { - mod_attr_pending.clear(); - } - PartitionState::Attrs + mod_attr_pending = line.to_owned(); + handle_attr(&mut mod_attr_pending, &mut source_info, edition); + continue; } else if trimline.chars().all(|c| c.is_whitespace()) || (trimline.starts_with("//") && !trimline.starts_with("///")) { @@ -341,15 +559,10 @@ fn partition_source(s: &str, edition: Edition) -> (String, String, String) { // If not, then we append the new line into the pending attribute to check // if this time it's complete... mod_attr_pending.push_str(line); - if !trimline.is_empty() - && check_if_attr_is_complete(&mod_attr_pending, edition) - { - // If it's complete, then we can clear the pending content. - mod_attr_pending.clear(); + if !trimline.is_empty() { + handle_attr(&mut mod_attr_pending, &mut source_info, edition); } - // In any case, this is considered as `PartitionState::Attrs` so it's - // prepended before rustdoc's inserts. - PartitionState::Attrs + continue; } else { PartitionState::Other } @@ -371,23 +584,25 @@ fn partition_source(s: &str, edition: Edition) -> (String, String, String) { match state { PartitionState::Attrs => { - before.push_str(line); - before.push('\n'); + source_info.crate_attrs.push_str(line); + source_info.crate_attrs.push('\n'); } PartitionState::Crates => { - crates.push_str(line); - crates.push('\n'); + source_info.crates.push_str(line); + source_info.crates.push('\n'); } PartitionState::Other => { - after.push_str(line); - after.push('\n'); + source_info.everything_else.push_str(line); + source_info.everything_else.push('\n'); } } } - debug!("before:\n{before}"); - debug!("crates:\n{crates}"); - debug!("after:\n{after}"); + source_info.everything_else = source_info.everything_else.trim().to_string(); - (before, after, crates) + debug!("crate_attrs:\n{}{}", source_info.crate_attrs, source_info.maybe_crate_attrs); + debug!("crates:\n{}", source_info.crates); + debug!("after:\n{}", source_info.everything_else); + + source_info } diff --git a/src/librustdoc/doctest/markdown.rs b/src/librustdoc/doctest/markdown.rs index b8ab7adb36e..4806d865589 100644 --- a/src/librustdoc/doctest/markdown.rs +++ b/src/librustdoc/doctest/markdown.rs @@ -1,34 +1,29 @@ //! Doctest functionality used only for doctests in `.md` Markdown files. use std::fs::read_to_string; +use std::sync::{Arc, Mutex}; use rustc_span::FileName; use tempfile::tempdir; use super::{ - generate_args_file, CreateRunnableDoctests, DoctestVisitor, GlobalTestOptions, ScrapedDoctest, + generate_args_file, CreateRunnableDocTests, DocTestVisitor, GlobalTestOptions, ScrapedDocTest, }; use crate::config::Options; use crate::html::markdown::{find_testable_code, ErrorCodes, LangString, MdRelLine}; struct MdCollector { - tests: Vec, + tests: Vec, cur_path: Vec, filename: FileName, } -impl DoctestVisitor for MdCollector { +impl DocTestVisitor for MdCollector { fn visit_test(&mut self, test: String, config: LangString, rel_line: MdRelLine) { let filename = self.filename.clone(); // First line of Markdown is line 1. let line = 1 + rel_line.offset(); - self.tests.push(ScrapedDoctest { - filename, - line, - logical_path: self.cur_path.clone(), - langstr: config, - text: test, - }); + self.tests.push(ScrapedDocTest::new(filename, line, self.cur_path.clone(), config, test)); } fn visit_header(&mut self, name: &str, level: u32) { @@ -118,8 +113,16 @@ pub(crate) fn test(options: Options) -> Result<(), String> { None, ); - let mut collector = CreateRunnableDoctests::new(options.clone(), opts); + let mut collector = CreateRunnableDocTests::new(options.clone(), opts); md_collector.tests.into_iter().for_each(|t| collector.add_test(t)); - crate::doctest::run_tests(options.test_args, options.nocapture, collector.tests); + let CreateRunnableDocTests { opts, rustdoc_options, standalone_tests, mergeable_tests, .. } = + collector; + crate::doctest::run_tests( + opts, + &rustdoc_options, + &Arc::new(Mutex::new(Vec::new())), + standalone_tests, + mergeable_tests, + ); Ok(()) } diff --git a/src/librustdoc/doctest/runner.rs b/src/librustdoc/doctest/runner.rs new file mode 100644 index 00000000000..d49fa3ac5ac --- /dev/null +++ b/src/librustdoc/doctest/runner.rs @@ -0,0 +1,265 @@ +use std::fmt::Write; + +use rustc_data_structures::fx::FxHashSet; +use rustc_span::edition::Edition; + +use crate::doctest::{ + run_test, DocTestBuilder, GlobalTestOptions, IndividualTestOptions, RunnableDocTest, + RustdocOptions, ScrapedDocTest, TestFailure, UnusedExterns, +}; +use crate::html::markdown::{Ignore, LangString}; + +/// Convenient type to merge compatible doctests into one. +pub(crate) struct DocTestRunner { + crate_attrs: FxHashSet, + ids: String, + output: String, + supports_color: bool, + nb_tests: usize, +} + +impl DocTestRunner { + pub(crate) fn new() -> Self { + Self { + crate_attrs: FxHashSet::default(), + ids: String::new(), + output: String::new(), + supports_color: true, + nb_tests: 0, + } + } + + pub(crate) fn add_test( + &mut self, + doctest: &DocTestBuilder, + scraped_test: &ScrapedDocTest, + target_str: &str, + ) { + let ignore = match scraped_test.langstr.ignore { + Ignore::All => true, + Ignore::None => false, + Ignore::Some(ref ignores) => ignores.iter().any(|s| target_str.contains(s)), + }; + if !ignore { + for line in doctest.crate_attrs.split('\n') { + self.crate_attrs.insert(line.to_string()); + } + } + if !self.ids.is_empty() { + self.ids.push(','); + } + self.ids.push_str(&format!( + "{}::TEST", + generate_mergeable_doctest( + doctest, + scraped_test, + ignore, + self.nb_tests, + &mut self.output + ), + )); + self.supports_color &= doctest.supports_color; + self.nb_tests += 1; + } + + pub(crate) fn run_merged_tests( + &mut self, + test_options: IndividualTestOptions, + edition: Edition, + opts: &GlobalTestOptions, + test_args: &[String], + rustdoc_options: &RustdocOptions, + ) -> Result { + let mut code = "\ +#![allow(unused_extern_crates)] +#![allow(internal_features)] +#![feature(test)] +#![feature(rustc_attrs)] +" + .to_string(); + + for crate_attr in &self.crate_attrs { + code.push_str(crate_attr); + code.push('\n'); + } + + if opts.attrs.is_empty() { + // If there aren't any attributes supplied by #![doc(test(attr(...)))], then allow some + // lints that are commonly triggered in doctests. The crate-level test attributes are + // commonly used to make tests fail in case they trigger warnings, so having this there in + // that case may cause some tests to pass when they shouldn't have. + code.push_str("#![allow(unused)]\n"); + } + + // Next, any attributes that came from the crate root via #![doc(test(attr(...)))]. + for attr in &opts.attrs { + code.push_str(&format!("#![{attr}]\n")); + } + + code.push_str("extern crate test;\n"); + + let test_args = + test_args.iter().map(|arg| format!("{arg:?}.to_string(),")).collect::(); + write!( + code, + "\ +{output} + +mod __doctest_mod {{ + use std::sync::OnceLock; + use std::path::PathBuf; + + pub static BINARY_PATH: OnceLock = OnceLock::new(); + pub const RUN_OPTION: &str = \"*doctest-inner-test\"; + pub const BIN_OPTION: &str = \"*doctest-bin-path\"; + + #[allow(unused)] + pub fn doctest_path() -> Option<&'static PathBuf> {{ + self::BINARY_PATH.get() + }} + + #[allow(unused)] + pub fn doctest_runner(bin: &std::path::Path, test_nb: usize) -> Result<(), String> {{ + let out = std::process::Command::new(bin) + .arg(self::RUN_OPTION) + .arg(test_nb.to_string()) + .output() + .expect(\"failed to run command\"); + if !out.status.success() {{ + Err(String::from_utf8_lossy(&out.stderr).to_string()) + }} else {{ + Ok(()) + }} + }} +}} + +#[rustc_main] +fn main() -> std::process::ExitCode {{ +const TESTS: [test::TestDescAndFn; {nb_tests}] = [{ids}]; +let bin_marker = std::ffi::OsStr::new(__doctest_mod::BIN_OPTION); +let test_marker = std::ffi::OsStr::new(__doctest_mod::RUN_OPTION); +let test_args = &[{test_args}]; + +let mut args = std::env::args_os().skip(1); +while let Some(arg) = args.next() {{ + if arg == bin_marker {{ + let Some(binary) = args.next() else {{ + panic!(\"missing argument after `{{}}`\", __doctest_mod::BIN_OPTION); + }}; + if crate::__doctest_mod::BINARY_PATH.set(binary.into()).is_err() {{ + panic!(\"`{{}}` option was used more than once\", bin_marker.to_string_lossy()); + }} + return std::process::Termination::report(test::test_main(test_args, Vec::from(TESTS), None)); + }} else if arg == test_marker {{ + let Some(nb_test) = args.next() else {{ + panic!(\"missing argument after `{{}}`\", __doctest_mod::RUN_OPTION); + }}; + if let Some(nb_test) = nb_test.to_str().and_then(|nb| nb.parse::().ok()) {{ + if let Some(test) = TESTS.get(nb_test) {{ + if let test::StaticTestFn(f) = test.testfn {{ + return std::process::Termination::report(f()); + }} + }} + }} + panic!(\"Unexpected value after `{{}}`\", __doctest_mod::RUN_OPTION); + }} +}} + +eprintln!(\"WARNING: No argument provided so doctests will be run in the same process\"); +std::process::Termination::report(test::test_main(test_args, Vec::from(TESTS), None)) +}}", + nb_tests = self.nb_tests, + output = self.output, + ids = self.ids, + ) + .expect("failed to generate test code"); + let runnable_test = RunnableDocTest { + full_test_code: code, + full_test_line_offset: 0, + test_opts: test_options, + global_opts: opts.clone(), + langstr: LangString::default(), + line: 0, + edition, + no_run: false, + is_multiple_tests: true, + }; + let ret = + run_test(runnable_test, rustdoc_options, self.supports_color, |_: UnusedExterns| {}); + if let Err(TestFailure::CompileError) = ret { Err(()) } else { Ok(ret.is_ok()) } + } +} + +/// Push new doctest content into `output`. Returns the test ID for this doctest. +fn generate_mergeable_doctest( + doctest: &DocTestBuilder, + scraped_test: &ScrapedDocTest, + ignore: bool, + id: usize, + output: &mut String, +) -> String { + let test_id = format!("__doctest_{id}"); + + if ignore { + // We generate nothing else. + writeln!(output, "mod {test_id} {{\n").unwrap(); + } else { + writeln!(output, "mod {test_id} {{\n{}{}", doctest.crates, doctest.maybe_crate_attrs) + .unwrap(); + if scraped_test.langstr.no_run { + // To prevent having warnings about unused items since they're not called. + writeln!(output, "#![allow(unused)]").unwrap(); + } + if doctest.has_main_fn { + output.push_str(&doctest.everything_else); + } else { + let returns_result = if doctest.everything_else.trim_end().ends_with("(())") { + "-> Result<(), impl core::fmt::Debug>" + } else { + "" + }; + write!( + output, + "\ +fn main() {returns_result} {{ +{} +}}", + doctest.everything_else + ) + .unwrap(); + } + } + let not_running = ignore || scraped_test.langstr.no_run; + writeln!( + output, + " +pub const TEST: test::TestDescAndFn = test::TestDescAndFn::new_doctest( +{test_name:?}, {ignore}, {file:?}, {line}, {no_run}, {should_panic}, +test::StaticTestFn( + || {{{runner}}}, +)); +}}", + test_name = scraped_test.name, + file = scraped_test.path(), + line = scraped_test.line, + no_run = scraped_test.langstr.no_run, + should_panic = !scraped_test.langstr.no_run && scraped_test.langstr.should_panic, + // Setting `no_run` to `true` in `TestDesc` still makes the test run, so we simply + // don't give it the function to run. + runner = if not_running { + "test::assert_test_result(Ok::<(), String>(()))".to_string() + } else { + format!( + " +if let Some(bin_path) = crate::__doctest_mod::doctest_path() {{ + test::assert_test_result(crate::__doctest_mod::doctest_runner(bin_path, {id})) +}} else {{ + test::assert_test_result(self::main()) +}} +", + ) + }, + ) + .unwrap(); + test_id +} diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs index f179f3aa1c9..5c0898f28fc 100644 --- a/src/librustdoc/doctest/rust.rs +++ b/src/librustdoc/doctest/rust.rs @@ -14,14 +14,14 @@ use rustc_session::Session; use rustc_span::source_map::SourceMap; use rustc_span::{BytePos, FileName, Pos, Span, DUMMY_SP}; -use super::{DoctestVisitor, ScrapedDoctest}; +use super::{DocTestVisitor, ScrapedDocTest}; use crate::clean::types::AttributesExt; use crate::clean::Attributes; use crate::html::markdown::{self, ErrorCodes, LangString, MdRelLine}; struct RustCollector { source_map: Lrc, - tests: Vec, + tests: Vec, cur_path: Vec, position: Span, } @@ -48,16 +48,16 @@ impl RustCollector { } } -impl DoctestVisitor for RustCollector { +impl DocTestVisitor for RustCollector { fn visit_test(&mut self, test: String, config: LangString, rel_line: MdRelLine) { let line = self.get_base_line() + rel_line.offset(); - self.tests.push(ScrapedDoctest { - filename: self.get_filename(), + self.tests.push(ScrapedDocTest::new( + self.get_filename(), line, - logical_path: self.cur_path.clone(), - langstr: config, - text: test, - }); + self.cur_path.clone(), + config, + test, + )); } fn visit_header(&mut self, _name: &str, _level: u32) {} @@ -89,7 +89,7 @@ impl<'a, 'tcx> HirCollector<'a, 'tcx> { Self { sess, map, codes, enable_per_target_ignores, tcx, collector } } - pub fn collect_crate(mut self) -> Vec { + pub fn collect_crate(mut self) -> Vec { let tcx = self.tcx; self.visit_testable("".to_string(), CRATE_DEF_ID, tcx.hir().span(CRATE_HIR_ID), |this| { tcx.hir().walk_toplevel_module(this) @@ -136,7 +136,7 @@ impl<'a, 'tcx> HirCollector<'a, 'tcx> { self.enable_per_target_ignores, Some(&crate::html::markdown::ExtraInfo::new( self.tcx, - def_id.to_def_id(), + def_id, span_of_fragments(&attrs.doc_strings).unwrap_or(sp), )), ); diff --git a/src/librustdoc/doctest/tests.rs b/src/librustdoc/doctest/tests.rs index 0f13ee404c6..160d0f222b4 100644 --- a/src/librustdoc/doctest/tests.rs +++ b/src/librustdoc/doctest/tests.rs @@ -2,7 +2,27 @@ use std::path::PathBuf; use rustc_span::edition::DEFAULT_EDITION; -use super::{make_test, GlobalTestOptions}; +use super::{DocTestBuilder, GlobalTestOptions}; + +fn make_test( + test_code: &str, + crate_name: Option<&str>, + dont_insert_main: bool, + opts: &GlobalTestOptions, + test_id: Option<&str>, +) -> (String, usize) { + let doctest = DocTestBuilder::new( + test_code, + crate_name, + DEFAULT_EDITION, + false, + test_id.map(|s| s.to_string()), + None, + ); + let (code, line_offset) = + doctest.generate_unique_doctest(test_code, dont_insert_main, opts, crate_name); + (code, line_offset) +} /// Default [`GlobalTestOptions`] for these unit tests. fn default_global_opts(crate_name: impl Into) -> GlobalTestOptions { @@ -25,7 +45,7 @@ fn main() { assert_eq!(2+2, 4); }" .to_string(); - let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION, None); + let (output, len) = make_test(input, None, false, &opts, None); assert_eq!((output, len), (expected, 2)); } @@ -40,7 +60,7 @@ fn main() { assert_eq!(2+2, 4); }" .to_string(); - let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION, None); + let (output, len) = make_test(input, Some("asdf"), false, &opts, None); assert_eq!((output, len), (expected, 2)); } @@ -59,7 +79,7 @@ use asdf::qwop; assert_eq!(2+2, 4); }" .to_string(); - let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION, None); + let (output, len) = make_test(input, Some("asdf"), false, &opts, None); assert_eq!((output, len), (expected, 3)); } @@ -76,7 +96,7 @@ use asdf::qwop; assert_eq!(2+2, 4); }" .to_string(); - let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION, None); + let (output, len) = make_test(input, Some("asdf"), false, &opts, None); assert_eq!((output, len), (expected, 2)); } @@ -94,7 +114,7 @@ use std::*; assert_eq!(2+2, 4); }" .to_string(); - let (output, len, _) = make_test(input, Some("std"), false, &opts, DEFAULT_EDITION, None); + let (output, len) = make_test(input, Some("std"), false, &opts, None); assert_eq!((output, len), (expected, 2)); } @@ -113,7 +133,7 @@ use asdf::qwop; assert_eq!(2+2, 4); }" .to_string(); - let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION, None); + let (output, len) = make_test(input, Some("asdf"), false, &opts, None); assert_eq!((output, len), (expected, 2)); } @@ -130,7 +150,7 @@ use asdf::qwop; assert_eq!(2+2, 4); }" .to_string(); - let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION, None); + let (output, len) = make_test(input, Some("asdf"), false, &opts, None); assert_eq!((output, len), (expected, 2)); } @@ -150,7 +170,7 @@ use asdf::qwop; assert_eq!(2+2, 4); }" .to_string(); - let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION, None); + let (output, len) = make_test(input, Some("asdf"), false, &opts, None); assert_eq!((output, len), (expected, 3)); // Adding more will also bump the returned line offset. @@ -164,7 +184,7 @@ use asdf::qwop; assert_eq!(2+2, 4); }" .to_string(); - let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION, None); + let (output, len) = make_test(input, Some("asdf"), false, &opts, None); assert_eq!((output, len), (expected, 4)); } @@ -181,7 +201,7 @@ fn main() { assert_eq!(2+2, 4); }" .to_string(); - let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION, None); + let (output, len) = make_test(input, None, false, &opts, None); assert_eq!((output, len), (expected, 2)); } @@ -197,7 +217,7 @@ fn main() { assert_eq!(2+2, 4); }" .to_string(); - let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION, None); + let (output, len) = make_test(input, None, false, &opts, None); assert_eq!((output, len), (expected, 1)); } @@ -213,7 +233,7 @@ fn main() { assert_eq!(2+2, 4); }" .to_string(); - let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION, None); + let (output, len) = make_test(input, None, false, &opts, None); assert_eq!((output, len), (expected, 2)); } @@ -227,7 +247,7 @@ assert_eq!(2+2, 4);"; //Ceci n'est pas une `fn main` assert_eq!(2+2, 4);" .to_string(); - let (output, len, _) = make_test(input, None, true, &opts, DEFAULT_EDITION, None); + let (output, len) = make_test(input, None, true, &opts, None); assert_eq!((output, len), (expected, 1)); } @@ -245,7 +265,7 @@ assert_eq!(2+2, 4); }" .to_string(); - let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION, None); + let (output, len) = make_test(input, None, false, &opts, None); assert_eq!((output, len), (expected, 2)); } @@ -265,7 +285,7 @@ assert_eq!(asdf::foo, 4); }" .to_string(); - let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION, None); + let (output, len) = make_test(input, Some("asdf"), false, &opts, None); assert_eq!((output, len), (expected, 3)); } @@ -283,7 +303,7 @@ test_wrapper! { }" .to_string(); - let (output, len, _) = make_test(input, Some("my_crate"), false, &opts, DEFAULT_EDITION, None); + let (output, len) = make_test(input, Some("my_crate"), false, &opts, None); assert_eq!((output, len), (expected, 1)); } @@ -303,7 +323,7 @@ io::stdin().read_line(&mut input)?; Ok::<(), io:Error>(()) } _inner().unwrap() }" .to_string(); - let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION, None); + let (output, len) = make_test(input, None, false, &opts, None); assert_eq!((output, len), (expected, 2)); } @@ -317,8 +337,7 @@ fn main() { #[allow(non_snake_case)] fn _doctest_main__some_unique_name() { assert_eq!(2+2, 4); } _doctest_main__some_unique_name() }" .to_string(); - let (output, len, _) = - make_test(input, None, false, &opts, DEFAULT_EDITION, Some("_some_unique_name")); + let (output, len) = make_test(input, None, false, &opts, Some("_some_unique_name")); assert_eq!((output, len), (expected, 2)); } @@ -337,7 +356,7 @@ fn main() { eprintln!(\"hello anan\"); }" .to_string(); - let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION, None); + let (output, len) = make_test(input, None, false, &opts, None); assert_eq!((output, len), (expected, 2)); } @@ -357,6 +376,6 @@ fn main() { eprintln!(\"hello anan\"); }" .to_string(); - let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION, None); + let (output, len) = make_test(input, None, false, &opts, None); assert_eq!((output, len), (expected, 1)); } diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs index 3dcef15b552..9754e1e6f74 100644 --- a/src/librustdoc/formats/item_type.rs +++ b/src/librustdoc/formats/item_type.rs @@ -162,7 +162,8 @@ impl ItemType { | DefKind::LifetimeParam | DefKind::GlobalAsm | DefKind::Impl { .. } - | DefKind::Closure => Self::ForeignType, + | DefKind::Closure + | DefKind::SyntheticCoroutineBody => Self::ForeignType, } } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 6357cfee141..5cbf8c5e19f 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1288,56 +1288,90 @@ impl clean::Impl { if self.is_negative_trait_impl() { write!(f, "!")?; } - ty.print(cx).fmt(f)?; + if self.kind.is_fake_variadic() + && let generics = ty.generics() + && let &[inner_type] = generics.as_ref().map_or(&[][..], |v| &v[..]) + { + let last = ty.last(); + if f.alternate() { + write!(f, "{}<", last)?; + self.print_type(inner_type, f, use_absolute, cx)?; + write!(f, ">")?; + } else { + write!(f, "{}<", anchor(ty.def_id(), last, cx).to_string())?; + self.print_type(inner_type, f, use_absolute, cx)?; + write!(f, ">")?; + } + } else { + ty.print(cx).fmt(f)?; + } write!(f, " for ")?; } - if let clean::Type::Tuple(types) = &self.for_ - && let [clean::Type::Generic(name)] = &types[..] - && (self.kind.is_fake_variadic() || self.kind.is_auto()) - { - // Hardcoded anchor library/core/src/primitive_docs.rs - // Link should match `# Trait implementations` - primitive_link_fragment( - f, - PrimitiveType::Tuple, - format_args!("({name}₁, {name}₂, …, {name}ₙ)"), - "#trait-implementations-1", - cx, - )?; - } else if let clean::BareFunction(bare_fn) = &self.for_ - && let [clean::Argument { type_: clean::Type::Generic(name), .. }] = - &bare_fn.decl.inputs.values[..] - && (self.kind.is_fake_variadic() || self.kind.is_auto()) - { - // Hardcoded anchor library/core/src/primitive_docs.rs - // Link should match `# Trait implementations` - - print_higher_ranked_params_with_space(&bare_fn.generic_params, cx).fmt(f)?; - bare_fn.safety.print_with_space().fmt(f)?; - print_abi_with_space(bare_fn.abi).fmt(f)?; - let ellipsis = if bare_fn.decl.c_variadic { ", ..." } else { "" }; - primitive_link_fragment( - f, - PrimitiveType::Tuple, - format_args!("fn({name}₁, {name}₂, …, {name}ₙ{ellipsis})"), - "#trait-implementations-1", - cx, - )?; - // Write output. - if !bare_fn.decl.output.is_unit() { - write!(f, " -> ")?; - fmt_type(&bare_fn.decl.output, f, use_absolute, cx)?; - } - } else if let Some(ty) = self.kind.as_blanket_ty() { + if let Some(ty) = self.kind.as_blanket_ty() { fmt_type(ty, f, use_absolute, cx)?; } else { - fmt_type(&self.for_, f, use_absolute, cx)?; + self.print_type(&self.for_, f, use_absolute, cx)?; } print_where_clause(&self.generics, cx, 0, Ending::Newline).fmt(f) }) } + fn print_type<'a, 'tcx: 'a>( + &self, + type_: &clean::Type, + f: &mut fmt::Formatter<'_>, + use_absolute: bool, + cx: &'a Context<'tcx>, + ) -> Result<(), fmt::Error> { + if let clean::Type::Tuple(types) = type_ + && let [clean::Type::Generic(name)] = &types[..] + && (self.kind.is_fake_variadic() || self.kind.is_auto()) + { + // Hardcoded anchor library/core/src/primitive_docs.rs + // Link should match `# Trait implementations` + primitive_link_fragment( + f, + PrimitiveType::Tuple, + format_args!("({name}₁, {name}₂, …, {name}ₙ)"), + "#trait-implementations-1", + cx, + )?; + } else if let clean::Type::Array(ty, len) = type_ + && let clean::Type::Generic(name) = &**ty + && &len[..] == "1" + && (self.kind.is_fake_variadic() || self.kind.is_auto()) + { + primitive_link(f, PrimitiveType::Array, format_args!("[{name}; N]"), cx)?; + } else if let clean::BareFunction(bare_fn) = &type_ + && let [clean::Argument { type_: clean::Type::Generic(name), .. }] = + &bare_fn.decl.inputs.values[..] + && (self.kind.is_fake_variadic() || self.kind.is_auto()) + { + // Hardcoded anchor library/core/src/primitive_docs.rs + // Link should match `# Trait implementations` + + print_higher_ranked_params_with_space(&bare_fn.generic_params, cx).fmt(f)?; + bare_fn.safety.print_with_space().fmt(f)?; + print_abi_with_space(bare_fn.abi).fmt(f)?; + let ellipsis = if bare_fn.decl.c_variadic { ", ..." } else { "" }; + primitive_link_fragment( + f, + PrimitiveType::Tuple, + format_args!("fn({name}₁, {name}₂, …, {name}ₙ{ellipsis})"), + "#trait-implementations-1", + cx, + )?; + // Write output. + if !bare_fn.decl.output.is_unit() { + write!(f, " -> ")?; + fmt_type(&bare_fn.decl.output, f, use_absolute, cx)?; + } + } else { + fmt_type(&type_, f, use_absolute, cx)?; + } + Ok(()) + } } impl clean::Arguments { diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index c41db654112..364d4e077b1 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -40,7 +40,7 @@ use pulldown_cmark::{ }; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Diag, DiagMessage}; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::LocalDefId; use rustc_middle::ty::TyCtxt; pub(crate) use rustc_resolve::rustdoc::main_body_opts; use rustc_resolve::rustdoc::may_be_doc_link; @@ -297,7 +297,8 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> { attrs: vec![], args_file: PathBuf::new(), }; - let (test, _, _) = doctest::make_test(&test, krate, false, &opts, edition, None); + let doctest = doctest::DocTestBuilder::new(&test, krate, edition, false, None, None); + let (test, _) = doctest.generate_unique_doctest(&test, false, &opts, krate); let channel = if test.contains("#![feature(") { "&version=nightly" } else { "" }; let test_escaped = small_url_encode(test); @@ -737,7 +738,7 @@ impl MdRelLine { } } -pub(crate) fn find_testable_code( +pub(crate) fn find_testable_code( doc: &str, tests: &mut T, error_codes: ErrorCodes, @@ -747,7 +748,7 @@ pub(crate) fn find_testable_code( find_codes(doc, tests, error_codes, enable_per_target_ignores, extra_info, false) } -pub(crate) fn find_codes( +pub(crate) fn find_codes( doc: &str, tests: &mut T, error_codes: ErrorCodes, @@ -817,27 +818,25 @@ pub(crate) fn find_codes( } pub(crate) struct ExtraInfo<'tcx> { - def_id: DefId, + def_id: LocalDefId, sp: Span, tcx: TyCtxt<'tcx>, } impl<'tcx> ExtraInfo<'tcx> { - pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: DefId, sp: Span) -> ExtraInfo<'tcx> { + pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId, sp: Span) -> ExtraInfo<'tcx> { ExtraInfo { def_id, sp, tcx } } fn error_invalid_codeblock_attr(&self, msg: impl Into) { - if let Some(def_id) = self.def_id.as_local() { - self.tcx.node_span_lint( - crate::lint::INVALID_CODEBLOCK_ATTRIBUTES, - self.tcx.local_def_id_to_hir_id(def_id), - self.sp, - |lint| { - lint.primary_message(msg); - }, - ); - } + self.tcx.node_span_lint( + crate::lint::INVALID_CODEBLOCK_ATTRIBUTES, + self.tcx.local_def_id_to_hir_id(self.def_id), + self.sp, + |lint| { + lint.primary_message(msg); + }, + ); } fn error_invalid_codeblock_attr_with_help( @@ -845,17 +844,15 @@ impl<'tcx> ExtraInfo<'tcx> { msg: impl Into, f: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>), ) { - if let Some(def_id) = self.def_id.as_local() { - self.tcx.node_span_lint( - crate::lint::INVALID_CODEBLOCK_ATTRIBUTES, - self.tcx.local_def_id_to_hir_id(def_id), - self.sp, - |lint| { - lint.primary_message(msg); - f(lint); - }, - ); - } + self.tcx.node_span_lint( + crate::lint::INVALID_CODEBLOCK_ATTRIBUTES, + self.tcx.local_def_id_to_hir_id(self.def_id), + self.sp, + |lint| { + lint.primary_message(msg); + f(lint); + }, + ); } } @@ -868,6 +865,7 @@ pub(crate) struct LangString { pub(crate) rust: bool, pub(crate) test_harness: bool, pub(crate) compile_fail: bool, + pub(crate) standalone: bool, pub(crate) error_codes: Vec, pub(crate) edition: Option, pub(crate) added_classes: Vec, @@ -1190,6 +1188,7 @@ impl Default for LangString { rust: true, test_harness: false, compile_fail: false, + standalone: false, error_codes: Vec::new(), edition: None, added_classes: Vec::new(), @@ -1259,6 +1258,10 @@ impl LangString { seen_rust_tags = !seen_other_tags || seen_rust_tags; data.no_run = true; } + LangStringToken::LangToken("standalone") => { + data.standalone = true; + seen_rust_tags = !seen_other_tags || seen_rust_tags; + } LangStringToken::LangToken(x) if x.starts_with("edition") => { data.edition = x[7..].parse::().ok(); } diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 0334eacc161..0ed8921b1e8 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -14,7 +14,6 @@ use rustc_span::edition::Edition; use rustc_span::{sym, FileName, Symbol}; use super::print_item::{full_path, item_path, print_item}; -use super::search_index::build_index; use super::sidebar::{print_sidebar, sidebar_module_like, Sidebar}; use super::write_shared::write_shared; use super::{collect_spans_and_sources, scrape_examples_help, AllTypes, LinkFromSrc, StylePath}; @@ -573,13 +572,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { } if !no_emit_shared { - // Build our search index - let index = build_index(&krate, &mut Rc::get_mut(&mut cx.shared).unwrap().cache, tcx); - - // Write shared runs within a flock; disable thread dispatching of IO temporarily. - Rc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(true); - write_shared(&mut cx, &krate, index, &md_opts)?; - Rc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(false); + write_shared(&mut cx, &krate, &md_opts, tcx)?; } Ok((cx, krate)) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 7ce637d3ab4..47f321a4c4a 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -29,8 +29,10 @@ pub(crate) mod search_index; mod tests; mod context; +mod ordered_json; mod print_item; pub(crate) mod sidebar; +mod sorted_template; mod span_map; mod type_layout; mod write_shared; @@ -1728,6 +1730,7 @@ fn render_impl( let source_id = format!("{item_type}.{name}"); let id = cx.derive_id(&source_id); write!(w, "
"); + render_rightside(w, cx, item, render_mode); if trait_.is_some() { // Anchors are only used on trait impls. write!(w, "§"); @@ -1749,6 +1752,7 @@ fn render_impl( let source_id = format!("{item_type}.{name}"); let id = cx.derive_id(&source_id); write!(w, "
"); + render_rightside(w, cx, item, render_mode); if trait_.is_some() { // Anchors are only used on trait impls. write!(w, "§"); diff --git a/src/librustdoc/html/render/ordered_json.rs b/src/librustdoc/html/render/ordered_json.rs new file mode 100644 index 00000000000..7abe40eef3b --- /dev/null +++ b/src/librustdoc/html/render/ordered_json.rs @@ -0,0 +1,83 @@ +use std::borrow::Borrow; +use std::fmt; + +use itertools::Itertools as _; +use serde::{Deserialize, Serialize}; +use serde_json::Value; + +/// Prerendered json. +/// +/// Both the Display and serde_json::to_string implementations write the serialized json +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] +#[serde(from = "Value")] +#[serde(into = "Value")] +pub(crate) struct OrderedJson(String); + +impl OrderedJson { + /// If you pass in an array, it will not be sorted. + pub(crate) fn serialize(item: T) -> Result { + Ok(Self(serde_json::to_string(&item)?)) + } + + /// Serializes and sorts + pub(crate) fn array_sorted, I: IntoIterator>(items: I) -> Self { + let items = items + .into_iter() + .sorted_unstable_by(|a, b| a.borrow().cmp(&b.borrow())) + .format_with(",", |item, f| f(item.borrow())); + Self(format!("[{}]", items)) + } + + pub(crate) fn array_unsorted, I: IntoIterator>(items: I) -> Self { + let items = items.into_iter().format_with(",", |item, f| f(item.borrow())); + Self(format!("[{items}]")) + } +} + +impl fmt::Display for OrderedJson { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +impl From for OrderedJson { + fn from(value: Value) -> Self { + let serialized = + serde_json::to_string(&value).expect("Serializing a Value to String should never fail"); + Self(serialized) + } +} + +impl From for Value { + fn from(json: OrderedJson) -> Self { + serde_json::from_str(&json.0).expect("OrderedJson should always store valid JSON") + } +} + +/// For use in JSON.parse('{...}'). +/// +/// Assumes we are going to be wrapped in single quoted strings. +/// +/// JSON.parse loads faster than raw JS source, +/// so this is used for large objects. +#[derive(Debug, Clone, Serialize, Deserialize)] +pub(crate) struct EscapedJson(OrderedJson); + +impl From for EscapedJson { + fn from(json: OrderedJson) -> Self { + Self(json) + } +} + +impl fmt::Display for EscapedJson { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // All these `replace` calls are because we have to go through JS string + // for JSON content. + // We need to escape double quotes for the JSON + let json = self.0.0.replace('\\', r"\\").replace('\'', r"\'").replace("\\\"", "\\\\\""); + json.fmt(f) + } +} + +#[cfg(test)] +mod tests; diff --git a/src/librustdoc/html/render/ordered_json/tests.rs b/src/librustdoc/html/render/ordered_json/tests.rs new file mode 100644 index 00000000000..e0fe6446b9a --- /dev/null +++ b/src/librustdoc/html/render/ordered_json/tests.rs @@ -0,0 +1,121 @@ +use super::super::ordered_json::*; + +fn check(json: OrderedJson, serialized: &str) { + assert_eq!(json.to_string(), serialized); + assert_eq!(serde_json::to_string(&json).unwrap(), serialized); + + let json = json.to_string(); + let json: OrderedJson = serde_json::from_str(&json).unwrap(); + + assert_eq!(json.to_string(), serialized); + assert_eq!(serde_json::to_string(&json).unwrap(), serialized); + + let json = serde_json::to_string(&json).unwrap(); + let json: OrderedJson = serde_json::from_str(&json).unwrap(); + + assert_eq!(json.to_string(), serialized); + assert_eq!(serde_json::to_string(&json).unwrap(), serialized); +} + +// Make sure there is no extra level of string, plus number of escapes. +#[test] +fn escape_json_number() { + let json = OrderedJson::serialize(3).unwrap(); + let json = EscapedJson::from(json); + assert_eq!(format!("{json}"), "3"); +} + +#[test] +fn escape_json_single_quote() { + let json = OrderedJson::serialize("he's").unwrap(); + let json = EscapedJson::from(json); + assert_eq!(format!("{json}"), r#""he\'s""#); +} + +#[test] +fn escape_json_array() { + let json = OrderedJson::serialize([1, 2, 3]).unwrap(); + let json = EscapedJson::from(json); + assert_eq!(format!("{json}"), r#"[1,2,3]"#); +} + +#[test] +fn escape_json_string() { + let json = OrderedJson::serialize(r#"he"llo"#).unwrap(); + let json = EscapedJson::from(json); + assert_eq!(format!("{json}"), r#""he\\\"llo""#); +} + +#[test] +fn escape_json_string_escaped() { + let json = OrderedJson::serialize(r#"he\"llo"#).unwrap(); + let json = EscapedJson::from(json); + assert_eq!(format!("{json}"), r#""he\\\\\\\"llo""#); +} + +#[test] +fn escape_json_string_escaped_escaped() { + let json = OrderedJson::serialize(r#"he\\"llo"#).unwrap(); + let json = EscapedJson::from(json); + assert_eq!(format!("{json}"), r#""he\\\\\\\\\\\"llo""#); +} + +// Testing round trip + making sure there is no extra level of string +#[test] +fn number() { + let json = OrderedJson::serialize(3).unwrap(); + let serialized = "3"; + check(json, serialized); +} + +#[test] +fn boolean() { + let json = OrderedJson::serialize(true).unwrap(); + let serialized = "true"; + check(json, serialized); +} + +#[test] +fn string() { + let json = OrderedJson::serialize("he\"llo").unwrap(); + let serialized = r#""he\"llo""#; + check(json, serialized); +} + +#[test] +fn serialize_array() { + let json = OrderedJson::serialize([3, 1, 2]).unwrap(); + let serialized = "[3,1,2]"; + check(json, serialized); +} + +#[test] +fn sorted_array() { + let items = ["c", "a", "b"]; + let serialized = r#"["a","b","c"]"#; + let items: Vec = + items.into_iter().map(OrderedJson::serialize).collect::, _>>().unwrap(); + let json = OrderedJson::array_sorted(items); + check(json, serialized); +} + +#[test] +fn nested_array() { + let a = OrderedJson::serialize(3).unwrap(); + let b = OrderedJson::serialize(2).unwrap(); + let c = OrderedJson::serialize(1).unwrap(); + let d = OrderedJson::serialize([1, 3, 2]).unwrap(); + let json = OrderedJson::array_sorted([a, b, c, d]); + let serialized = r#"[1,2,3,[1,3,2]]"#; + check(json, serialized); +} + +#[test] +fn array_unsorted() { + let items = ["c", "a", "b"]; + let serialized = r#"["c","a","b"]"#; + let items: Vec = + items.into_iter().map(OrderedJson::serialize).collect::, _>>().unwrap(); + let json = OrderedJson::array_unsorted(items); + check(json, serialized); +} diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index 8a2f31f7413..d7682bd1c19 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -18,6 +18,7 @@ use crate::formats::cache::{Cache, OrphanImplItem}; use crate::formats::item_type::ItemType; use crate::html::format::join_with_double_colon; use crate::html::markdown::short_markdown_summary; +use crate::html::render::ordered_json::OrderedJson; use crate::html::render::{self, IndexItem, IndexItemFunctionType, RenderType, RenderTypeId}; /// The serialized search description sharded version @@ -46,7 +47,7 @@ use crate::html::render::{self, IndexItem, IndexItemFunctionType, RenderType, Re /// [2]: https://en.wikipedia.org/wiki/Sliding_window_protocol#Basic_concept /// [3]: https://learn.microsoft.com/en-us/troubleshoot/windows-server/networking/description-tcp-features pub(crate) struct SerializedSearchIndex { - pub(crate) index: String, + pub(crate) index: OrderedJson, pub(crate) desc: Vec<(usize, String)>, } @@ -578,12 +579,14 @@ pub(crate) fn build_index<'tcx>( let mut names = Vec::with_capacity(self.items.len()); let mut types = String::with_capacity(self.items.len()); let mut full_paths = Vec::with_capacity(self.items.len()); - let mut parents = Vec::with_capacity(self.items.len()); + let mut parents = String::with_capacity(self.items.len()); + let mut parents_backref_queue = VecDeque::new(); let mut functions = String::with_capacity(self.items.len()); let mut deprecated = Vec::with_capacity(self.items.len()); - let mut backref_queue = VecDeque::new(); + let mut type_backref_queue = VecDeque::new(); + let mut last_name = None; for (index, item) in self.items.iter().enumerate() { let n = item.ty as u8; let c = char::try_from(n + b'A').expect("item types must fit in ASCII"); @@ -596,17 +599,39 @@ pub(crate) fn build_index<'tcx>( "`{}` is missing idx", item.name ); - // 0 is a sentinel, everything else is one-indexed - parents.push(item.parent_idx.map(|x| x + 1).unwrap_or(0)); + assert!( + parents_backref_queue.len() <= 16, + "the string encoding only supports 16 slots of lookback" + ); + let parent: i32 = item.parent_idx.map(|x| x + 1).unwrap_or(0).try_into().unwrap(); + if let Some(idx) = parents_backref_queue.iter().position(|p: &i32| *p == parent) { + parents.push( + char::try_from('0' as u32 + u32::try_from(idx).unwrap()) + .expect("last possible value is '?'"), + ); + } else if parent == 0 { + write_vlqhex_to_string(parent, &mut parents); + } else { + parents_backref_queue.push_front(parent); + write_vlqhex_to_string(parent, &mut parents); + if parents_backref_queue.len() > 16 { + parents_backref_queue.pop_back(); + } + } - names.push(item.name.as_str()); + if Some(item.name.as_str()) == last_name { + names.push(""); + } else { + names.push(item.name.as_str()); + last_name = Some(item.name.as_str()); + } if !item.path.is_empty() { full_paths.push((index, &item.path)); } match &item.search_type { - Some(ty) => ty.write_to_string(&mut functions, &mut backref_queue), + Some(ty) => ty.write_to_string(&mut functions, &mut type_backref_queue), None => functions.push('`'), } @@ -683,24 +708,19 @@ pub(crate) fn build_index<'tcx>( // The index, which is actually used to search, is JSON // It uses `JSON.parse(..)` to actually load, since JSON // parses faster than the full JavaScript syntax. - let index = format!( - r#"["{}",{}]"#, - krate.name(tcx), - serde_json::to_string(&CrateData { - items: crate_items, - paths: crate_paths, - aliases: &aliases, - associated_item_disambiguators: &associated_item_disambiguators, - desc_index, - empty_desc, - }) - .expect("failed serde conversion") - // All these `replace` calls are because we have to go through JS string for JSON content. - .replace('\\', r"\\") - .replace('\'', r"\'") - // We need to escape double quotes for the JSON. - .replace("\\\"", "\\\\\"") - ); + let crate_name = krate.name(tcx); + let data = CrateData { + items: crate_items, + paths: crate_paths, + aliases: &aliases, + associated_item_disambiguators: &associated_item_disambiguators, + desc_index, + empty_desc, + }; + let index = OrderedJson::array_unsorted([ + OrderedJson::serialize(crate_name.as_str()).unwrap(), + OrderedJson::serialize(data).unwrap(), + ]); SerializedSearchIndex { index, desc } } diff --git a/src/librustdoc/html/render/sorted_template.rs b/src/librustdoc/html/render/sorted_template.rs new file mode 100644 index 00000000000..28f7766d7c7 --- /dev/null +++ b/src/librustdoc/html/render/sorted_template.rs @@ -0,0 +1,159 @@ +use std::collections::BTreeSet; +use std::fmt::{self, Write as _}; +use std::marker::PhantomData; +use std::str::FromStr; + +use itertools::{Itertools as _, Position}; +use serde::{Deserialize, Serialize}; + +/// Append-only templates for sorted, deduplicated lists of items. +/// +/// Last line of the rendered output is a comment encoding the next insertion point. +#[derive(Debug, Clone)] +pub(crate) struct SortedTemplate { + format: PhantomData, + before: String, + after: String, + fragments: BTreeSet, +} + +/// Written to last line of file to specify the location of each fragment +#[derive(Serialize, Deserialize, Debug, Clone)] +struct Offset { + /// Index of the first byte in the template + start: usize, + /// The length of each fragment in the encoded template, including the separator + fragment_lengths: Vec, +} + +impl SortedTemplate { + /// Generate this template from arbitary text. + /// Will insert wherever the substring `delimiter` can be found. + /// Errors if it does not appear exactly once. + pub(crate) fn from_template(template: &str, delimiter: &str) -> Result { + let mut split = template.split(delimiter); + let before = split.next().ok_or(Error("delimiter should appear at least once"))?; + let after = split.next().ok_or(Error("delimiter should appear at least once"))?; + // not `split_once` because we want to check for too many occurrences + if split.next().is_some() { + return Err(Error("delimiter should appear at most once")); + } + Ok(Self::from_before_after(before, after)) + } + + /// Template will insert fragments between `before` and `after` + pub(crate) fn from_before_after(before: S, after: T) -> Self { + let before = before.to_string(); + let after = after.to_string(); + Self { format: PhantomData, before, after, fragments: Default::default() } + } +} + +impl SortedTemplate { + /// Adds this text to the template + pub(crate) fn append(&mut self, insert: String) { + self.fragments.insert(insert); + } +} + +impl fmt::Display for SortedTemplate { + fn fmt(&self, mut f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut fragment_lengths = Vec::default(); + write!(f, "{}", self.before)?; + for (p, fragment) in self.fragments.iter().with_position() { + let mut f = DeltaWriter { inner: &mut f, delta: 0 }; + let sep = if matches!(p, Position::First | Position::Only) { "" } else { F::SEPARATOR }; + write!(f, "{}{}", sep, fragment)?; + fragment_lengths.push(f.delta); + } + let offset = Offset { start: self.before.len(), fragment_lengths }; + let offset = serde_json::to_string(&offset).unwrap(); + write!(f, "{}\n{}{}{}", self.after, F::COMMENT_START, offset, F::COMMENT_END) + } +} + +impl FromStr for SortedTemplate { + type Err = Error; + fn from_str(s: &str) -> Result { + let (s, offset) = s + .rsplit_once("\n") + .ok_or(Error("invalid format: should have a newline on the last line"))?; + let offset = offset + .strip_prefix(F::COMMENT_START) + .ok_or(Error("last line expected to start with a comment"))?; + let offset = offset + .strip_suffix(F::COMMENT_END) + .ok_or(Error("last line expected to end with a comment"))?; + let offset: Offset = serde_json::from_str(&offset).map_err(|_| { + Error("could not find insertion location descriptor object on last line") + })?; + let (before, mut s) = + s.split_at_checked(offset.start).ok_or(Error("invalid start: out of bounds"))?; + let mut fragments = BTreeSet::default(); + for (p, &index) in offset.fragment_lengths.iter().with_position() { + let (fragment, rest) = + s.split_at_checked(index).ok_or(Error("invalid fragment length: out of bounds"))?; + s = rest; + let sep = if matches!(p, Position::First | Position::Only) { "" } else { F::SEPARATOR }; + let fragment = fragment + .strip_prefix(sep) + .ok_or(Error("invalid fragment length: expected to find separator here"))?; + fragments.insert(fragment.to_string()); + } + Ok(Self { + format: PhantomData, + before: before.to_string(), + after: s.to_string(), + fragments, + }) + } +} + +pub(crate) trait FileFormat { + const COMMENT_START: &'static str; + const COMMENT_END: &'static str; + const SEPARATOR: &'static str; +} + +#[derive(Debug, Clone)] +pub(crate) struct Html; + +impl FileFormat for Html { + const COMMENT_START: &'static str = ""; + const SEPARATOR: &'static str = ""; +} + +#[derive(Debug, Clone)] +pub(crate) struct Js; + +impl FileFormat for Js { + const COMMENT_START: &'static str = "//"; + const COMMENT_END: &'static str = ""; + const SEPARATOR: &'static str = ","; +} + +#[derive(Debug, Clone)] +pub(crate) struct Error(&'static str); + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "invalid template: {}", self.0) + } +} + +struct DeltaWriter { + inner: W, + delta: usize, +} + +impl fmt::Write for DeltaWriter { + fn write_str(&mut self, s: &str) -> fmt::Result { + self.inner.write_str(s)?; + self.delta += s.len(); + Ok(()) + } +} + +#[cfg(test)] +mod tests; diff --git a/src/librustdoc/html/render/sorted_template/tests.rs b/src/librustdoc/html/render/sorted_template/tests.rs new file mode 100644 index 00000000000..db057463005 --- /dev/null +++ b/src/librustdoc/html/render/sorted_template/tests.rs @@ -0,0 +1,149 @@ +use std::str::FromStr; + +use super::super::sorted_template::*; + +fn is_comment_js(s: &str) -> bool { + s.starts_with("//") +} + +fn is_comment_html(s: &str) -> bool { + // not correct but good enough for these tests + s.starts_with("") +} + +#[test] +fn html_from_empty() { + let inserts = ["

hello

", "

kind

", "

hello

", "

world

"]; + let mut template = SortedTemplate::::from_before_after("", ""); + for insert in inserts { + template.append(insert.to_string()); + } + let template = format!("{template}"); + let (template, end) = template.rsplit_once("\n").unwrap(); + assert_eq!(template, "

hello

kind

world

"); + assert!(is_comment_html(end)); + assert!(!end.contains("\n")); +} + +#[test] +fn html_page() { + let inserts = ["

hello

", "

kind

", "

world

"]; + let before = ""; + let after = ""; + let mut template = SortedTemplate::::from_before_after(before, after); + for insert in inserts { + template.append(insert.to_string()); + } + let template = format!("{template}"); + let (template, end) = template.rsplit_once("\n").unwrap(); + assert_eq!(template, format!("{before}{}{after}", inserts.join(""))); + assert!(is_comment_html(end)); + assert!(!end.contains("\n")); +} + +#[test] +fn js_from_empty() { + let inserts = ["1", "2", "2", "2", "3", "1"]; + let mut template = SortedTemplate::::from_before_after("", ""); + for insert in inserts { + template.append(insert.to_string()); + } + let template = format!("{template}"); + let (template, end) = template.rsplit_once("\n").unwrap(); + assert_eq!(template, "1,2,3"); + assert!(is_comment_js(end)); + assert!(!end.contains("\n")); +} + +#[test] +fn js_empty_array() { + let template = SortedTemplate::::from_before_after("[", "]"); + let template = format!("{template}"); + let (template, end) = template.rsplit_once("\n").unwrap(); + assert_eq!(template, format!("[]")); + assert!(is_comment_js(end)); + assert!(!end.contains("\n")); +} + +#[test] +fn js_number_array() { + let inserts = ["1", "2", "3"]; + let mut template = SortedTemplate::::from_before_after("[", "]"); + for insert in inserts { + template.append(insert.to_string()); + } + let template = format!("{template}"); + let (template, end) = template.rsplit_once("\n").unwrap(); + assert_eq!(template, format!("[1,2,3]")); + assert!(is_comment_js(end)); + assert!(!end.contains("\n")); +} + +#[test] +fn magic_js_number_array() { + let inserts = ["1", "1"]; + let mut template = SortedTemplate::::from_template("[#]", "#").unwrap(); + for insert in inserts { + template.append(insert.to_string()); + } + let template = format!("{template}"); + let (template, end) = template.rsplit_once("\n").unwrap(); + assert_eq!(template, format!("[1]")); + assert!(is_comment_js(end)); + assert!(!end.contains("\n")); +} + +#[test] +fn round_trip_js() { + let inserts = ["1", "2", "3"]; + let mut template = SortedTemplate::::from_before_after("[", "]"); + for insert in inserts { + template.append(insert.to_string()); + } + let template1 = format!("{template}"); + let mut template = SortedTemplate::::from_str(&template1).unwrap(); + assert_eq!(template1, format!("{template}")); + template.append("4".to_string()); + let template = format!("{template}"); + let (template, end) = template.rsplit_once("\n").unwrap(); + assert_eq!(template, "[1,2,3,4]"); + assert!(is_comment_js(end)); +} + +#[test] +fn round_trip_html() { + let inserts = ["

hello

", "

kind

", "

world

", "

kind

"]; + let before = ""; + let after = ""; + let mut template = SortedTemplate::::from_before_after(before, after); + template.append(inserts[0].to_string()); + template.append(inserts[1].to_string()); + let template = format!("{template}"); + let mut template = SortedTemplate::::from_str(&template).unwrap(); + template.append(inserts[2].to_string()); + let template = format!("{template}"); + let (template, end) = template.rsplit_once("\n").unwrap(); + assert_eq!(template, format!("{before}

hello

kind

world

{after}")); + assert!(is_comment_html(end)); +} + +#[test] +fn blank_js() { + let inserts = ["1", "2", "3"]; + let template = SortedTemplate::::from_before_after("", ""); + let template = format!("{template}"); + let (t, _) = template.rsplit_once("\n").unwrap(); + assert_eq!(t, ""); + let mut template = SortedTemplate::::from_str(&template).unwrap(); + for insert in inserts { + template.append(insert.to_string()); + } + let template1 = format!("{template}"); + let mut template = SortedTemplate::::from_str(&template1).unwrap(); + assert_eq!(template1, format!("{template}")); + template.append("4".to_string()); + let template = format!("{template}"); + let (template, end) = template.rsplit_once("\n").unwrap(); + assert_eq!(template, "1,2,3,4"); + assert!(is_comment_js(end)); +} diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index 8fd56eae37f..60dc142b9ff 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -1,19 +1,41 @@ +//! Rustdoc writes aut two kinds of shared files: +//! - Static files, which are embedded in the rustdoc binary and are written with a +//! filename that includes a hash of their contents. These will always have a new +//! URL if the contents change, so they are safe to cache with the +//! `Cache-Control: immutable` directive. They are written under the static.files/ +//! directory and are written when --emit-type is empty (default) or contains +//! "toolchain-specific". If using the --static-root-path flag, it should point +//! to a URL path prefix where each of these filenames can be fetched. +//! - Invocation specific files. These are generated based on the crate(s) being +//! documented. Their filenames need to be predictable without knowing their +//! contents, so they do not include a hash in their filename and are not safe to +//! cache with `Cache-Control: immutable`. They include the contents of the +//! --resource-suffix flag and are emitted when --emit-type is empty (default) +//! or contains "invocation-specific". + use std::cell::RefCell; -use std::fs::{self, File}; -use std::io::prelude::*; -use std::io::{self, BufReader}; -use std::path::{Component, Path}; +use std::ffi::OsString; +use std::fs::File; +use std::io::{self, BufWriter, Write as _}; +use std::iter::once; +use std::marker::PhantomData; +use std::path::{Component, Path, PathBuf}; use std::rc::{Rc, Weak}; +use std::str::FromStr; +use std::{fmt, fs}; use indexmap::IndexMap; use itertools::Itertools; +use regex::Regex; use rustc_data_structures::flock; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; +use rustc_middle::ty::TyCtxt; use rustc_span::def_id::DefId; use rustc_span::Symbol; +use serde::de::DeserializeOwned; use serde::ser::SerializeSeq; -use serde::{Serialize, Serializer}; +use serde::{Deserialize, Serialize, Serializer}; use super::{collect_paths_for_type, ensure_trailing_slash, Context, RenderMode}; use crate::clean::{Crate, Item, ItemId, ItemKind}; @@ -24,53 +46,83 @@ use crate::formats::cache::Cache; use crate::formats::item_type::ItemType; use crate::formats::Impl; use crate::html::format::Buffer; -use crate::html::render::search_index::SerializedSearchIndex; +use crate::html::layout; +use crate::html::render::ordered_json::{EscapedJson, OrderedJson}; +use crate::html::render::search_index::{build_index, SerializedSearchIndex}; +use crate::html::render::sorted_template::{self, FileFormat, SortedTemplate}; use crate::html::render::{AssocItemLink, ImplRenderingParameters}; -use crate::html::{layout, static_files}; +use crate::html::static_files::{self, suffix_path}; use crate::visit::DocVisitor; use crate::{try_err, try_none}; -/// Rustdoc writes out two kinds of shared files: -/// - Static files, which are embedded in the rustdoc binary and are written with a -/// filename that includes a hash of their contents. These will always have a new -/// URL if the contents change, so they are safe to cache with the -/// `Cache-Control: immutable` directive. They are written under the static.files/ -/// directory and are written when --emit-type is empty (default) or contains -/// "toolchain-specific". If using the --static-root-path flag, it should point -/// to a URL path prefix where each of these filenames can be fetched. -/// - Invocation specific files. These are generated based on the crate(s) being -/// documented. Their filenames need to be predictable without knowing their -/// contents, so they do not include a hash in their filename and are not safe to -/// cache with `Cache-Control: immutable`. They include the contents of the -/// --resource-suffix flag and are emitted when --emit-type is empty (default) -/// or contains "invocation-specific". -pub(super) fn write_shared( +/// Write cross-crate information files, static files, invocation-specific files, etc. to disk +pub(crate) fn write_shared( cx: &mut Context<'_>, krate: &Crate, - search_index: SerializedSearchIndex, - options: &RenderOptions, + opt: &RenderOptions, + tcx: TyCtxt<'_>, ) -> Result<(), Error> { - // Write out the shared files. Note that these are shared among all rustdoc - // docs placed in the output directory, so this needs to be a synchronized - // operation with respect to all other rustdocs running around. + // NOTE(EtomicBomb): I don't think we need sync here because no read-after-write? + Rc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(true); let lock_file = cx.dst.join(".lock"); + // Write shared runs within a flock; disable thread dispatching of IO temporarily. let _lock = try_err!(flock::Lock::new(&lock_file, true, true, true), &lock_file); - // InvocationSpecific resources should always be dynamic. - let write_invocation_specific = |p: &str, make_content: &dyn Fn() -> Result, Error>| { - let content = make_content()?; - if options.emit.is_empty() || options.emit.contains(&EmitType::InvocationSpecific) { - let output_filename = static_files::suffix_path(p, &cx.shared.resource_suffix); - cx.shared.fs.write(cx.dst.join(output_filename), content) - } else { - Ok(()) - } + let SerializedSearchIndex { index, desc } = + build_index(&krate, &mut Rc::get_mut(&mut cx.shared).unwrap().cache, tcx); + write_search_desc(cx, &krate, &desc)?; // does not need to be merged; written unconditionally + + let crate_name = krate.name(cx.tcx()); + let crate_name = crate_name.as_str(); // rand + let crate_name_json = OrderedJson::serialize(crate_name).unwrap(); // "rand" + let external_crates = hack_get_external_crate_names(&cx.dst, &cx.shared.resource_suffix)?; + let info = CrateInfo { + src_files_js: SourcesPart::get(cx, &crate_name_json)?, + search_index_js: SearchIndexPart::get(index, &cx.shared.resource_suffix)?, + all_crates: AllCratesPart::get(crate_name_json.clone(), &cx.shared.resource_suffix)?, + crates_index: CratesIndexPart::get(&crate_name, &external_crates)?, + trait_impl: TraitAliasPart::get(cx, &crate_name_json)?, + type_impl: TypeAliasPart::get(cx, krate, &crate_name_json)?, }; - cx.shared - .fs - .create_dir_all(cx.dst.join("static.files")) - .map_err(|e| PathError::new(e, "static.files"))?; + let crates = vec![info]; // we have info from just one crate. rest will found in out dir + + write_static_files(cx, &opt)?; + let dst = &cx.dst; + if opt.emit.is_empty() || opt.emit.contains(&EmitType::InvocationSpecific) { + if cx.include_sources { + write_rendered_cci::(SourcesPart::blank, dst, &crates)?; + } + write_rendered_cci::(SearchIndexPart::blank, dst, &crates)?; + write_rendered_cci::(AllCratesPart::blank, dst, &crates)?; + } + write_rendered_cci::(TraitAliasPart::blank, dst, &crates)?; + write_rendered_cci::(TypeAliasPart::blank, dst, &crates)?; + match &opt.index_page { + Some(index_page) if opt.enable_index_page => { + let mut md_opts = opt.clone(); + md_opts.output = cx.dst.clone(); + md_opts.external_html = cx.shared.layout.external_html.clone(); + try_err!( + crate::markdown::render(&index_page, md_opts, cx.shared.edition()), + &index_page + ); + } + None if opt.enable_index_page => { + write_rendered_cci::(|| CratesIndexPart::blank(cx), dst, &crates)?; + } + _ => {} // they don't want an index page + } + + Rc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(false); + Ok(()) +} + +/// Writes the static files, the style files, and the css extensions +fn write_static_files(cx: &mut Context<'_>, options: &RenderOptions) -> Result<(), Error> { + let static_dir = cx.dst.join("static.files"); + + cx.shared.fs.create_dir_all(&static_dir).map_err(|e| PathError::new(e, "static.files"))?; // Handle added third-party themes for entry in &cx.shared.style_files { @@ -97,680 +149,792 @@ pub(super) fn write_shared( } if options.emit.is_empty() || options.emit.contains(&EmitType::Toolchain) { - let static_dir = cx.dst.join(Path::new("static.files")); static_files::for_each(|f: &static_files::StaticFile| { let filename = static_dir.join(f.output_filename()); cx.shared.fs.write(filename, f.minified()) })?; } - /// Read a file and return all lines that match the `"{crate}":{data},` format, - /// and return a tuple `(Vec, Vec)`. - /// - /// This forms the payload of files that look like this: - /// - /// ```javascript - /// var data = { - /// "{crate1}":{data}, - /// "{crate2}":{data} - /// }; - /// use_data(data); - /// ``` - /// - /// The file needs to be formatted so that *only crate data lines start with `"`*. - fn collect(path: &Path, krate: &str) -> io::Result<(Vec, Vec)> { - let mut ret = Vec::new(); - let mut krates = Vec::new(); + Ok(()) +} - if path.exists() { - let prefix = format!("\"{krate}\""); - for line in BufReader::new(File::open(path)?).lines() { - let line = line?; - if !line.starts_with('"') { - continue; - } - if line.starts_with(&prefix) { - continue; - } - if line.ends_with(',') { - ret.push(line[..line.len() - 1].to_string()); - } else { - // No comma (it's the case for the last added crate line) - ret.push(line.to_string()); - } - krates.push( - line.split('"') - .find(|s| !s.is_empty()) - .map(|s| s.to_owned()) - .unwrap_or_else(String::new), - ); - } - } - Ok((ret, krates)) +/// Write the search description shards to disk +fn write_search_desc( + cx: &mut Context<'_>, + krate: &Crate, + search_desc: &[(usize, String)], +) -> Result<(), Error> { + let crate_name = krate.name(cx.tcx()).to_string(); + let encoded_crate_name = OrderedJson::serialize(&crate_name).unwrap(); + let path = PathBuf::from_iter([&cx.dst, Path::new("search.desc"), Path::new(&crate_name)]); + if path.exists() { + try_err!(fs::remove_dir_all(&path), &path); } - - /// Read a file and return all lines that match the "{crate}":{data},\ format, - /// and return a tuple `(Vec, Vec)`. - /// - /// This forms the payload of files that look like this: - /// - /// ```javascript - /// var data = JSON.parse('{\ - /// "{crate1}":{data},\ - /// "{crate2}":{data}\ - /// }'); - /// use_data(data); - /// ``` - /// - /// The file needs to be formatted so that *only crate data lines start with `"`*. - fn collect_json(path: &Path, krate: &str) -> io::Result<(Vec, Vec)> { - let mut ret = Vec::new(); - let mut krates = Vec::new(); - - if path.exists() { - let prefix = format!("[\"{krate}\""); - for line in BufReader::new(File::open(path)?).lines() { - let line = line?; - if !line.starts_with("[\"") { - continue; - } - if line.starts_with(&prefix) { - continue; - } - if line.ends_with("],\\") { - ret.push(line[..line.len() - 2].to_string()); - } else { - // Ends with "\\" (it's the case for the last added crate line) - ret.push(line[..line.len() - 1].to_string()); - } - krates.push( - line[1..] // We skip the `[` parent at the beginning of the line. - .split('"') - .find(|s| !s.is_empty()) - .map(|s| s.to_owned()) - .unwrap_or_else(String::new), - ); - } - } - Ok((ret, krates)) - } - - use std::ffi::OsString; - - #[derive(Debug, Default)] - struct Hierarchy { - parent: Weak, - elem: OsString, - children: RefCell>>, - elems: RefCell>, - } - - impl Hierarchy { - fn with_parent(elem: OsString, parent: &Rc) -> Self { - Self { elem, parent: Rc::downgrade(parent), ..Self::default() } - } - - fn to_json_string(&self) -> String { - let borrow = self.children.borrow(); - let mut subs: Vec<_> = borrow.values().collect(); - subs.sort_unstable_by(|a, b| a.elem.cmp(&b.elem)); - let mut files = self - .elems - .borrow() - .iter() - .map(|s| format!("\"{}\"", s.to_str().expect("invalid osstring conversion"))) - .collect::>(); - files.sort_unstable(); - let subs = subs.iter().map(|s| s.to_json_string()).collect::>().join(","); - let dirs = if subs.is_empty() && files.is_empty() { - String::new() - } else { - format!(",[{subs}]") - }; - let files = files.join(","); - let files = if files.is_empty() { String::new() } else { format!(",[{files}]") }; - format!( - "[\"{name}\"{dirs}{files}]", - name = self.elem.to_str().expect("invalid osstring conversion"), - dirs = dirs, - files = files - ) - } - - fn add_path(self: &Rc, path: &Path) { - let mut h = Rc::clone(&self); - let mut elems = path - .components() - .filter_map(|s| match s { - Component::Normal(s) => Some(s.to_owned()), - Component::ParentDir => Some(OsString::from("..")), - _ => None, - }) - .peekable(); - loop { - let cur_elem = elems.next().expect("empty file path"); - if cur_elem == ".." { - if let Some(parent) = h.parent.upgrade() { - h = parent; - } - continue; - } - if elems.peek().is_none() { - h.elems.borrow_mut().insert(cur_elem); - break; - } else { - let entry = Rc::clone( - h.children - .borrow_mut() - .entry(cur_elem.clone()) - .or_insert_with(|| Rc::new(Self::with_parent(cur_elem, &h))), - ); - h = entry; - } - } - } - } - - if cx.include_sources { - let hierarchy = Rc::new(Hierarchy::default()); - for source in cx - .shared - .local_sources - .iter() - .filter_map(|p| p.0.strip_prefix(&cx.shared.src_root).ok()) - { - hierarchy.add_path(source); - } - let hierarchy = Rc::try_unwrap(hierarchy).unwrap(); - let dst = cx.dst.join(&format!("src-files{}.js", cx.shared.resource_suffix)); - let make_sources = || { - let (mut all_sources, _krates) = - try_err!(collect_json(&dst, krate.name(cx.tcx()).as_str()), &dst); - all_sources.push(format!( - r#"["{}",{}]"#, - &krate.name(cx.tcx()), - hierarchy - .to_json_string() - // All these `replace` calls are because we have to go through JS string for JSON content. - .replace('\\', r"\\") - .replace('\'', r"\'") - // We need to escape double quotes for the JSON. - .replace("\\\"", "\\\\\"") - )); - all_sources.sort(); - // This needs to be `var`, not `const`. - // This variable needs declared in the current global scope so that if - // src-script.js loads first, it can pick it up. - let mut v = String::from("var srcIndex = new Map(JSON.parse('[\\\n"); - v.push_str(&all_sources.join(",\\\n")); - v.push_str("\\\n]'));\ncreateSrcSidebar();\n"); - Ok(v.into_bytes()) - }; - write_invocation_specific("src-files.js", &make_sources)?; - } - - // Update the search index and crate list. - let dst = cx.dst.join(&format!("search-index{}.js", cx.shared.resource_suffix)); - let (mut all_indexes, mut krates) = - try_err!(collect_json(&dst, krate.name(cx.tcx()).as_str()), &dst); - all_indexes.push(search_index.index); - krates.push(krate.name(cx.tcx()).to_string()); - krates.sort(); - - // Sort the indexes by crate so the file will be generated identically even - // with rustdoc running in parallel. - all_indexes.sort(); - write_invocation_specific("search-index.js", &|| { - // This needs to be `var`, not `const`. - // This variable needs declared in the current global scope so that if - // search.js loads first, it can pick it up. - let mut v = String::from("var searchIndex = new Map(JSON.parse('[\\\n"); - v.push_str(&all_indexes.join(",\\\n")); - v.push_str( - r#"\ -]')); -if (typeof exports !== 'undefined') exports.searchIndex = searchIndex; -else if (window.initSearch) window.initSearch(searchIndex); -"#, - ); - Ok(v.into_bytes()) - })?; - - let search_desc_dir = cx.dst.join(format!("search.desc/{krate}", krate = krate.name(cx.tcx()))); - if Path::new(&search_desc_dir).exists() { - try_err!(std::fs::remove_dir_all(&search_desc_dir), &search_desc_dir); - } - try_err!(std::fs::create_dir_all(&search_desc_dir), &search_desc_dir); - let kratename = krate.name(cx.tcx()).to_string(); - for (i, (_, data)) in search_index.desc.into_iter().enumerate() { - let output_filename = static_files::suffix_path( - &format!("{kratename}-desc-{i}-.js"), + for (i, (_, part)) in search_desc.iter().enumerate() { + let filename = static_files::suffix_path( + &format!("{crate_name}-desc-{i}-.js"), &cx.shared.resource_suffix, ); - let path = search_desc_dir.join(output_filename); - try_err!( - std::fs::write( - &path, - &format!( - r##"searchState.loadedDescShard({kratename}, {i}, {data})"##, - kratename = serde_json::to_string(&kratename).unwrap(), - data = serde_json::to_string(&data).unwrap(), - ) - .into_bytes() - ), - &path - ); - } - - write_invocation_specific("crates.js", &|| { - let krates = krates.iter().map(|k| format!("\"{k}\"")).join(","); - Ok(format!("window.ALL_CRATES = [{krates}];").into_bytes()) - })?; - - if options.enable_index_page { - if let Some(index_page) = options.index_page.clone() { - let mut md_opts = options.clone(); - md_opts.output = cx.dst.clone(); - md_opts.external_html = (*cx.shared).layout.external_html.clone(); - - crate::markdown::render(&index_page, md_opts, cx.shared.edition()) - .map_err(|e| Error::new(e, &index_page))?; - } else { - let shared = Rc::clone(&cx.shared); - let dst = cx.dst.join("index.html"); - let page = layout::Page { - title: "Index of crates", - css_class: "mod sys", - root_path: "./", - static_root_path: shared.static_root_path.as_deref(), - description: "List of crates", - resource_suffix: &shared.resource_suffix, - rust_logo: true, - }; - - let content = format!( - "

List of all crates

    {}
", - krates.iter().format_with("", |k, f| { - f(&format_args!( - "
  • {k}
  • ", - trailing_slash = ensure_trailing_slash(k), - )) - }) - ); - let v = layout::render(&shared.layout, &page, "", content, &shared.style_files); - shared.fs.write(dst, v)?; - } - } - - let cloned_shared = Rc::clone(&cx.shared); - let cache = &cloned_shared.cache; - - // Collect the list of aliased types and their aliases. - // - // - // The clean AST has type aliases that point at their types, but - // this visitor works to reverse that: `aliased_types` is a map - // from target to the aliases that reference it, and each one - // will generate one file. - struct TypeImplCollector<'cx, 'cache> { - // Map from DefId-of-aliased-type to its data. - aliased_types: IndexMap>, - visited_aliases: FxHashSet, - cache: &'cache Cache, - cx: &'cache mut Context<'cx>, - } - // Data for an aliased type. - // - // In the final file, the format will be roughly: - // - // ```json - // // type.impl/CRATE/TYPENAME.js - // JSONP( - // "CRATE": [ - // ["IMPL1 HTML", "ALIAS1", "ALIAS2", ...], - // ["IMPL2 HTML", "ALIAS3", "ALIAS4", ...], - // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ struct AliasedType - // ... - // ] - // ) - // ``` - struct AliasedType<'cache> { - // This is used to generate the actual filename of this aliased type. - target_fqp: &'cache [Symbol], - target_type: ItemType, - // This is the data stored inside the file. - // ItemId is used to deduplicate impls. - impl_: IndexMap>, - } - // The `impl_` contains data that's used to figure out if an alias will work, - // and to generate the HTML at the end. - // - // The `type_aliases` list is built up with each type alias that matches. - struct AliasedTypeImpl<'cache> { - impl_: &'cache Impl, - type_aliases: Vec<(&'cache [Symbol], Item)>, - } - impl<'cx, 'cache> DocVisitor for TypeImplCollector<'cx, 'cache> { - fn visit_item(&mut self, it: &Item) { - self.visit_item_recur(it); - let cache = self.cache; - let ItemKind::TypeAliasItem(ref t) = *it.kind else { return }; - let Some(self_did) = it.item_id.as_def_id() else { return }; - if !self.visited_aliases.insert(self_did) { - return; - } - let Some(target_did) = t.type_.def_id(cache) else { return }; - let get_extern = { || cache.external_paths.get(&target_did) }; - let Some(&(ref target_fqp, target_type)) = - cache.paths.get(&target_did).or_else(get_extern) - else { - return; - }; - let aliased_type = self.aliased_types.entry(target_did).or_insert_with(|| { - let impl_ = cache - .impls - .get(&target_did) - .map(|v| &v[..]) - .unwrap_or_default() - .iter() - .map(|impl_| { - ( - impl_.impl_item.item_id, - AliasedTypeImpl { impl_, type_aliases: Vec::new() }, - ) - }) - .collect(); - AliasedType { target_fqp: &target_fqp[..], target_type, impl_ } - }); - let get_local = { || cache.paths.get(&self_did).map(|(p, _)| p) }; - let Some(self_fqp) = cache.exact_paths.get(&self_did).or_else(get_local) else { - return; - }; - let aliased_ty = self.cx.tcx().type_of(self_did).skip_binder(); - // Exclude impls that are directly on this type. They're already in the HTML. - // Some inlining scenarios can cause there to be two versions of the same - // impl: one on the type alias and one on the underlying target type. - let mut seen_impls: FxHashSet = cache - .impls - .get(&self_did) - .map(|s| &s[..]) - .unwrap_or_default() - .iter() - .map(|i| i.impl_item.item_id) - .collect(); - for (impl_item_id, aliased_type_impl) in &mut aliased_type.impl_ { - // Only include this impl if it actually unifies with this alias. - // Synthetic impls are not included; those are also included in the HTML. - // - // FIXME(lazy_type_alias): Once the feature is complete or stable, rewrite this - // to use type unification. - // Be aware of `tests/rustdoc/type-alias/deeply-nested-112515.rs` which might regress. - let Some(impl_did) = impl_item_id.as_def_id() else { continue }; - let for_ty = self.cx.tcx().type_of(impl_did).skip_binder(); - let reject_cx = DeepRejectCtxt::new(self.cx.tcx(), TreatParams::AsCandidateKey); - if !reject_cx.types_may_unify(aliased_ty, for_ty) { - continue; - } - // Avoid duplicates - if !seen_impls.insert(*impl_item_id) { - continue; - } - // This impl was not found in the set of rejected impls - aliased_type_impl.type_aliases.push((&self_fqp[..], it.clone())); - } - } - } - let mut type_impl_collector = TypeImplCollector { - aliased_types: IndexMap::default(), - visited_aliases: FxHashSet::default(), - cache, - cx, - }; - DocVisitor::visit_crate(&mut type_impl_collector, &krate); - // Final serialized form of the alias impl - struct AliasSerializableImpl { - text: String, - trait_: Option, - aliases: Vec, - } - impl Serialize for AliasSerializableImpl { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - let mut seq = serializer.serialize_seq(None)?; - seq.serialize_element(&self.text)?; - if let Some(trait_) = &self.trait_ { - seq.serialize_element(trait_)?; - } else { - seq.serialize_element(&0)?; - } - for type_ in &self.aliases { - seq.serialize_element(type_)?; - } - seq.end() - } - } - let cx = type_impl_collector.cx; - let dst = cx.dst.join("type.impl"); - let aliased_types = type_impl_collector.aliased_types; - for aliased_type in aliased_types.values() { - let impls = aliased_type - .impl_ - .values() - .flat_map(|AliasedTypeImpl { impl_, type_aliases }| { - let mut ret = Vec::new(); - let trait_ = impl_ - .inner_impl() - .trait_ - .as_ref() - .map(|trait_| format!("{:#}", trait_.print(cx))); - // render_impl will filter out "impossible-to-call" methods - // to make that functionality work here, it needs to be called with - // each type alias, and if it gives a different result, split the impl - for &(type_alias_fqp, ref type_alias_item) in type_aliases { - let mut buf = Buffer::html(); - cx.id_map = Default::default(); - cx.deref_id_map = Default::default(); - let target_did = impl_ - .inner_impl() - .trait_ - .as_ref() - .map(|trait_| trait_.def_id()) - .or_else(|| impl_.inner_impl().for_.def_id(cache)); - let provided_methods; - let assoc_link = if let Some(target_did) = target_did { - provided_methods = impl_.inner_impl().provided_trait_methods(cx.tcx()); - AssocItemLink::GotoSource(ItemId::DefId(target_did), &provided_methods) - } else { - AssocItemLink::Anchor(None) - }; - super::render_impl( - &mut buf, - cx, - *impl_, - &type_alias_item, - assoc_link, - RenderMode::Normal, - None, - &[], - ImplRenderingParameters { - show_def_docs: true, - show_default_items: true, - show_non_assoc_items: true, - toggle_open_by_default: true, - }, - ); - let text = buf.into_inner(); - let type_alias_fqp = (*type_alias_fqp).iter().join("::"); - if Some(&text) == ret.last().map(|s: &AliasSerializableImpl| &s.text) { - ret.last_mut() - .expect("already established that ret.last() is Some()") - .aliases - .push(type_alias_fqp); - } else { - ret.push(AliasSerializableImpl { - text, - trait_: trait_.clone(), - aliases: vec![type_alias_fqp], - }) - } - } - ret - }) - .collect::>(); - - // FIXME: this fixes only rustdoc part of instability of trait impls - // for js files, see #120371 - // Manually collect to string and sort to make list not depend on order - let mut impls = impls - .iter() - .map(|i| serde_json::to_string(i).expect("failed serde conversion")) - .collect::>(); - impls.sort(); - - let impls = format!(r#""{}":[{}]"#, krate.name(cx.tcx()), impls.join(",")); - - let mut mydst = dst.clone(); - for part in &aliased_type.target_fqp[..aliased_type.target_fqp.len() - 1] { - mydst.push(part.to_string()); - } - cx.shared.ensure_dir(&mydst)?; - let aliased_item_type = aliased_type.target_type; - mydst.push(&format!( - "{aliased_item_type}.{}.js", - aliased_type.target_fqp[aliased_type.target_fqp.len() - 1] - )); - - let (mut all_impls, _) = try_err!(collect(&mydst, krate.name(cx.tcx()).as_str()), &mydst); - all_impls.push(impls); - // Sort the implementors by crate so the file will be generated - // identically even with rustdoc running in parallel. - all_impls.sort(); - - let mut v = String::from("(function() {var type_impls = {\n"); - v.push_str(&all_impls.join(",\n")); - v.push_str("\n};"); - v.push_str( - "if (window.register_type_impls) {\ - window.register_type_impls(type_impls);\ - } else {\ - window.pending_type_impls = type_impls;\ - }", - ); - v.push_str("})()"); - cx.shared.fs.write(mydst, v)?; - } - - // Update the list of all implementors for traits - // - let dst = cx.dst.join("trait.impl"); - for (&did, imps) in &cache.implementors { - // Private modules can leak through to this phase of rustdoc, which - // could contain implementations for otherwise private types. In some - // rare cases we could find an implementation for an item which wasn't - // indexed, so we just skip this step in that case. - // - // FIXME: this is a vague explanation for why this can't be a `get`, in - // theory it should be... - let (remote_path, remote_item_type) = match cache.exact_paths.get(&did) { - Some(p) => match cache.paths.get(&did).or_else(|| cache.external_paths.get(&did)) { - Some((_, t)) => (p, t), - None => continue, - }, - None => match cache.external_paths.get(&did) { - Some((p, t)) => (p, t), - None => continue, - }, - }; - - struct Implementor { - text: String, - synthetic: bool, - types: Vec, - } - - impl Serialize for Implementor { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - let mut seq = serializer.serialize_seq(None)?; - seq.serialize_element(&self.text)?; - if self.synthetic { - seq.serialize_element(&1)?; - seq.serialize_element(&self.types)?; - } - seq.end() - } - } - - let implementors = imps - .iter() - .filter_map(|imp| { - // If the trait and implementation are in the same crate, then - // there's no need to emit information about it (there's inlining - // going on). If they're in different crates then the crate defining - // the trait will be interested in our implementation. - // - // If the implementation is from another crate then that crate - // should add it. - if imp.impl_item.item_id.krate() == did.krate || !imp.impl_item.item_id.is_local() { - None - } else { - Some(Implementor { - text: imp.inner_impl().print(false, cx).to_string(), - synthetic: imp.inner_impl().kind.is_auto(), - types: collect_paths_for_type(imp.inner_impl().for_.clone(), cache), - }) - } - }) - .collect::>(); - - // Only create a js file if we have impls to add to it. If the trait is - // documented locally though we always create the file to avoid dead - // links. - if implementors.is_empty() && !cache.paths.contains_key(&did) { - continue; - } - - // FIXME: this fixes only rustdoc part of instability of trait impls - // for js files, see #120371 - // Manually collect to string and sort to make list not depend on order - let mut implementors = implementors - .iter() - .map(|i| serde_json::to_string(i).expect("failed serde conversion")) - .collect::>(); - implementors.sort(); - - let implementors = format!(r#""{}":[{}]"#, krate.name(cx.tcx()), implementors.join(",")); - - let mut mydst = dst.clone(); - for part in &remote_path[..remote_path.len() - 1] { - mydst.push(part.to_string()); - } - cx.shared.ensure_dir(&mydst)?; - mydst.push(&format!("{remote_item_type}.{}.js", remote_path[remote_path.len() - 1])); - - let (mut all_implementors, _) = - try_err!(collect(&mydst, krate.name(cx.tcx()).as_str()), &mydst); - all_implementors.push(implementors); - // Sort the implementors by crate so the file will be generated - // identically even with rustdoc running in parallel. - all_implementors.sort(); - - let mut v = String::from("(function() {var implementors = {\n"); - v.push_str(&all_implementors.join(",\n")); - v.push_str("\n};"); - v.push_str( - "if (window.register_implementors) {\ - window.register_implementors(implementors);\ - } else {\ - window.pending_implementors = implementors;\ - }", - ); - v.push_str("})()"); - cx.shared.fs.write(mydst, v)?; + let path = path.join(filename); + let part = OrderedJson::serialize(&part).unwrap(); + let part = format!("searchState.loadedDescShard({encoded_crate_name}, {i}, {part})"); + create_parents(&path)?; + try_err!(fs::write(&path, part), &path); } Ok(()) } + +/// Contains pre-rendered contents to insert into the CCI template +#[derive(Serialize, Deserialize, Clone, Debug)] +struct CrateInfo { + src_files_js: PartsAndLocations, + search_index_js: PartsAndLocations, + all_crates: PartsAndLocations, + crates_index: PartsAndLocations, + trait_impl: PartsAndLocations, + type_impl: PartsAndLocations, +} + +/// Paths (relative to the doc root) and their pre-merge contents +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(transparent)] +struct PartsAndLocations

    { + parts: Vec<(PathBuf, P)>, +} + +impl

    Default for PartsAndLocations

    { + fn default() -> Self { + Self { parts: Vec::default() } + } +} + +impl PartsAndLocations> { + fn push(&mut self, path: PathBuf, item: U) { + self.parts.push((path, Part { _artifact: PhantomData, item })); + } + + /// Singleton part, one file + fn with(path: PathBuf, part: U) -> Self { + let mut ret = Self::default(); + ret.push(path, part); + ret + } +} + +/// A piece of one of the shared artifacts for documentation (search index, sources, alias list, etc.) +/// +/// Merged at a user specified time and written to the `doc/` directory +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(transparent)] +struct Part { + #[serde(skip)] + _artifact: PhantomData, + item: U, +} + +impl fmt::Display for Part { + /// Writes serialized JSON + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.item) + } +} + +/// Wrapper trait for `Part` +trait CciPart: Sized + fmt::Display + DeserializeOwned + 'static { + /// Identifies the file format of the cross-crate information + type FileFormat: sorted_template::FileFormat; + fn from_crate_info(crate_info: &CrateInfo) -> &PartsAndLocations; +} + +#[derive(Serialize, Deserialize, Clone, Default, Debug)] +struct SearchIndex; +type SearchIndexPart = Part; +impl CciPart for SearchIndexPart { + type FileFormat = sorted_template::Js; + fn from_crate_info(crate_info: &CrateInfo) -> &PartsAndLocations { + &crate_info.search_index_js + } +} + +impl SearchIndexPart { + fn blank() -> SortedTemplate<::FileFormat> { + SortedTemplate::from_before_after( + r"var searchIndex = new Map(JSON.parse('[", + r"]')); +if (typeof exports !== 'undefined') exports.searchIndex = searchIndex; +else if (window.initSearch) window.initSearch(searchIndex);", + ) + } + + fn get( + search_index: OrderedJson, + resource_suffix: &str, + ) -> Result, Error> { + let path = suffix_path("search-index.js", resource_suffix); + let search_index = EscapedJson::from(search_index); + Ok(PartsAndLocations::with(path, search_index)) + } +} + +#[derive(Serialize, Deserialize, Clone, Default, Debug)] +struct AllCrates; +type AllCratesPart = Part; +impl CciPart for AllCratesPart { + type FileFormat = sorted_template::Js; + fn from_crate_info(crate_info: &CrateInfo) -> &PartsAndLocations { + &crate_info.all_crates + } +} + +impl AllCratesPart { + fn blank() -> SortedTemplate<::FileFormat> { + SortedTemplate::from_before_after("window.ALL_CRATES = [", "];") + } + + fn get( + crate_name_json: OrderedJson, + resource_suffix: &str, + ) -> Result, Error> { + // external hack_get_external_crate_names not needed here, because + // there's no way that we write the search index but not crates.js + let path = suffix_path("crates.js", resource_suffix); + Ok(PartsAndLocations::with(path, crate_name_json)) + } +} + +/// Reads `crates.js`, which seems like the best +/// place to obtain the list of externally documented crates if the index +/// page was disabled when documenting the deps. +/// +/// This is to match the current behavior of rustdoc, which allows you to get all crates +/// on the index page, even if --enable-index-page is only passed to the last crate. +fn hack_get_external_crate_names( + doc_root: &Path, + resource_suffix: &str, +) -> Result, Error> { + let path = doc_root.join(suffix_path("crates.js", resource_suffix)); + let Ok(content) = fs::read_to_string(&path) else { + // they didn't emit invocation specific, so we just say there were no crates + return Ok(Vec::default()); + }; + // this is only run once so it's fine not to cache it + // !dot_matches_new_line: all crates on same line. greedy: match last bracket + let regex = Regex::new(r"\[.*\]").unwrap(); + let Some(content) = regex.find(&content) else { + return Err(Error::new("could not find crates list in crates.js", path)); + }; + let content: Vec = try_err!(serde_json::from_str(content.as_str()), &path); + Ok(content) +} + +#[derive(Serialize, Deserialize, Clone, Default, Debug)] +struct CratesIndex; +type CratesIndexPart = Part; +impl CciPart for CratesIndexPart { + type FileFormat = sorted_template::Html; + fn from_crate_info(crate_info: &CrateInfo) -> &PartsAndLocations { + &crate_info.crates_index + } +} + +impl CratesIndexPart { + fn blank(cx: &Context<'_>) -> SortedTemplate<::FileFormat> { + let page = layout::Page { + title: "Index of crates", + css_class: "mod sys", + root_path: "./", + static_root_path: cx.shared.static_root_path.as_deref(), + description: "List of crates", + resource_suffix: &cx.shared.resource_suffix, + rust_logo: true, + }; + let layout = &cx.shared.layout; + let style_files = &cx.shared.style_files; + const DELIMITER: &str = "\u{FFFC}"; // users are being naughty if they have this + let content = + format!("

    List of all crates

      {DELIMITER}
    "); + let template = layout::render(layout, &page, "", content, &style_files); + match SortedTemplate::from_template(&template, DELIMITER) { + Ok(template) => template, + Err(e) => panic!( + "Object Replacement Character (U+FFFC) should not appear in the --index-page: {e}" + ), + } + } + + /// Might return parts that are duplicate with ones in prexisting index.html + fn get(crate_name: &str, external_crates: &[String]) -> Result, Error> { + let mut ret = PartsAndLocations::default(); + let path = PathBuf::from("index.html"); + for crate_name in external_crates.iter().map(|s| s.as_str()).chain(once(crate_name)) { + let part = format!( + "
  • {crate_name}
  • ", + trailing_slash = ensure_trailing_slash(crate_name), + ); + ret.push(path.clone(), part); + } + Ok(ret) + } +} + +#[derive(Serialize, Deserialize, Clone, Default, Debug)] +struct Sources; +type SourcesPart = Part; +impl CciPart for SourcesPart { + type FileFormat = sorted_template::Js; + fn from_crate_info(crate_info: &CrateInfo) -> &PartsAndLocations { + &crate_info.src_files_js + } +} + +impl SourcesPart { + fn blank() -> SortedTemplate<::FileFormat> { + // This needs to be `var`, not `const`. + // This variable needs declared in the current global scope so that if + // src-script.js loads first, it can pick it up. + SortedTemplate::from_before_after( + r"var srcIndex = new Map(JSON.parse('[", + r"]')); +createSrcSidebar();", + ) + } + + fn get(cx: &Context<'_>, crate_name: &OrderedJson) -> Result, Error> { + let hierarchy = Rc::new(Hierarchy::default()); + cx.shared + .local_sources + .iter() + .filter_map(|p| p.0.strip_prefix(&cx.shared.src_root).ok()) + .for_each(|source| hierarchy.add_path(source)); + let path = suffix_path("src-files.js", &cx.shared.resource_suffix); + let hierarchy = hierarchy.to_json_string(); + let part = OrderedJson::array_unsorted([crate_name, &hierarchy]); + let part = EscapedJson::from(part); + Ok(PartsAndLocations::with(path, part)) + } +} + +/// Source files directory tree +#[derive(Debug, Default)] +struct Hierarchy { + parent: Weak, + elem: OsString, + children: RefCell>>, + elems: RefCell>, +} + +impl Hierarchy { + fn with_parent(elem: OsString, parent: &Rc) -> Self { + Self { elem, parent: Rc::downgrade(parent), ..Self::default() } + } + + fn to_json_string(&self) -> OrderedJson { + let subs = self.children.borrow(); + let files = self.elems.borrow(); + let name = OrderedJson::serialize(self.elem.to_str().expect("invalid osstring conversion")) + .unwrap(); + let mut out = Vec::from([name]); + if !subs.is_empty() || !files.is_empty() { + let subs = subs.iter().map(|(_, s)| s.to_json_string()); + out.push(OrderedJson::array_sorted(subs)); + } + if !files.is_empty() { + let files = files + .iter() + .map(|s| OrderedJson::serialize(s.to_str().expect("invalid osstring")).unwrap()); + out.push(OrderedJson::array_sorted(files)); + } + OrderedJson::array_unsorted(out) + } + + fn add_path(self: &Rc, path: &Path) { + let mut h = Rc::clone(&self); + let mut elems = path + .components() + .filter_map(|s| match s { + Component::Normal(s) => Some(s.to_owned()), + Component::ParentDir => Some(OsString::from("..")), + _ => None, + }) + .peekable(); + loop { + let cur_elem = elems.next().expect("empty file path"); + if cur_elem == ".." { + if let Some(parent) = h.parent.upgrade() { + h = parent; + } + continue; + } + if elems.peek().is_none() { + h.elems.borrow_mut().insert(cur_elem); + break; + } else { + let entry = Rc::clone( + h.children + .borrow_mut() + .entry(cur_elem.clone()) + .or_insert_with(|| Rc::new(Self::with_parent(cur_elem, &h))), + ); + h = entry; + } + } + } +} + +#[derive(Serialize, Deserialize, Clone, Default, Debug)] +struct TypeAlias; +type TypeAliasPart = Part; +impl CciPart for TypeAliasPart { + type FileFormat = sorted_template::Js; + fn from_crate_info(crate_info: &CrateInfo) -> &PartsAndLocations { + &crate_info.type_impl + } +} + +impl TypeAliasPart { + fn blank() -> SortedTemplate<::FileFormat> { + SortedTemplate::from_before_after( + r"(function() { + var type_impls = Object.fromEntries([", + r"]); + if (window.register_type_impls) { + window.register_type_impls(type_impls); + } else { + window.pending_type_impls = type_impls; + } +})()", + ) + } + + fn get( + cx: &mut Context<'_>, + krate: &Crate, + crate_name_json: &OrderedJson, + ) -> Result, Error> { + let cache = &Rc::clone(&cx.shared).cache; + let mut path_parts = PartsAndLocations::default(); + + let mut type_impl_collector = TypeImplCollector { + aliased_types: IndexMap::default(), + visited_aliases: FxHashSet::default(), + cache, + cx, + }; + DocVisitor::visit_crate(&mut type_impl_collector, &krate); + let cx = type_impl_collector.cx; + let aliased_types = type_impl_collector.aliased_types; + for aliased_type in aliased_types.values() { + let impls = aliased_type + .impl_ + .values() + .flat_map(|AliasedTypeImpl { impl_, type_aliases }| { + let mut ret = Vec::new(); + let trait_ = impl_ + .inner_impl() + .trait_ + .as_ref() + .map(|trait_| format!("{:#}", trait_.print(cx))); + // render_impl will filter out "impossible-to-call" methods + // to make that functionality work here, it needs to be called with + // each type alias, and if it gives a different result, split the impl + for &(type_alias_fqp, ref type_alias_item) in type_aliases { + let mut buf = Buffer::html(); + cx.id_map = Default::default(); + cx.deref_id_map = Default::default(); + let target_did = impl_ + .inner_impl() + .trait_ + .as_ref() + .map(|trait_| trait_.def_id()) + .or_else(|| impl_.inner_impl().for_.def_id(cache)); + let provided_methods; + let assoc_link = if let Some(target_did) = target_did { + provided_methods = impl_.inner_impl().provided_trait_methods(cx.tcx()); + AssocItemLink::GotoSource(ItemId::DefId(target_did), &provided_methods) + } else { + AssocItemLink::Anchor(None) + }; + super::render_impl( + &mut buf, + cx, + *impl_, + &type_alias_item, + assoc_link, + RenderMode::Normal, + None, + &[], + ImplRenderingParameters { + show_def_docs: true, + show_default_items: true, + show_non_assoc_items: true, + toggle_open_by_default: true, + }, + ); + let text = buf.into_inner(); + let type_alias_fqp = (*type_alias_fqp).iter().join("::"); + if Some(&text) == ret.last().map(|s: &AliasSerializableImpl| &s.text) { + ret.last_mut() + .expect("already established that ret.last() is Some()") + .aliases + .push(type_alias_fqp); + } else { + ret.push(AliasSerializableImpl { + text, + trait_: trait_.clone(), + aliases: vec![type_alias_fqp], + }) + } + } + ret + }) + .collect::>(); + + let mut path = PathBuf::from("type.impl"); + for component in &aliased_type.target_fqp[..aliased_type.target_fqp.len() - 1] { + path.push(component.as_str()); + } + let aliased_item_type = aliased_type.target_type; + path.push(&format!( + "{aliased_item_type}.{}.js", + aliased_type.target_fqp[aliased_type.target_fqp.len() - 1] + )); + + let part = OrderedJson::array_sorted( + impls.iter().map(OrderedJson::serialize).collect::, _>>().unwrap(), + ); + path_parts.push(path, OrderedJson::array_unsorted([crate_name_json, &part])); + } + Ok(path_parts) + } +} + +#[derive(Serialize, Deserialize, Clone, Default, Debug)] +struct TraitAlias; +type TraitAliasPart = Part; +impl CciPart for TraitAliasPart { + type FileFormat = sorted_template::Js; + fn from_crate_info(crate_info: &CrateInfo) -> &PartsAndLocations { + &crate_info.trait_impl + } +} + +impl TraitAliasPart { + fn blank() -> SortedTemplate<::FileFormat> { + SortedTemplate::from_before_after( + r"(function() { + var implementors = Object.fromEntries([", + r"]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})()", + ) + } + + fn get( + cx: &mut Context<'_>, + crate_name_json: &OrderedJson, + ) -> Result, Error> { + let cache = &cx.shared.cache; + let mut path_parts = PartsAndLocations::default(); + // Update the list of all implementors for traits + // + for (&did, imps) in &cache.implementors { + // Private modules can leak through to this phase of rustdoc, which + // could contain implementations for otherwise private types. In some + // rare cases we could find an implementation for an item which wasn't + // indexed, so we just skip this step in that case. + // + // FIXME: this is a vague explanation for why this can't be a `get`, in + // theory it should be... + let (remote_path, remote_item_type) = match cache.exact_paths.get(&did) { + Some(p) => match cache.paths.get(&did).or_else(|| cache.external_paths.get(&did)) { + Some((_, t)) => (p, t), + None => continue, + }, + None => match cache.external_paths.get(&did) { + Some((p, t)) => (p, t), + None => continue, + }, + }; + + let implementors = imps + .iter() + .filter_map(|imp| { + // If the trait and implementation are in the same crate, then + // there's no need to emit information about it (there's inlining + // going on). If they're in different crates then the crate defining + // the trait will be interested in our implementation. + // + // If the implementation is from another crate then that crate + // should add it. + if imp.impl_item.item_id.krate() == did.krate + || !imp.impl_item.item_id.is_local() + { + None + } else { + Some(Implementor { + text: imp.inner_impl().print(false, cx).to_string(), + synthetic: imp.inner_impl().kind.is_auto(), + types: collect_paths_for_type(imp.inner_impl().for_.clone(), cache), + }) + } + }) + .collect::>(); + + // Only create a js file if we have impls to add to it. If the trait is + // documented locally though we always create the file to avoid dead + // links. + if implementors.is_empty() && !cache.paths.contains_key(&did) { + continue; + } + + let mut path = PathBuf::from("trait.impl"); + for component in &remote_path[..remote_path.len() - 1] { + path.push(component.as_str()); + } + path.push(&format!("{remote_item_type}.{}.js", remote_path[remote_path.len() - 1])); + + let part = OrderedJson::array_sorted( + implementors + .iter() + .map(OrderedJson::serialize) + .collect::, _>>() + .unwrap(), + ); + path_parts.push(path, OrderedJson::array_unsorted([crate_name_json, &part])); + } + Ok(path_parts) + } +} + +struct Implementor { + text: String, + synthetic: bool, + types: Vec, +} + +impl Serialize for Implementor { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut seq = serializer.serialize_seq(None)?; + seq.serialize_element(&self.text)?; + if self.synthetic { + seq.serialize_element(&1)?; + seq.serialize_element(&self.types)?; + } + seq.end() + } +} + +/// Collect the list of aliased types and their aliases. +/// +/// +/// The clean AST has type aliases that point at their types, but +/// this visitor works to reverse that: `aliased_types` is a map +/// from target to the aliases that reference it, and each one +/// will generate one file. +struct TypeImplCollector<'cx, 'cache> { + /// Map from DefId-of-aliased-type to its data. + aliased_types: IndexMap>, + visited_aliases: FxHashSet, + cache: &'cache Cache, + cx: &'cache mut Context<'cx>, +} + +/// Data for an aliased type. +/// +/// In the final file, the format will be roughly: +/// +/// ```json +/// // type.impl/CRATE/TYPENAME.js +/// JSONP( +/// "CRATE": [ +/// ["IMPL1 HTML", "ALIAS1", "ALIAS2", ...], +/// ["IMPL2 HTML", "ALIAS3", "ALIAS4", ...], +/// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ struct AliasedType +/// ... +/// ] +/// ) +/// ``` +struct AliasedType<'cache> { + /// This is used to generate the actual filename of this aliased type. + target_fqp: &'cache [Symbol], + target_type: ItemType, + /// This is the data stored inside the file. + /// ItemId is used to deduplicate impls. + impl_: IndexMap>, +} + +/// The `impl_` contains data that's used to figure out if an alias will work, +/// and to generate the HTML at the end. +/// +/// The `type_aliases` list is built up with each type alias that matches. +struct AliasedTypeImpl<'cache> { + impl_: &'cache Impl, + type_aliases: Vec<(&'cache [Symbol], Item)>, +} + +impl<'cx, 'cache> DocVisitor for TypeImplCollector<'cx, 'cache> { + fn visit_item(&mut self, it: &Item) { + self.visit_item_recur(it); + let cache = self.cache; + let ItemKind::TypeAliasItem(ref t) = *it.kind else { return }; + let Some(self_did) = it.item_id.as_def_id() else { return }; + if !self.visited_aliases.insert(self_did) { + return; + } + let Some(target_did) = t.type_.def_id(cache) else { return }; + let get_extern = { || cache.external_paths.get(&target_did) }; + let Some(&(ref target_fqp, target_type)) = cache.paths.get(&target_did).or_else(get_extern) + else { + return; + }; + let aliased_type = self.aliased_types.entry(target_did).or_insert_with(|| { + let impl_ = cache + .impls + .get(&target_did) + .map(|v| &v[..]) + .unwrap_or_default() + .iter() + .map(|impl_| { + (impl_.impl_item.item_id, AliasedTypeImpl { impl_, type_aliases: Vec::new() }) + }) + .collect(); + AliasedType { target_fqp: &target_fqp[..], target_type, impl_ } + }); + let get_local = { || cache.paths.get(&self_did).map(|(p, _)| p) }; + let Some(self_fqp) = cache.exact_paths.get(&self_did).or_else(get_local) else { + return; + }; + let aliased_ty = self.cx.tcx().type_of(self_did).skip_binder(); + // Exclude impls that are directly on this type. They're already in the HTML. + // Some inlining scenarios can cause there to be two versions of the same + // impl: one on the type alias and one on the underlying target type. + let mut seen_impls: FxHashSet = cache + .impls + .get(&self_did) + .map(|s| &s[..]) + .unwrap_or_default() + .iter() + .map(|i| i.impl_item.item_id) + .collect(); + for (impl_item_id, aliased_type_impl) in &mut aliased_type.impl_ { + // Only include this impl if it actually unifies with this alias. + // Synthetic impls are not included; those are also included in the HTML. + // + // FIXME(lazy_type_alias): Once the feature is complete or stable, rewrite this + // to use type unification. + // Be aware of `tests/rustdoc/type-alias/deeply-nested-112515.rs` which might regress. + let Some(impl_did) = impl_item_id.as_def_id() else { continue }; + let for_ty = self.cx.tcx().type_of(impl_did).skip_binder(); + let reject_cx = DeepRejectCtxt::new(self.cx.tcx(), TreatParams::AsCandidateKey); + if !reject_cx.types_may_unify(aliased_ty, for_ty) { + continue; + } + // Avoid duplicates + if !seen_impls.insert(*impl_item_id) { + continue; + } + // This impl was not found in the set of rejected impls + aliased_type_impl.type_aliases.push((&self_fqp[..], it.clone())); + } + } +} + +/// Final serialized form of the alias impl +struct AliasSerializableImpl { + text: String, + trait_: Option, + aliases: Vec, +} + +impl Serialize for AliasSerializableImpl { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut seq = serializer.serialize_seq(None)?; + seq.serialize_element(&self.text)?; + if let Some(trait_) = &self.trait_ { + seq.serialize_element(trait_)?; + } else { + seq.serialize_element(&0)?; + } + for type_ in &self.aliases { + seq.serialize_element(type_)?; + } + seq.end() + } +} + +fn get_path_parts( + dst: &Path, + crates_info: &[CrateInfo], +) -> FxHashMap> { + let mut templates: FxHashMap> = FxHashMap::default(); + crates_info + .iter() + .map(|crate_info| T::from_crate_info(crate_info).parts.iter()) + .flatten() + .for_each(|(path, part)| { + let path = dst.join(&path); + let part = part.to_string(); + templates.entry(path).or_default().push(part); + }); + templates +} + +/// Create all parents +fn create_parents(path: &Path) -> Result<(), Error> { + let parent = path.parent().expect("should not have an empty path here"); + try_err!(fs::create_dir_all(parent), parent); + Ok(()) +} + +/// Returns a blank template unless we could find one to append to +fn read_template_or_blank( + mut make_blank: F, + path: &Path, +) -> Result, Error> +where + F: FnMut() -> SortedTemplate, +{ + match fs::read_to_string(&path) { + Ok(template) => Ok(try_err!(SortedTemplate::from_str(&template), &path)), + Err(e) if e.kind() == io::ErrorKind::NotFound => Ok(make_blank()), + Err(e) => Err(Error::new(e, &path)), + } +} + +/// info from this crate and the --include-info-json'd crates +fn write_rendered_cci( + mut make_blank: F, + dst: &Path, + crates_info: &[CrateInfo], +) -> Result<(), Error> +where + F: FnMut() -> SortedTemplate, +{ + // write the merged cci to disk + for (path, parts) in get_path_parts::(dst, crates_info) { + create_parents(&path)?; + // read previous rendered cci from storage, append to them + let mut template = read_template_or_blank::<_, T::FileFormat>(&mut make_blank, &path)?; + for part in parts { + template.append(part); + } + let file = try_err!(File::create(&path), &path); + let mut file = BufWriter::new(file); + try_err!(write!(file, "{template}"), &path); + try_err!(file.flush(), &path); + } + Ok(()) +} + +#[cfg(test)] +mod tests; diff --git a/src/librustdoc/html/render/write_shared/tests.rs b/src/librustdoc/html/render/write_shared/tests.rs new file mode 100644 index 00000000000..e282cd99e43 --- /dev/null +++ b/src/librustdoc/html/render/write_shared/tests.rs @@ -0,0 +1,207 @@ +use crate::html::render::ordered_json::{EscapedJson, OrderedJson}; +use crate::html::render::sorted_template::{Html, SortedTemplate}; +use crate::html::render::write_shared::*; + +#[test] +fn hack_external_crate_names() { + let path = tempfile::TempDir::new().unwrap(); + let path = path.path(); + let crates = hack_get_external_crate_names(&path, "").unwrap(); + assert!(crates.is_empty()); + fs::write(path.join("crates.js"), r#"window.ALL_CRATES = ["a","b","c"];"#).unwrap(); + let crates = hack_get_external_crate_names(&path, "").unwrap(); + assert_eq!(crates, ["a".to_string(), "b".to_string(), "c".to_string()]); +} + +fn but_last_line(s: &str) -> &str { + let (before, _) = s.rsplit_once("\n").unwrap(); + before +} + +#[test] +fn sources_template() { + let mut template = SourcesPart::blank(); + assert_eq!( + but_last_line(&template.to_string()), + r"var srcIndex = new Map(JSON.parse('[]')); +createSrcSidebar();" + ); + template.append(EscapedJson::from(OrderedJson::serialize("u").unwrap()).to_string()); + assert_eq!( + but_last_line(&template.to_string()), + r#"var srcIndex = new Map(JSON.parse('["u"]')); +createSrcSidebar();"# + ); + template.append(EscapedJson::from(OrderedJson::serialize("v").unwrap()).to_string()); + assert_eq!( + but_last_line(&template.to_string()), + r#"var srcIndex = new Map(JSON.parse('["u","v"]')); +createSrcSidebar();"# + ); +} + +#[test] +fn sources_parts() { + let parts = + SearchIndexPart::get(OrderedJson::serialize(["foo", "bar"]).unwrap(), "suffix").unwrap(); + assert_eq!(&parts.parts[0].0, Path::new("search-indexsuffix.js")); + assert_eq!(&parts.parts[0].1.to_string(), r#"["foo","bar"]"#); +} + +#[test] +fn all_crates_template() { + let mut template = AllCratesPart::blank(); + assert_eq!(but_last_line(&template.to_string()), r"window.ALL_CRATES = [];"); + template.append(EscapedJson::from(OrderedJson::serialize("b").unwrap()).to_string()); + assert_eq!(but_last_line(&template.to_string()), r#"window.ALL_CRATES = ["b"];"#); + template.append(EscapedJson::from(OrderedJson::serialize("a").unwrap()).to_string()); + assert_eq!(but_last_line(&template.to_string()), r#"window.ALL_CRATES = ["a","b"];"#); +} + +#[test] +fn all_crates_parts() { + let parts = AllCratesPart::get(OrderedJson::serialize("crate").unwrap(), "").unwrap(); + assert_eq!(&parts.parts[0].0, Path::new("crates.js")); + assert_eq!(&parts.parts[0].1.to_string(), r#""crate""#); +} + +#[test] +fn search_index_template() { + let mut template = SearchIndexPart::blank(); + assert_eq!( + but_last_line(&template.to_string()), + r"var searchIndex = new Map(JSON.parse('[]')); +if (typeof exports !== 'undefined') exports.searchIndex = searchIndex; +else if (window.initSearch) window.initSearch(searchIndex);" + ); + template.append(EscapedJson::from(OrderedJson::serialize([1, 2]).unwrap()).to_string()); + assert_eq!( + but_last_line(&template.to_string()), + r"var searchIndex = new Map(JSON.parse('[[1,2]]')); +if (typeof exports !== 'undefined') exports.searchIndex = searchIndex; +else if (window.initSearch) window.initSearch(searchIndex);" + ); + template.append(EscapedJson::from(OrderedJson::serialize([4, 3]).unwrap()).to_string()); + assert_eq!( + but_last_line(&template.to_string()), + r"var searchIndex = new Map(JSON.parse('[[1,2],[4,3]]')); +if (typeof exports !== 'undefined') exports.searchIndex = searchIndex; +else if (window.initSearch) window.initSearch(searchIndex);" + ); +} + +#[test] +fn crates_index_part() { + let external_crates = ["bar".to_string(), "baz".to_string()]; + let mut parts = CratesIndexPart::get("foo", &external_crates).unwrap(); + parts.parts.sort_by(|a, b| a.1.to_string().cmp(&b.1.to_string())); + + assert_eq!(&parts.parts[0].0, Path::new("index.html")); + assert_eq!(&parts.parts[0].1.to_string(), r#"
  • bar
  • "#); + + assert_eq!(&parts.parts[1].0, Path::new("index.html")); + assert_eq!(&parts.parts[1].1.to_string(), r#"
  • baz
  • "#); + + assert_eq!(&parts.parts[2].0, Path::new("index.html")); + assert_eq!(&parts.parts[2].1.to_string(), r#"
  • foo
  • "#); +} + +#[test] +fn trait_alias_template() { + let mut template = TraitAliasPart::blank(); + assert_eq!( + but_last_line(&template.to_string()), + r#"(function() { + var implementors = Object.fromEntries([]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})()"#, + ); + template.append(OrderedJson::serialize(["a"]).unwrap().to_string()); + assert_eq!( + but_last_line(&template.to_string()), + r#"(function() { + var implementors = Object.fromEntries([["a"]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})()"#, + ); + template.append(OrderedJson::serialize(["b"]).unwrap().to_string()); + assert_eq!( + but_last_line(&template.to_string()), + r#"(function() { + var implementors = Object.fromEntries([["a"],["b"]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})()"#, + ); +} + +#[test] +fn type_alias_template() { + let mut template = TypeAliasPart::blank(); + assert_eq!( + but_last_line(&template.to_string()), + r#"(function() { + var type_impls = Object.fromEntries([]); + if (window.register_type_impls) { + window.register_type_impls(type_impls); + } else { + window.pending_type_impls = type_impls; + } +})()"#, + ); + template.append(OrderedJson::serialize(["a"]).unwrap().to_string()); + assert_eq!( + but_last_line(&template.to_string()), + r#"(function() { + var type_impls = Object.fromEntries([["a"]]); + if (window.register_type_impls) { + window.register_type_impls(type_impls); + } else { + window.pending_type_impls = type_impls; + } +})()"#, + ); + template.append(OrderedJson::serialize(["b"]).unwrap().to_string()); + assert_eq!( + but_last_line(&template.to_string()), + r#"(function() { + var type_impls = Object.fromEntries([["a"],["b"]]); + if (window.register_type_impls) { + window.register_type_impls(type_impls); + } else { + window.pending_type_impls = type_impls; + } +})()"#, + ); +} + +#[test] +fn read_template_test() { + let path = tempfile::TempDir::new().unwrap(); + let path = path.path().join("file.html"); + let make_blank = || SortedTemplate::::from_before_after("
    ", "
    "); + + let template = read_template_or_blank(make_blank, &path).unwrap(); + assert_eq!(but_last_line(&template.to_string()), "
    "); + fs::write(&path, template.to_string()).unwrap(); + let mut template = read_template_or_blank(make_blank, &path).unwrap(); + template.append("".to_string()); + fs::write(&path, template.to_string()).unwrap(); + let mut template = read_template_or_blank(make_blank, &path).unwrap(); + template.append("
    ".to_string()); + fs::write(&path, template.to_string()).unwrap(); + let template = read_template_or_blank(make_blank, &path).unwrap(); + + assert_eq!(but_last_line(&template.to_string()), "

    "); +} diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index eb5a5d935e2..28df8d3f011 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1547,10 +1547,23 @@ instead, we check that it's not a "finger" cursor. margin-left: 24px; } +@keyframes targetfadein { + from { + background-color: var(--main-background-color); + } + 10% { + background-color: var(--target-border-color); + } + to { + background-color: var(--target-background-color); + } +} + :target { padding-right: 3px; background-color: var(--target-background-color); border-right: 3px solid var(--target-border-color); + animation: 0.65s cubic-bezier(0, 0, 0.1, 1.0) 0.1s targetfadein; } .code-header a.tooltip { diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 3eb27ea087c..be0ec425946 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -1393,6 +1393,7 @@ function initSearch(rawSearchIndex) { */ async function sortResults(results, isType, preferredCrate) { const userQuery = parsedQuery.userQuery; + const casedUserQuery = parsedQuery.original; const result_list = []; for (const result of results.values()) { result.item = searchIndex[result.id]; @@ -1403,6 +1404,13 @@ function initSearch(rawSearchIndex) { result_list.sort((aaa, bbb) => { let a, b; + // sort by exact case-sensitive match + a = (aaa.item.name !== casedUserQuery); + b = (bbb.item.name !== casedUserQuery); + if (a !== b) { + return a - b; + } + // sort by exact match with regard to the last word (mismatch goes later) a = (aaa.word !== userQuery); b = (bbb.word !== userQuery); @@ -3546,7 +3554,7 @@ ${item.displayPath}${name}\ // Used to de-duplicate inlined and re-exported stuff const itemReexports = new Map(crateCorpus.r); // an array of (Number) the parent path index + 1 to `paths`, or 0 if none - const itemParentIdxs = crateCorpus.i; + const itemParentIdxDecoder = new VlqHexDecoder(crateCorpus.i, noop => noop); // a map Number, string for impl disambiguators const implDisambiguator = new Map(crateCorpus.b); // an array of [(Number) item type, @@ -3593,6 +3601,8 @@ ${item.displayPath}${name}\ // faster analysis operations lastPath = ""; len = itemTypes.length; + let lastName = ""; + let lastWord = ""; for (let i = 0; i < len; ++i) { const bitIndex = i + 1; if (descIndex >= descShard.len && @@ -3608,10 +3618,8 @@ ${item.displayPath}${name}\ descIndex = 0; descShardList.push(descShard); } - let word = ""; - if (typeof itemNames[i] === "string") { - word = itemNames[i].toLowerCase(); - } + const name = itemNames[i] === "" ? lastName : itemNames[i]; + const word = itemNames[i] === "" ? lastWord : itemNames[i].toLowerCase(); const path = itemPaths.has(i) ? itemPaths.get(i) : lastPath; const type = itemFunctionDecoder.next(); if (type !== null) { @@ -3633,15 +3641,16 @@ ${item.displayPath}${name}\ } // This object should have exactly the same set of fields as the "crateRow" // object defined above. + const itemParentIdx = itemParentIdxDecoder.next(); const row = { crate, ty: itemTypes.charCodeAt(i) - 65, // 65 = "A" - name: itemNames[i], + name, path, descShard, descIndex, exactPath: itemReexports.has(i) ? itemPaths.get(itemReexports.get(i)) : path, - parent: itemParentIdxs[i] > 0 ? paths[itemParentIdxs[i] - 1] : undefined, + parent: itemParentIdx > 0 ? paths[itemParentIdx - 1] : undefined, type, id, word, @@ -3655,6 +3664,8 @@ ${item.displayPath}${name}\ if (!searchIndexEmptyDesc.get(crate).contains(bitIndex)) { descIndex += 1; } + lastName = name; + lastWord = word; } if (aliases) { diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index ea191dc89cf..e2860292aa3 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -9,16 +9,19 @@ mod import_finder; use std::cell::RefCell; use std::fs::{create_dir_all, File}; -use std::io::{BufWriter, Write}; +use std::io::{stdout, BufWriter, Write}; use std::path::PathBuf; use std::rc::Rc; -use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::{DefId, DefIdSet}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_span::def_id::LOCAL_CRATE; use rustdoc_json_types as types; +// It's important to use the FxHashMap from rustdoc_json_types here, instead of +// the one from rustc_data_structures, as they're different types due to sysroots. +// See #110051 and #127456 for details +use rustdoc_json_types::FxHashMap; use crate::clean::types::{ExternalCrate, ExternalLocation}; use crate::clean::ItemKind; @@ -36,8 +39,10 @@ pub(crate) struct JsonRenderer<'tcx> { /// A mapping of IDs that contains all local items for this crate which gets output as a top /// level field of the JSON blob. index: Rc>>, - /// The directory where the blob will be written to. - out_path: PathBuf, + /// The directory where the JSON blob should be written to. + /// + /// If this is `None`, the blob will be printed to `stdout` instead. + out_dir: Option, cache: Rc, imported_items: DefIdSet, } @@ -97,6 +102,22 @@ impl<'tcx> JsonRenderer<'tcx> { }) .unwrap_or_default() } + + fn serialize_and_write( + &self, + output_crate: types::Crate, + mut writer: BufWriter, + path: &str, + ) -> Result<(), Error> { + self.sess().time("rustdoc_json_serialize_and_write", || { + try_err!( + serde_json::ser::to_writer(&mut writer, &output_crate).map_err(|e| e.to_string()), + path + ); + try_err!(writer.flush(), path); + Ok(()) + }) + } } impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { @@ -120,7 +141,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { JsonRenderer { tcx, index: Rc::new(RefCell::new(FxHashMap::default())), - out_path: options.output, + out_dir: if options.output_to_stdout { None } else { Some(options.output) }, cache: Rc::new(cache), imported_items, }, @@ -220,14 +241,11 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { let index = (*self.index).clone().into_inner(); debug!("Constructing Output"); - // This needs to be the default HashMap for compatibility with the public interface for - // rustdoc-json-types - #[allow(rustc::default_hash_types)] - let output = types::Crate { + let output_crate = types::Crate { root: types::Id(format!("0:0:{}", e.name(self.tcx).as_u32())), crate_version: self.cache.crate_version.clone(), includes_private: self.cache.document_private, - index: index.into_iter().collect(), + index, paths: self .cache .paths @@ -264,20 +282,21 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { .collect(), format_version: types::FORMAT_VERSION, }; - let out_dir = self.out_path.clone(); - try_err!(create_dir_all(&out_dir), out_dir); + if let Some(ref out_dir) = self.out_dir { + try_err!(create_dir_all(&out_dir), out_dir); - let mut p = out_dir; - p.push(output.index.get(&output.root).unwrap().name.clone().unwrap()); - p.set_extension("json"); - let mut file = BufWriter::new(try_err!(File::create(&p), p)); - self.tcx - .sess - .time("rustdoc_json_serialization", || serde_json::ser::to_writer(&mut file, &output)) - .unwrap(); - try_err!(file.flush(), p); + let mut p = out_dir.clone(); + p.push(output_crate.index.get(&output_crate.root).unwrap().name.clone().unwrap()); + p.set_extension("json"); - Ok(()) + self.serialize_and_write( + output_crate, + BufWriter::new(try_err!(File::create(&p), p)), + &p.display().to_string(), + ) + } else { + self.serialize_and_write(output_crate, BufWriter::new(stdout().lock()), "") + } } fn cache(&self) -> &Cache { diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs index d78afdffc62..5015d665955 100644 --- a/src/librustdoc/passes/check_doc_test_visibility.rs +++ b/src/librustdoc/passes/check_doc_test_visibility.rs @@ -45,7 +45,7 @@ pub(crate) struct Tests { pub(crate) found_tests: usize, } -impl crate::doctest::DoctestVisitor for Tests { +impl crate::doctest::DocTestVisitor for Tests { fn visit_test(&mut self, _: String, config: LangString, _: MdRelLine) { if config.rust && config.ignore == Ignore::None { self.found_tests += 1; diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 9c7eee4040b..eae12b84839 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -53,7 +53,7 @@ fn filter_assoc_items_by_name_and_namespace<'a>( assoc_items_of: DefId, ident: Ident, ns: Namespace, -) -> impl Iterator + 'a { +) -> impl Iterator + 'a { tcx.associated_items(assoc_items_of).filter_by_name_unhygienic(ident.name).filter(move |item| { item.kind.namespace() == ns && tcx.hygienic_eq(ident, item.ident(tcx), assoc_items_of) }) @@ -495,7 +495,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { ty::RawPtr(_, _) => Res::Primitive(RawPointer), ty::Ref(..) => Res::Primitive(Reference), ty::FnDef(..) => panic!("type alias to a function definition"), - ty::FnPtr(_) => Res::Primitive(Fn), + ty::FnPtr(..) => Res::Primitive(Fn), ty::Never => Res::Primitive(Never), ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did, .. }, _)), _) | ty::Foreign(did) => { Res::from_def_id(self.cx.tcx, did) @@ -1950,7 +1950,9 @@ fn resolution_failure( | TraitAlias | TyParam | Static { .. } => "associated item", - Impl { .. } | GlobalAsm => unreachable!("not a path"), + Impl { .. } | GlobalAsm | SyntheticCoroutineBody => { + unreachable!("not a path") + } } } else { "associated item" diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs index ef05befdddc..977c0953336 100644 --- a/src/librustdoc/passes/lint/check_code_block_syntax.rs +++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs @@ -16,9 +16,11 @@ use crate::core::DocContext; use crate::html::markdown::{self, RustCodeBlock}; pub(crate) fn visit_item(cx: &DocContext<'_>, item: &clean::Item) { - if let Some(dox) = &item.opt_doc_value() { + if let Some(def_id) = item.item_id.as_local_def_id() + && let Some(dox) = &item.opt_doc_value() + { let sp = item.attr_span(cx.tcx); - let extra = crate::html::markdown::ExtraInfo::new(cx.tcx, item.item_id.expect_def_id(), sp); + let extra = crate::html::markdown::ExtraInfo::new(cx.tcx, def_id, sp); for code_block in markdown::rust_code_blocks(dox, &extra) { check_rust_syntax(cx, item, dox, code_block); } diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs index faf42b3aab1..23e298571d5 100644 --- a/src/librustdoc/passes/strip_hidden.rs +++ b/src/librustdoc/passes/strip_hidden.rs @@ -2,7 +2,7 @@ use std::mem; -use rustc_hir::def_id::LocalDefId; +use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; use rustc_middle::ty::TyCtxt; use rustc_span::symbol::sym; @@ -145,8 +145,9 @@ impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> { let old = mem::replace(&mut self.update_retained, false); let ret = self.set_is_in_hidden_item_and_fold(true, i); self.update_retained = old; - if ret.is_crate() { - // We don't strip the crate, even if it has `#[doc(hidden)]`. + if ret.item_id == clean::ItemId::DefId(CRATE_DEF_ID.into()) { + // We don't strip the current crate, even if it has `#[doc(hidden)]`. + debug!("strip_hidden: Not strippping local crate"); Some(ret) } else { Some(strip_item(ret)) diff --git a/src/llvm-project b/src/llvm-project index 57ae1a34740..2b259b3c201 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit 57ae1a3474057fead2c438928ed368b3740bf0ec +Subproject commit 2b259b3c201f939f2ed8d2fb0a0e9b37dd2d1321 diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index 999134a4090..40a90c1a565 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -5,7 +5,7 @@ use std::path::PathBuf; -use rustc_hash::FxHashMap; +pub use rustc_hash::FxHashMap; use serde::{Deserialize, Serialize}; /// The version of JSON output that this crate represents. diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 2b263f848e8..92b21f7dbaa 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -54,6 +54,7 @@ static TARGETS: &[&str] = &[ "arm64e-apple-darwin", "aarch64-apple-ios", "arm64e-apple-ios", + "aarch64-apple-ios-macabi", "aarch64-apple-ios-sim", "aarch64-unknown-fuchsia", "aarch64-linux-android", @@ -161,6 +162,7 @@ static TARGETS: &[&str] = &[ "wasm32-wasip2", "x86_64-apple-darwin", "x86_64-apple-ios", + "x86_64-apple-ios-macabi", "x86_64-fortanix-unknown-sgx", "x86_64-unknown-fuchsia", "x86_64-linux-android", diff --git a/src/tools/cargo b/src/tools/cargo index 0d8d22f83b0..8f40fc59fb0 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 0d8d22f83b066503f6b2b755925197e959e58b4f +Subproject commit 8f40fc59fb0c8df91c97405785197f3c630304ea diff --git a/src/tools/clippy/.cargo/config.toml b/src/tools/clippy/.cargo/config.toml index ce07290d1e1..d9c635df5dc 100644 --- a/src/tools/clippy/.cargo/config.toml +++ b/src/tools/clippy/.cargo/config.toml @@ -1,10 +1,10 @@ [alias] +bless = "test --config env.RUSTC_BLESS='1'" uitest = "test --test compile-test" -uibless = "test --test compile-test -- -- --bless" -bless = "test -- -- --bless" +uibless = "bless --test compile-test" dev = "run --package clippy_dev --bin clippy_dev --manifest-path clippy_dev/Cargo.toml --" lintcheck = "run --package lintcheck --bin lintcheck --manifest-path lintcheck/Cargo.toml -- " -collect-metadata = "test --test dogfood --features internal -- collect_metadata" +collect-metadata = "test --test compile-test --config env.COLLECT_METADATA='1'" [build] # -Zbinary-dep-depinfo allows us to track which rlib files to use for compiling UI tests diff --git a/src/tools/clippy/.github/deploy.sh b/src/tools/clippy/.github/deploy.sh index 5a59f94ec91..d937661c0f8 100644 --- a/src/tools/clippy/.github/deploy.sh +++ b/src/tools/clippy/.github/deploy.sh @@ -10,6 +10,7 @@ mkdir out/master/ cp util/gh-pages/index.html out/master cp util/gh-pages/script.js out/master cp util/gh-pages/lints.json out/master +cp util/gh-pages/style.css out/master if [[ -n $TAG_NAME ]]; then echo "Save the doc for the current tag ($TAG_NAME) and point stable/ to it" diff --git a/src/tools/clippy/.github/workflows/clippy_bors.yml b/src/tools/clippy/.github/workflows/clippy_bors.yml index 10e18e84c89..2aa13313fa5 100644 --- a/src/tools/clippy/.github/workflows/clippy_bors.yml +++ b/src/tools/clippy/.github/workflows/clippy_bors.yml @@ -136,11 +136,6 @@ jobs: - name: Test metadata collection run: cargo collect-metadata - - name: Test lint_configuration.md is up-to-date - run: | - echo "run \`cargo collect-metadata\` if this fails" - git update-index --refresh - integration_build: needs: changelog runs-on: ubuntu-latest diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md index fddc2fd994e..9bc4ad9698d 100644 --- a/src/tools/clippy/CHANGELOG.md +++ b/src/tools/clippy/CHANGELOG.md @@ -5914,6 +5914,7 @@ Released 2018-09-13 [`to_string_in_format_args`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_string_in_format_args [`to_string_trait_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_string_trait_impl [`todo`]: https://rust-lang.github.io/rust-clippy/master/index.html#todo +[`too_long_first_doc_paragraph`]: https://rust-lang.github.io/rust-clippy/master/index.html#too_long_first_doc_paragraph [`too_many_arguments`]: https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments [`too_many_lines`]: https://rust-lang.github.io/rust-clippy/master/index.html#too_many_lines [`toplevel_ref_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#toplevel_ref_arg diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml index 78409c7a09e..b48b881097f 100644 --- a/src/tools/clippy/Cargo.toml +++ b/src/tools/clippy/Cargo.toml @@ -30,8 +30,11 @@ color-print = "0.3.4" anstream = "0.6.0" [dev-dependencies] +cargo_metadata = "0.18.1" ui_test = "0.25" regex = "1.5.5" +serde = { version = "1.0.145", features = ["derive"] } +serde_json = "1.0.122" toml = "0.7.3" walkdir = "2.3" filetime = "0.2.9" @@ -41,7 +44,6 @@ itertools = "0.12" clippy_utils = { path = "clippy_utils" } if_chain = "1.0" quote = "1.0.25" -serde = { version = "1.0.145", features = ["derive"] } syn = { version = "2.0", features = ["full"] } futures = "0.3" parking_lot = "0.12" diff --git a/src/tools/clippy/book/src/development/adding_lints.md b/src/tools/clippy/book/src/development/adding_lints.md index a71d94daca7..963e02e5c16 100644 --- a/src/tools/clippy/book/src/development/adding_lints.md +++ b/src/tools/clippy/book/src/development/adding_lints.md @@ -739,7 +739,7 @@ for some users. Adding a configuration is done in the following steps: 5. Update [Lint Configuration](../lint_configuration.md) - Run `cargo collect-metadata` to generate documentation changes for the book. + Run `cargo bless --test config-metadata` to generate documentation changes for the book. [`clippy_config::conf`]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_config/src/conf.rs [`clippy_lints` lib file]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_lints/src/lib.rs diff --git a/src/tools/clippy/book/src/lint_configuration.md b/src/tools/clippy/book/src/lint_configuration.md index e3d550b1466..78348797588 100644 --- a/src/tools/clippy/book/src/lint_configuration.md +++ b/src/tools/clippy/book/src/lint_configuration.md @@ -1,5 +1,5 @@ @@ -199,7 +199,7 @@ Allowed names below the minimum allowed characters. The value `".."` can be used the list to indicate, that the configured values should be appended to the default configuration of Clippy. By default, any configuration will replace the default value. -**Default Value:** `["j", "z", "i", "y", "n", "x", "w"]` +**Default Value:** `["i", "j", "x", "y", "z", "w", "n"]` --- **Affected lints:** @@ -455,7 +455,7 @@ default configuration of Clippy. By default, any configuration will replace the * `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`. * `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list. -**Default Value:** `["TiB", "CoreGraphics", "CoffeeScript", "TeX", "Direct2D", "PiB", "DirectX", "NetBSD", "OAuth", "NaN", "OpenType", "WebGL2", "WebTransport", "JavaScript", "OpenSSL", "OpenSSH", "EiB", "PureScript", "OpenAL", "MiB", "WebAssembly", "MinGW", "CoreFoundation", "WebGPU", "ClojureScript", "CamelCase", "OpenDNS", "NaNs", "OpenMP", "GitLab", "KiB", "sRGB", "CoreText", "macOS", "TypeScript", "GiB", "OpenExr", "YCbCr", "OpenTelemetry", "OpenBSD", "FreeBSD", "GPLv2", "PostScript", "WebP", "LaTeX", "TensorFlow", "AccessKit", "TrueType", "OpenStreetMap", "OpenGL", "DevOps", "OCaml", "WebRTC", "WebGL", "BibLaTeX", "GitHub", "GraphQL", "iOS", "Direct3D", "BibTeX", "DirectWrite", "GPLv3", "IPv6", "WebSocket", "IPv4", "ECMAScript"]` +**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "AccessKit", "CoreFoundation", "CoreGraphics", "CoreText", "DevOps", "Direct2D", "Direct3D", "DirectWrite", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PostScript", "PureScript", "TypeScript", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenAL", "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry", "OpenType", "WebGL", "WebGL2", "WebGPU", "WebRTC", "WebSocket", "WebTransport", "WebP", "OpenExr", "YCbCr", "sRGB", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "NetBSD", "OpenBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` --- **Affected lints:** @@ -949,5 +949,3 @@ Whether to also emit warnings for unsafe blocks with metavariable expansions in --- **Affected lints:** * [`macro_metavars_in_unsafe`](https://rust-lang.github.io/rust-clippy/master/index.html#macro_metavars_in_unsafe) - - diff --git a/src/tools/clippy/clippy_config/Cargo.toml b/src/tools/clippy/clippy_config/Cargo.toml index d5b28e25323..5c4e0761dbc 100644 --- a/src/tools/clippy/clippy_config/Cargo.toml +++ b/src/tools/clippy/clippy_config/Cargo.toml @@ -7,7 +7,6 @@ edition = "2021" [dependencies] itertools = "0.12" -rustc-semver = "1.1" serde = { version = "1.0", features = ["derive"] } toml = "0.7.3" diff --git a/src/tools/clippy/clippy_config/src/conf.rs b/src/tools/clippy/clippy_config/src/conf.rs index 4c2a8255d6b..a6f1b958bfb 100644 --- a/src/tools/clippy/clippy_config/src/conf.rs +++ b/src/tools/clippy/clippy_config/src/conf.rs @@ -1,7 +1,6 @@ use crate::msrvs::Msrv; use crate::types::{DisallowedPath, MacroMatcher, MatchLintBehaviour, PubUnderscoreFieldsBehaviour, Rename}; use crate::ClippyConfiguration; -use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_session::Session; use rustc_span::edit_distance::edit_distance; @@ -218,7 +217,7 @@ macro_rules! define_Conf { define_Conf! { /// Which crates to allow absolute paths from #[lints(absolute_paths)] - absolute_paths_allowed_crates: FxHashSet = FxHashSet::default(), + absolute_paths_allowed_crates: Vec = Vec::new(), /// The maximum number of segments a path can have before being linted, anything above this will /// be linted. #[lints(absolute_paths)] @@ -280,12 +279,12 @@ define_Conf! { allowed_dotfiles: Vec = Vec::default(), /// A list of crate names to allow duplicates of #[lints(multiple_crate_versions)] - allowed_duplicate_crates: FxHashSet = FxHashSet::default(), + allowed_duplicate_crates: Vec = Vec::new(), /// Allowed names below the minimum allowed characters. The value `".."` can be used as part of /// the list to indicate, that the configured values should be appended to the default /// configuration of Clippy. By default, any configuration will replace the default value. #[lints(min_ident_chars)] - allowed_idents_below_min_chars: FxHashSet = + allowed_idents_below_min_chars: Vec = DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS.iter().map(ToString::to_string).collect(), /// List of prefixes to allow when determining whether an item's name ends with the module's name. /// If the rest of an item's name is an allowed prefix (e.g. item `ToFoo` or `to_foo` in module `foo`), @@ -323,7 +322,7 @@ define_Conf! { /// 2. Paths with any segment that containing the word 'prelude' /// are already allowed by default. #[lints(wildcard_imports)] - allowed_wildcard_imports: FxHashSet = FxHashSet::default(), + allowed_wildcard_imports: Vec = Vec::new(), /// Suppress checking of the passed type names in all types of operations. /// /// If a specific operation is desired, consider using `arithmetic_side_effects_allowed_binary` or `arithmetic_side_effects_allowed_unary` instead. @@ -355,7 +354,7 @@ define_Conf! { /// arithmetic-side-effects-allowed-binary = [["SomeType" , "f32"], ["AnotherType", "*"]] /// ``` #[lints(arithmetic_side_effects)] - arithmetic_side_effects_allowed_binary: Vec<[String; 2]> = <_>::default(), + arithmetic_side_effects_allowed_binary: Vec<(String, String)> = <_>::default(), /// Suppress checking of the passed type names in unary operations like "negation" (`-`). /// /// #### Example @@ -431,7 +430,7 @@ define_Conf! { /// * `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`. /// * `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list. #[lints(doc_markdown)] - doc_valid_idents: FxHashSet = DEFAULT_DOC_VALID_IDENTS.iter().map(ToString::to_string).collect(), + doc_valid_idents: Vec = DEFAULT_DOC_VALID_IDENTS.iter().map(ToString::to_string).collect(), /// Whether to apply the raw pointer heuristic to determine if a type is `Send`. #[lints(non_send_fields_in_send_ty)] enable_raw_pointer_heuristic_for_send: bool = true, @@ -706,12 +705,12 @@ fn deserialize(file: &SourceFile) -> TryConf { DEFAULT_ALLOWED_TRAITS_WITH_RENAMED_PARAMS, ); // TODO: THIS SHOULD BE TESTED, this comment will be gone soon - if conf.conf.allowed_idents_below_min_chars.contains("..") { + if conf.conf.allowed_idents_below_min_chars.iter().any(|e| e == "..") { conf.conf .allowed_idents_below_min_chars .extend(DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS.iter().map(ToString::to_string)); } - if conf.conf.doc_valid_idents.contains("..") { + if conf.conf.doc_valid_idents.iter().any(|e| e == "..") { conf.conf .doc_valid_idents .extend(DEFAULT_DOC_VALID_IDENTS.iter().map(ToString::to_string)); @@ -890,14 +889,14 @@ fn calculate_dimensions(fields: &[&str]) -> (usize, Vec) { #[cfg(test)] mod tests { - use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use serde::de::IgnoredAny; + use std::collections::{HashMap, HashSet}; use std::fs; use walkdir::WalkDir; #[test] fn configs_are_tested() { - let mut names: FxHashSet = crate::get_configuration_metadata() + let mut names: HashSet = crate::get_configuration_metadata() .into_iter() .map(|meta| meta.name.replace('_', "-")) .collect(); @@ -910,7 +909,7 @@ mod tests { for entry in toml_files { let file = fs::read_to_string(entry.path()).unwrap(); #[allow(clippy::zero_sized_map_values)] - if let Ok(map) = toml::from_str::>(&file) { + if let Ok(map) = toml::from_str::>(&file) { for name in map.keys() { names.remove(name.as_str()); } diff --git a/src/tools/clippy/clippy_config/src/lib.rs b/src/tools/clippy/clippy_config/src/lib.rs index d2246f12029..ac838cc81d2 100644 --- a/src/tools/clippy/clippy_config/src/lib.rs +++ b/src/tools/clippy/clippy_config/src/lib.rs @@ -14,7 +14,7 @@ )] extern crate rustc_ast; -extern crate rustc_data_structures; +extern crate rustc_attr; #[allow(unused_extern_crates)] extern crate rustc_driver; extern crate rustc_errors; diff --git a/src/tools/clippy/clippy_config/src/msrvs.rs b/src/tools/clippy/clippy_config/src/msrvs.rs index fc56ac51796..0e8215aa8e3 100644 --- a/src/tools/clippy/clippy_config/src/msrvs.rs +++ b/src/tools/clippy/clippy_config/src/msrvs.rs @@ -1,6 +1,6 @@ use rustc_ast::Attribute; -use rustc_semver::RustcVersion; -use rustc_session::Session; +use rustc_attr::parse_version; +use rustc_session::{RustcVersion, Session}; use rustc_span::{sym, Symbol}; use serde::Deserialize; use std::fmt; @@ -10,7 +10,7 @@ macro_rules! msrv_aliases { $($name:ident),* $(,)? })*) => { $($( - pub const $name: RustcVersion = RustcVersion::new($major, $minor, $patch); + pub const $name: RustcVersion = RustcVersion { major: $major, minor :$minor, patch: $patch }; )*)* }; } @@ -18,6 +18,7 @@ macro_rules! msrv_aliases { // names may refer to stabilized feature flags or library items msrv_aliases! { 1,81,0 { LINT_REASONS_STABILIZATION } + 1,80,0 { BOX_INTO_ITER} 1,77,0 { C_STR_LITERALS } 1,76,0 { PTR_FROM_REF, OPTION_RESULT_INSPECT } 1,71,0 { TUPLE_ARRAY_CONVERSIONS, BUILD_HASHER_HASH_ONE } @@ -81,9 +82,9 @@ impl<'de> Deserialize<'de> for Msrv { D: serde::Deserializer<'de>, { let v = String::deserialize(deserializer)?; - RustcVersion::parse(&v) + parse_version(Symbol::intern(&v)) .map(|v| Msrv { stack: vec![v] }) - .map_err(|_| serde::de::Error::custom("not a valid Rust version")) + .ok_or_else(|| serde::de::Error::custom("not a valid Rust version")) } } @@ -95,7 +96,7 @@ impl Msrv { pub fn read_cargo(&mut self, sess: &Session) { let cargo_msrv = std::env::var("CARGO_PKG_RUST_VERSION") .ok() - .and_then(|v| RustcVersion::parse(&v).ok()); + .and_then(|v| parse_version(Symbol::intern(&v))); match (self.current(), cargo_msrv) { (None, Some(cargo_msrv)) => self.stack = vec![cargo_msrv], @@ -115,7 +116,7 @@ impl Msrv { } pub fn meets(&self, required: RustcVersion) -> bool { - self.current().map_or(true, |version| version.meets(required)) + self.current().map_or(true, |msrv| msrv >= required) } fn parse_attr(sess: &Session, attrs: &[Attribute]) -> Option { @@ -131,7 +132,7 @@ impl Msrv { } if let Some(msrv) = msrv_attr.value_str() { - if let Ok(version) = RustcVersion::parse(msrv.as_str()) { + if let Some(version) = parse_version(msrv) { return Some(version); } diff --git a/src/tools/clippy/clippy_dev/src/main.rs b/src/tools/clippy/clippy_dev/src/main.rs index 755b04b0b23..fc15913354c 100644 --- a/src/tools/clippy/clippy_dev/src/main.rs +++ b/src/tools/clippy/clippy_dev/src/main.rs @@ -1,3 +1,4 @@ +#![feature(rustc_private)] // warn on lints, that are included in `rust-lang/rust`s bootstrap #![warn(rust_2018_idioms, unused_lifetimes)] diff --git a/src/tools/clippy/clippy_dev/src/new_lint.rs b/src/tools/clippy/clippy_dev/src/new_lint.rs index de91233d196..87117832fb9 100644 --- a/src/tools/clippy/clippy_dev/src/new_lint.rs +++ b/src/tools/clippy/clippy_dev/src/new_lint.rs @@ -470,7 +470,7 @@ fn setup_mod_file(path: &Path, lint: &LintData<'_>) -> io::Result<&'static str> }); // Find both the last lint declaration (declare_clippy_lint!) and the lint pass impl - while let Some(LintDeclSearchResult { content, .. }) = iter.find(|result| result.token_kind == TokenKind::Ident) { + while let Some(LintDeclSearchResult { content, .. }) = iter.find(|result| result.token == TokenKind::Ident) { let mut iter = iter .by_ref() .filter(|t| !matches!(t.token_kind, TokenKind::Whitespace | TokenKind::LineComment { .. })); @@ -480,7 +480,7 @@ fn setup_mod_file(path: &Path, lint: &LintData<'_>) -> io::Result<&'static str> // matches `!{` match_tokens!(iter, Bang OpenBrace); if let Some(LintDeclSearchResult { range, .. }) = - iter.find(|result| result.token_kind == TokenKind::CloseBrace) + iter.find(|result| result.token == TokenKind::CloseBrace) { last_decl_curly_offset = Some(range.end); } diff --git a/src/tools/clippy/clippy_dev/src/update_lints.rs b/src/tools/clippy/clippy_dev/src/update_lints.rs index 15578d69c3a..8dbda1c634c 100644 --- a/src/tools/clippy/clippy_dev/src/update_lints.rs +++ b/src/tools/clippy/clippy_dev/src/update_lints.rs @@ -604,7 +604,7 @@ fn gen_declared_lints<'a>( details.sort_unstable(); let mut output = GENERATED_FILE_COMMENT.to_string(); - output.push_str("pub(crate) static LINTS: &[&crate::LintInfo] = &[\n"); + output.push_str("pub static LINTS: &[&crate::LintInfo] = &[\n"); for (is_public, module_name, lint_name) in details { if !is_public { diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml index 99ed93468a0..fbd4566da58 100644 --- a/src/tools/clippy/clippy_lints/Cargo.toml +++ b/src/tools/clippy/clippy_lints/Cargo.toml @@ -25,7 +25,6 @@ regex = { version = "1.5", optional = true } unicode-normalization = "0.1" unicode-script = { version = "0.5", default-features = false } semver = "1.0" -rustc-semver = "1.1" url = "2.2" [dev-dependencies] diff --git a/src/tools/clippy/clippy_lints/src/absolute_paths.rs b/src/tools/clippy/clippy_lints/src/absolute_paths.rs index c0a9d888e0b..c72b3f1318c 100644 --- a/src/tools/clippy/clippy_lints/src/absolute_paths.rs +++ b/src/tools/clippy/clippy_lints/src/absolute_paths.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint; -use clippy_utils::source::snippet_opt; +use clippy_utils::is_from_proc_macro; use rustc_data_structures::fx::FxHashSet; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; @@ -8,6 +8,7 @@ use rustc_hir::{HirId, ItemKind, Node, Path}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; use rustc_span::symbol::kw; +use rustc_span::Symbol; declare_clippy_lint! { /// ### What it does @@ -24,6 +25,13 @@ declare_clippy_lint! { /// Note: One exception to this is code from macro expansion - this does not lint such cases, as /// using absolute paths is the proper way of referencing items in one. /// + /// ### Known issues + /// + /// There are currently a few cases which are not caught by this lint: + /// * Macro calls. e.g. `path::to::macro!()` + /// * Derive macros. e.g. `#[derive(path::to::macro)]` + /// * Attribute macros. e.g. `#[path::to::macro]` + /// /// ### Example /// ```no_run /// let x = std::f64::consts::PI; @@ -48,63 +56,66 @@ impl_lint_pass!(AbsolutePaths => [ABSOLUTE_PATHS]); pub struct AbsolutePaths { pub absolute_paths_max_segments: u64, - pub absolute_paths_allowed_crates: &'static FxHashSet, + pub absolute_paths_allowed_crates: FxHashSet, } impl AbsolutePaths { pub fn new(conf: &'static Conf) -> Self { Self { absolute_paths_max_segments: conf.absolute_paths_max_segments, - absolute_paths_allowed_crates: &conf.absolute_paths_allowed_crates, + absolute_paths_allowed_crates: conf + .absolute_paths_allowed_crates + .iter() + .map(|x| Symbol::intern(x)) + .collect(), } } } -impl LateLintPass<'_> for AbsolutePaths { +impl<'tcx> LateLintPass<'tcx> for AbsolutePaths { // We should only lint `QPath::Resolved`s, but since `Path` is only used in `Resolved` and `UsePath` // we don't need to use a visitor or anything as we can just check if the `Node` for `hir_id` isn't // a `Use` - #[expect(clippy::cast_possible_truncation)] - fn check_path(&mut self, cx: &LateContext<'_>, path: &Path<'_>, hir_id: HirId) { - let Self { - absolute_paths_max_segments, - absolute_paths_allowed_crates, - } = self; - - if !path.span.from_expansion() - && let node = cx.tcx.hir_node(hir_id) - && !matches!(node, Node::Item(item) if matches!(item.kind, ItemKind::Use(_, _))) - && let [first, rest @ ..] = path.segments - // Handle `::std` - && let (segment, len) = if first.ident.name == kw::PathRoot { - // Indexing is fine as `PathRoot` must be followed by another segment. `len() - 1` - // is fine here for the same reason - (&rest[0], path.segments.len() - 1) - } else { - (first, path.segments.len()) - } - && len > *absolute_paths_max_segments as usize - && let Some(segment_snippet) = snippet_opt(cx, segment.ident.span) - && segment_snippet == segment.ident.as_str() - { - let is_abs_external = - matches!(segment.res, Res::Def(DefKind::Mod, DefId { index, .. }) if index == CRATE_DEF_INDEX); - let is_abs_crate = segment.ident.name == kw::Crate; - - if is_abs_external && absolute_paths_allowed_crates.contains(segment.ident.name.as_str()) - || is_abs_crate && absolute_paths_allowed_crates.contains("crate") + fn check_path(&mut self, cx: &LateContext<'tcx>, path: &Path<'tcx>, hir_id: HirId) { + let segments = match path.segments { + [] | [_] => return, + // Don't count enum variants and trait items as part of the length. + [rest @ .., _] + if let [.., s] = rest + && matches!(s.res, Res::Def(DefKind::Enum | DefKind::Trait | DefKind::TraitAlias, _)) => { + rest + }, + path => path, + }; + if let [s1, s2, ..] = segments + && let has_root = s1.ident.name == kw::PathRoot + && let first = if has_root { s2 } else { s1 } + && let len = segments.len() - usize::from(has_root) + && len as u64 > self.absolute_paths_max_segments + && let crate_name = if let Res::Def(DefKind::Mod, DefId { index, .. }) = first.res + && index == CRATE_DEF_INDEX + { + // `other_crate::foo` or `::other_crate::foo` + first.ident.name + } else if first.ident.name == kw::Crate || has_root { + // `::foo` or `crate::foo` + kw::Crate + } else { return; } - - if is_abs_external || is_abs_crate { - span_lint( - cx, - ABSOLUTE_PATHS, - path.span, - "consider bringing this path into scope with the `use` keyword", - ); - } + && !path.span.from_expansion() + && let node = cx.tcx.hir_node(hir_id) + && !matches!(node, Node::Item(item) if matches!(item.kind, ItemKind::Use(..))) + && !self.absolute_paths_allowed_crates.contains(&crate_name) + && !is_from_proc_macro(cx, path) + { + span_lint( + cx, + ABSOLUTE_PATHS, + path.span, + "consider bringing this path into scope with the `use` keyword", + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/approx_const.rs b/src/tools/clippy/clippy_lints/src/approx_const.rs index 3b4cc113480..56f5e903dc3 100644 --- a/src/tools/clippy/clippy_lints/src/approx_const.rs +++ b/src/tools/clippy/clippy_lints/src/approx_const.rs @@ -4,8 +4,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use rustc_ast::ast::{FloatTy, LitFloatType, LitKind}; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_semver::RustcVersion; -use rustc_session::impl_lint_pass; +use rustc_session::{impl_lint_pass, RustcVersion}; use rustc_span::symbol; use std::f64::consts as f64; diff --git a/src/tools/clippy/clippy_lints/src/assigning_clones.rs b/src/tools/clippy/clippy_lints/src/assigning_clones.rs index 6e336efbb90..55645d04eef 100644 --- a/src/tools/clippy/clippy_lints/src/assigning_clones.rs +++ b/src/tools/clippy/clippy_lints/src/assigning_clones.rs @@ -3,7 +3,7 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::mir::{enclosing_mir, PossibleBorrowerMap}; use clippy_utils::sugg::Sugg; -use clippy_utils::{is_diag_trait_item, last_path_segment, local_is_initialized, path_to_local}; +use clippy_utils::{is_diag_trait_item, is_in_test, last_path_segment, local_is_initialized, path_to_local}; use rustc_errors::Applicability; use rustc_hir::{self as hir, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -118,6 +118,7 @@ impl<'tcx> LateLintPass<'tcx> for AssigningClones { } ) && !clone_source_borrows_from_dest(cx, lhs, rhs.span) + && !is_in_test(cx.tcx, e.hir_id) { span_lint_and_then( cx, diff --git a/src/tools/clippy/clippy_lints/src/attrs/empty_line_after.rs b/src/tools/clippy/clippy_lints/src/attrs/empty_line_after.rs index ca43e76ac57..7ff644b4c44 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/empty_line_after.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/empty_line_after.rs @@ -1,6 +1,6 @@ use super::{EMPTY_LINE_AFTER_DOC_COMMENTS, EMPTY_LINE_AFTER_OUTER_ATTR}; use clippy_utils::diagnostics::span_lint; -use clippy_utils::source::{is_present_in_source, snippet_opt, without_block_comments}; +use clippy_utils::source::{is_present_in_source, without_block_comments, SpanRangeExt}; use rustc_ast::{AttrKind, AttrStyle}; use rustc_lint::EarlyContext; use rustc_span::Span; @@ -26,7 +26,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, item: &rustc_ast::Item) { item.span.parent(), ); - if let Some(snippet) = snippet_opt(cx, end_of_attr_to_next_attr_or_item) { + if let Some(snippet) = end_of_attr_to_next_attr_or_item.get_source_text(cx) { let lines = snippet.split('\n').collect::>(); let lines = without_block_comments(lines); diff --git a/src/tools/clippy/clippy_lints/src/attrs/mod.rs b/src/tools/clippy/clippy_lints/src/attrs/mod.rs index 8f430ae601a..3b14e9aee7f 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/mod.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/mod.rs @@ -1,5 +1,3 @@ -//! checks for attributes - mod allow_attributes; mod allow_attributes_without_reason; mod blanket_clippy_restriction_lints; @@ -310,8 +308,8 @@ declare_clippy_lint! { /// ```rust,ignore /// #[allow(unused_mut)] /// fn foo() -> usize { - /// let mut a = Vec::new(); - /// a.len() + /// let mut a = Vec::new(); + /// a.len() /// } /// ``` /// Use instead: diff --git a/src/tools/clippy/clippy_lints/src/attrs/non_minimal_cfg.rs b/src/tools/clippy/clippy_lints/src/attrs/non_minimal_cfg.rs index 3fde7061585..877025cce4c 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/non_minimal_cfg.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/non_minimal_cfg.rs @@ -1,6 +1,6 @@ use super::{Attribute, NON_MINIMAL_CFG}; use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use rustc_ast::{MetaItemKind, NestedMetaItem}; use rustc_errors::Applicability; use rustc_lint::EarlyContext; @@ -29,8 +29,13 @@ fn check_nested_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) { meta.span, "unneeded sub `cfg` when there is only one condition", |diag| { - if let Some(snippet) = snippet_opt(cx, list[0].span()) { - diag.span_suggestion(meta.span, "try", snippet, Applicability::MaybeIncorrect); + if let Some(snippet) = list[0].span().get_source_text(cx) { + diag.span_suggestion( + meta.span, + "try", + snippet.to_owned(), + Applicability::MaybeIncorrect, + ); } }, ); diff --git a/src/tools/clippy/clippy_lints/src/attrs/unnecessary_clippy_cfg.rs b/src/tools/clippy/clippy_lints/src/attrs/unnecessary_clippy_cfg.rs index 486e7c6ec4f..478ba7a187b 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/unnecessary_clippy_cfg.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/unnecessary_clippy_cfg.rs @@ -1,6 +1,7 @@ use super::{Attribute, UNNECESSARY_CLIPPY_CFG}; use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_sugg}; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; +use itertools::Itertools; use rustc_ast::AttrStyle; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, Level}; @@ -31,7 +32,7 @@ pub(super) fn check( return; } if nb_items == clippy_lints.len() { - if let Some(snippet) = snippet_opt(cx, behind_cfg_attr.span) { + if let Some(snippet) = behind_cfg_attr.span.get_source_text(cx) { span_lint_and_sugg( cx, UNNECESSARY_CLIPPY_CFG, @@ -47,11 +48,7 @@ pub(super) fn check( ); } } else { - let snippet = clippy_lints - .iter() - .filter_map(|sp| snippet_opt(cx, *sp)) - .collect::>() - .join(","); + let snippet = clippy_lints.iter().filter_map(|sp| sp.get_source_text(cx)).join(","); span_lint_and_note( cx, UNNECESSARY_CLIPPY_CFG, diff --git a/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs b/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs index f0868231d01..67ba605a59f 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs @@ -1,7 +1,7 @@ use super::utils::{extract_clippy_lint, is_lint_level, is_word}; use super::{Attribute, USELESS_ATTRIBUTE}; use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::{first_line_of_span, snippet_opt}; +use clippy_utils::source::{first_line_of_span, SpanRangeExt}; use rustc_ast::NestedMetaItem; use rustc_errors::Applicability; use rustc_hir::{Item, ItemKind}; @@ -69,14 +69,14 @@ pub(super) fn check(cx: &LateContext<'_>, item: &Item<'_>, attrs: &[Attribute]) } let line_span = first_line_of_span(cx, attr.span); - if let Some(mut sugg) = snippet_opt(cx, line_span) { - if sugg.contains("#[") { + if let Some(src) = line_span.get_source_text(cx) { + if src.contains("#[") { + #[expect(clippy::collapsible_span_lint_calls)] span_lint_and_then(cx, USELESS_ATTRIBUTE, line_span, "useless lint attribute", |diag| { - sugg = sugg.replacen("#[", "#![", 1); diag.span_suggestion( line_span, "if you just forgot a `!`, use", - sugg, + src.replacen("#[", "#![", 1), Applicability::MaybeIncorrect, ); }); diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs index a2f48c18170..e933fdf1d6e 100644 --- a/src/tools/clippy/clippy_lints/src/booleans.rs +++ b/src/tools/clippy/clippy_lints/src/booleans.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then}; use clippy_utils::eq_expr_value; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; @@ -134,28 +134,30 @@ fn check_inverted_bool_in_condition( let suggestion = match (left.kind, right.kind) { (ExprKind::Unary(UnOp::Not, left_sub), ExprKind::Unary(UnOp::Not, right_sub)) => { - let Some(left) = snippet_opt(cx, left_sub.span) else { + let Some(left) = left_sub.span.get_source_text(cx) else { return; }; - let Some(right) = snippet_opt(cx, right_sub.span) else { + let Some(right) = right_sub.span.get_source_text(cx) else { return; }; let Some(op) = bin_op_eq_str(op) else { return }; format!("{left} {op} {right}") }, (ExprKind::Unary(UnOp::Not, left_sub), _) => { - let Some(left) = snippet_opt(cx, left_sub.span) else { + let Some(left) = left_sub.span.get_source_text(cx) else { return; }; - let Some(right) = snippet_opt(cx, right.span) else { + let Some(right) = right.span.get_source_text(cx) else { return; }; let Some(op) = inverted_bin_op_eq_str(op) else { return }; format!("{left} {op} {right}") }, (_, ExprKind::Unary(UnOp::Not, right_sub)) => { - let Some(left) = snippet_opt(cx, left.span) else { return }; - let Some(right) = snippet_opt(cx, right_sub.span) else { + let Some(left) = left.span.get_source_text(cx) else { + return; + }; + let Some(right) = right_sub.span.get_source_text(cx) else { return; }; let Some(op) = inverted_bin_op_eq_str(op) else { return }; @@ -313,8 +315,7 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> { self.output.push_str(&str); } else { self.output.push('!'); - let snip = snippet_opt(self.cx, terminal.span)?; - self.output.push_str(&snip); + self.output.push_str(&terminal.span.get_source_text(self.cx)?); } }, True | False | Not(_) => { @@ -345,8 +346,12 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> { } }, &Term(n) => { - let snip = snippet_opt(self.cx, self.terminals[n as usize].span.source_callsite())?; - self.output.push_str(&snip); + self.output.push_str( + &self.terminals[n as usize] + .span + .source_callsite() + .get_source_text(self.cx)?, + ); }, } Some(()) @@ -370,8 +375,8 @@ fn simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option { _ => None, } .and_then(|op| { - let lhs_snippet = snippet_opt(cx, lhs.span)?; - let rhs_snippet = snippet_opt(cx, rhs.span)?; + let lhs_snippet = lhs.span.get_source_text(cx)?; + let rhs_snippet = rhs.span.get_source_text(cx)?; if !(lhs_snippet.starts_with('(') && lhs_snippet.ends_with(')')) { if let (ExprKind::Cast(..), BinOpKind::Ge) = (&lhs.kind, binop.node) { @@ -399,7 +404,7 @@ fn simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option { let path: &str = path.ident.name.as_str(); a == path }) - .and_then(|(_, neg_method)| Some(format!("{}.{neg_method}()", snippet_opt(cx, receiver.span)?))) + .and_then(|(_, neg_method)| Some(format!("{}.{neg_method}()", receiver.span.get_source_text(cx)?))) }, _ => None, } diff --git a/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs b/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs index bd123a725a7..cba8224b84c 100644 --- a/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs +++ b/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs @@ -1,6 +1,6 @@ use crate::reference::DEREF_ADDROF; use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::implements_trait; use clippy_utils::{get_parent_expr, is_from_proc_macro, is_lint_allowed}; use rustc_errors::Applicability; @@ -73,6 +73,7 @@ impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef { } }) && !is_from_proc_macro(cx, e) + && let Some(deref_text) = deref_target.span.get_source_text(cx) { span_lint_and_then( cx, @@ -83,7 +84,7 @@ impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef { diag.span_suggestion( e.span, "if you would like to reborrow, try removing `&*`", - snippet_opt(cx, deref_target.span).unwrap(), + deref_text.as_str(), Applicability::MachineApplicable, ); @@ -98,7 +99,7 @@ impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef { diag.span_suggestion( e.span, "if you would like to deref, try using `&**`", - format!("&**{}", &snippet_opt(cx, deref_target.span).unwrap()), + format!("&**{deref_text}"), Applicability::MaybeIncorrect, ); }, diff --git a/src/tools/clippy/clippy_lints/src/cargo/common_metadata.rs b/src/tools/clippy/clippy_lints/src/cargo/common_metadata.rs index 3af2d8c0256..fed0aa8b275 100644 --- a/src/tools/clippy/clippy_lints/src/cargo/common_metadata.rs +++ b/src/tools/clippy/clippy_lints/src/cargo/common_metadata.rs @@ -1,5 +1,3 @@ -//! lint on missing cargo common metadata - use cargo_metadata::Metadata; use clippy_utils::diagnostics::span_lint; use rustc_lint::LateContext; diff --git a/src/tools/clippy/clippy_lints/src/cargo/mod.rs b/src/tools/clippy/clippy_lints/src/cargo/mod.rs index 312ad4c2990..96a2b161464 100644 --- a/src/tools/clippy/clippy_lints/src/cargo/mod.rs +++ b/src/tools/clippy/clippy_lints/src/cargo/mod.rs @@ -205,7 +205,7 @@ declare_clippy_lint! { } pub struct Cargo { - allowed_duplicate_crates: &'static FxHashSet, + allowed_duplicate_crates: FxHashSet, ignore_publish: bool, } @@ -221,7 +221,7 @@ impl_lint_pass!(Cargo => [ impl Cargo { pub fn new(conf: &'static Conf) -> Self { Self { - allowed_duplicate_crates: &conf.allowed_duplicate_crates, + allowed_duplicate_crates: conf.allowed_duplicate_crates.iter().cloned().collect(), ignore_publish: conf.cargo_ignore_publish, } } @@ -263,7 +263,7 @@ impl LateLintPass<'_> for Cargo { { match MetadataCommand::new().exec() { Ok(metadata) => { - multiple_crate_versions::check(cx, &metadata, self.allowed_duplicate_crates); + multiple_crate_versions::check(cx, &metadata, &self.allowed_duplicate_crates); }, Err(e) => { for lint in WITH_DEPS_LINTS { diff --git a/src/tools/clippy/clippy_lints/src/cargo/multiple_crate_versions.rs b/src/tools/clippy/clippy_lints/src/cargo/multiple_crate_versions.rs index 2769463c8a5..44cd1f7192f 100644 --- a/src/tools/clippy/clippy_lints/src/cargo/multiple_crate_versions.rs +++ b/src/tools/clippy/clippy_lints/src/cargo/multiple_crate_versions.rs @@ -1,5 +1,3 @@ -//! lint on multiple versions of a crate being used - use cargo_metadata::{DependencyKind, Metadata, Node, Package, PackageId}; use clippy_utils::diagnostics::span_lint; use itertools::Itertools; diff --git a/src/tools/clippy/clippy_lints/src/casts/as_ptr_cast_mut.rs b/src/tools/clippy/clippy_lints/src/casts/as_ptr_cast_mut.rs index f05fd3fcde5..15ecba20a0b 100644 --- a/src/tools/clippy/clippy_lints/src/casts/as_ptr_cast_mut.rs +++ b/src/tools/clippy/clippy_lints/src/casts/as_ptr_cast_mut.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; @@ -19,7 +19,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, && let as_ptr_sig = cx.tcx.fn_sig(as_ptr_did).instantiate_identity() && let Some(first_param_ty) = as_ptr_sig.skip_binder().inputs().iter().next() && let ty::Ref(_, _, Mutability::Not) = first_param_ty.kind() - && let Some(recv) = snippet_opt(cx, receiver.span) + && let Some(recv) = receiver.span.get_source_text(cx) { // `as_mut_ptr` might not exist let applicability = Applicability::MaybeIncorrect; diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs b/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs index bd3acc06f4b..346aed7e9f1 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs @@ -1,7 +1,7 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_in_const_context; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::sugg::Sugg; use clippy_utils::ty::is_isize_or_usize; use rustc_errors::Applicability; @@ -34,7 +34,7 @@ pub(super) fn check( diag.help("an `as` cast can become silently lossy if the types change in the future"); let mut applicability = Applicability::MachineApplicable; let from_sugg = Sugg::hir_with_context(cx, cast_from_expr, expr.span.ctxt(), "", &mut applicability); - let Some(ty) = snippet_opt(cx, hygiene::walk_chain(cast_to_hir.span, expr.span.ctxt())) else { + let Some(ty) = hygiene::walk_chain(cast_to_hir.span, expr.span.ctxt()).get_source_text(cx) else { return; }; match cast_to_hir.kind { diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs index 102fe25fc67..5708aae3f3e 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs @@ -4,7 +4,7 @@ use clippy_utils::expr_or_init; use clippy_utils::source::snippet; use clippy_utils::sugg::Sugg; use clippy_utils::ty::{get_discriminant_value, is_isize_or_usize}; -use rustc_errors::{Applicability, Diag, SuggestionStyle}; +use rustc_errors::{Applicability, Diag}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::LateContext; @@ -190,12 +190,10 @@ fn offer_suggestion( format!("{cast_to_snip}::try_from({})", Sugg::hir(cx, cast_expr, "..")) }; - diag.span_suggestion_with_style( + diag.span_suggestion_verbose( expr.span, "... or use `try_from` and handle the error accordingly", suggestion, Applicability::Unspecified, - // always show the suggestion in a separate line - SuggestionStyle::ShowAlways, ); } diff --git a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast.rs b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast.rs index f263bec1576..dbe03e4ae80 100644 --- a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast.rs +++ b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast.rs @@ -15,7 +15,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, } match cast_from.kind() { - ty::FnDef(..) | ty::FnPtr(_) => { + ty::FnDef(..) | ty::FnPtr(..) => { let mut applicability = Applicability::MaybeIncorrect; let from_snippet = snippet_with_applicability(cx, cast_expr.span, "x", &mut applicability); let to_nbits = utils::int_ty_to_nbits(cast_to, cx.tcx); diff --git a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_any.rs b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_any.rs index 75de53f73ee..b22e8f4ee89 100644 --- a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_any.rs +++ b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_any.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet_with_applicability; -use rustc_errors::{Applicability, SuggestionStyle}; +use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; @@ -14,7 +14,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, _ => { /* continue to checks */ }, } - if let ty::FnDef(..) | ty::FnPtr(_) = cast_from.kind() { + if let ty::FnDef(..) | ty::FnPtr(..) = cast_from.kind() { let mut applicability = Applicability::MaybeIncorrect; let from_snippet = snippet_with_applicability(cx, cast_expr.span, "..", &mut applicability); @@ -24,12 +24,11 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, expr.span, format!("casting function pointer `{from_snippet}` to `{cast_to}`"), |diag| { - diag.span_suggestion_with_style( + diag.span_suggestion_verbose( expr.span, "did you mean to invoke the function?", format!("{from_snippet}() as {cast_to}"), applicability, - SuggestionStyle::ShowAlways, ); }, ); diff --git a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs index 0e11bcfb8ec..dfbae1618ac 100644 --- a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs +++ b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs @@ -14,7 +14,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, _ => return, } match cast_from.kind() { - ty::FnDef(..) | ty::FnPtr(_) => { + ty::FnDef(..) | ty::FnPtr(..) => { let mut applicability = Applicability::MaybeIncorrect; let from_snippet = snippet_with_applicability(cx, cast_expr.span, "x", &mut applicability); diff --git a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs index fb0b0cba6a6..566adc83d69 100644 --- a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs +++ b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::numeric_literal::NumericLiteral; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::{snippet_opt, SpanRangeExt}; use clippy_utils::visitors::{for_each_expr_without_closures, Visitable}; use clippy_utils::{get_parent_expr, is_hir_ty_cfg_dependant, is_ty_alias, path_to_local}; use rustc_ast::{LitFloatType, LitIntType, LitKind}; @@ -104,7 +104,7 @@ pub(super) fn check<'tcx>( let literal_str = &cast_str; if let LitKind::Int(n, _) = lit.node - && let Some(src) = snippet_opt(cx, cast_expr.span) + && let Some(src) = cast_expr.span.get_source_text(cx) && cast_to.is_floating_point() && let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node) && let from_nbits = 128 - n.get().leading_zeros() @@ -131,7 +131,7 @@ pub(super) fn check<'tcx>( | LitKind::Float(_, LitFloatType::Suffixed(_)) if cast_from.kind() == cast_to.kind() => { - if let Some(src) = snippet_opt(cx, cast_expr.span) { + if let Some(src) = cast_expr.span.get_source_text(cx) { if let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node) { lint_unnecessary_cast(cx, expr, num_lit.integer, cast_from, cast_to); return true; @@ -253,7 +253,7 @@ fn is_cast_from_ty_alias<'tcx>(cx: &LateContext<'tcx>, expr: impl Visitable<'tcx let res = cx.qpath_res(&qpath, expr.hir_id); // Function call if let Res::Def(DefKind::Fn, def_id) = res { - let Some(snippet) = snippet_opt(cx, cx.tcx.def_span(def_id)) else { + let Some(snippet) = cx.tcx.def_span(def_id).get_source_text(cx) else { return ControlFlow::Continue(()); }; // This is the worst part of this entire function. This is the only way I know of to diff --git a/src/tools/clippy/clippy_lints/src/casts/zero_ptr.rs b/src/tools/clippy/clippy_lints/src/casts/zero_ptr.rs index 3c1c7d2dc3a..c5c4a28646d 100644 --- a/src/tools/clippy/clippy_lints/src/casts/zero_ptr.rs +++ b/src/tools/clippy/clippy_lints/src/casts/zero_ptr.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::{is_in_const_context, is_integer_literal, std_or_core}; use rustc_errors::Applicability; use rustc_hir::{Expr, Mutability, Ty, TyKind}; @@ -20,7 +20,7 @@ pub fn check(cx: &LateContext<'_>, expr: &Expr<'_>, from: &Expr<'_>, to: &Ty<'_> let sugg = if let TyKind::Infer = mut_ty.ty.kind { format!("{std_or_core}::{sugg_fn}()") - } else if let Some(mut_ty_snip) = snippet_opt(cx, mut_ty.ty.span) { + } else if let Some(mut_ty_snip) = mut_ty.ty.span.get_source_text(cx) { format!("{std_or_core}::{sugg_fn}::<{mut_ty_snip}>()") } else { return; diff --git a/src/tools/clippy/clippy_lints/src/cfg_not_test.rs b/src/tools/clippy/clippy_lints/src/cfg_not_test.rs index b54f392bf2f..d820c1e0720 100644 --- a/src/tools/clippy/clippy_lints/src/cfg_not_test.rs +++ b/src/tools/clippy/clippy_lints/src/cfg_not_test.rs @@ -5,7 +5,7 @@ use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does - /// Checks for usage of `cfg` that excludes code from `test` builds. (i.e., `#{cfg(not(test))]`) + /// Checks for usage of `cfg` that excludes code from `test` builds. (i.e., `#[cfg(not(test))]`) /// /// ### Why is this bad? /// This may give the false impression that a codebase has 100% coverage, yet actually has untested code. diff --git a/src/tools/clippy/clippy_lints/src/checked_conversions.rs b/src/tools/clippy/clippy_lints/src/checked_conversions.rs index 1711565fca8..dd7c34d1e46 100644 --- a/src/tools/clippy/clippy_lints/src/checked_conversions.rs +++ b/src/tools/clippy/clippy_lints/src/checked_conversions.rs @@ -1,5 +1,3 @@ -//! lint on manually implemented checked conversions that could be transformed into `try_from` - use clippy_config::msrvs::{self, Msrv}; use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_sugg; diff --git a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs index 5fa0522e4e5..0099eefbc8d 100644 --- a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs +++ b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs @@ -1,5 +1,3 @@ -//! calculate cognitive complexity and warn about overly complex functions - use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::source::{IntoSpan, SpanRangeExt}; diff --git a/src/tools/clippy/clippy_lints/src/collapsible_if.rs b/src/tools/clippy/clippy_lints/src/collapsible_if.rs index f311c052ad6..e73bfc6ebf7 100644 --- a/src/tools/clippy/clippy_lints/src/collapsible_if.rs +++ b/src/tools/clippy/clippy_lints/src/collapsible_if.rs @@ -1,17 +1,3 @@ -//! Checks for if expressions that contain only an if expression. -//! -//! For example, the lint would catch: -//! -//! ```rust,ignore -//! if x { -//! if y { -//! println!("Hello world"); -//! } -//! } -//! ``` -//! -//! This lint is **warn** by default - use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::{snippet, snippet_block, snippet_block_with_applicability}; use clippy_utils::sugg::Sugg; diff --git a/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs b/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs index eebda3ff76f..c6847411c75 100644 --- a/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs +++ b/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint; -use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item}; +use clippy_utils::ty::{get_type_diagnostic_name, is_type_lang_item}; use clippy_utils::visitors::{for_each_expr, Visitable}; use clippy_utils::{get_enclosing_block, path_to_local_id}; use core::ops::ControlFlow; @@ -7,7 +7,6 @@ use rustc_hir::{Body, ExprKind, HirId, LangItem, LetStmt, Node, PatKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; use rustc_span::symbol::sym; -use rustc_span::Symbol; declare_clippy_lint! { /// ### What it does @@ -44,24 +43,11 @@ declare_clippy_lint! { } declare_lint_pass!(CollectionIsNeverRead => [COLLECTION_IS_NEVER_READ]); -// Add `String` here when it is added to diagnostic items -static COLLECTIONS: [Symbol; 9] = [ - sym::BTreeMap, - sym::BTreeSet, - sym::BinaryHeap, - sym::HashMap, - sym::HashSet, - sym::LinkedList, - sym::Option, - sym::Vec, - sym::VecDeque, -]; - impl<'tcx> LateLintPass<'tcx> for CollectionIsNeverRead { fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx LetStmt<'tcx>) { // Look for local variables whose type is a container. Search surrounding block for read access. if let PatKind::Binding(_, local_id, _, _) = local.pat.kind - && match_acceptable_type(cx, local, &COLLECTIONS) + && match_acceptable_type(cx, local) && let Some(enclosing_block) = get_enclosing_block(cx, local.hir_id) && has_no_read_access(cx, local_id, enclosing_block) { @@ -70,11 +56,22 @@ impl<'tcx> LateLintPass<'tcx> for CollectionIsNeverRead { } } -fn match_acceptable_type(cx: &LateContext<'_>, local: &LetStmt<'_>, collections: &[Symbol]) -> bool { +fn match_acceptable_type(cx: &LateContext<'_>, local: &LetStmt<'_>) -> bool { let ty = cx.typeck_results().pat_ty(local.pat); - collections.iter().any(|&sym| is_type_diagnostic_item(cx, ty, sym)) - // String type is a lang item but not a diagnostic item for now so we need a separate check - || is_type_lang_item(cx, ty, LangItem::String) + matches!( + get_type_diagnostic_name(cx, ty), + Some( + sym::BTreeMap + | sym::BTreeSet + | sym::BinaryHeap + | sym::HashMap + | sym::HashSet + | sym::LinkedList + | sym::Option + | sym::Vec + | sym::VecDeque + ) + ) || is_type_lang_item(cx, ty, LangItem::String) } fn has_no_read_access<'tcx, T: Visitable<'tcx>>(cx: &LateContext<'tcx>, id: HirId, block: T) -> bool { diff --git a/src/tools/clippy/clippy_lints/src/create_dir.rs b/src/tools/clippy/clippy_lints/src/create_dir.rs index b49a977dbea..24570d8f440 100644 --- a/src/tools/clippy/clippy_lints/src/create_dir.rs +++ b/src/tools/clippy/clippy_lints/src/create_dir.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet_with_applicability; -use rustc_errors::{Applicability, SuggestionStyle}; +use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; @@ -46,7 +46,7 @@ impl LateLintPass<'_> for CreateDir { "calling `std::fs::create_dir` where there may be a better way", |diag| { let mut app = Applicability::MaybeIncorrect; - diag.span_suggestion_with_style( + diag.span_suggestion_verbose( expr.span, "consider calling `std::fs::create_dir_all` instead", format!( @@ -54,7 +54,6 @@ impl LateLintPass<'_> for CreateDir { snippet_with_applicability(cx, arg.span, "..", &mut app) ), app, - SuggestionStyle::ShowAlways, ); }, ); diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs index 3fb083dd833..60e51713173 100644 --- a/src/tools/clippy/clippy_lints/src/declared_lints.rs +++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs @@ -2,7 +2,7 @@ // Use that command to update this file and do not edit by hand. // Manual edits will be overwritten. -pub(crate) static LINTS: &[&crate::LintInfo] = &[ +pub static LINTS: &[&crate::LintInfo] = &[ #[cfg(feature = "internal")] crate::utils::internal_lints::almost_standard_lint_formulation::ALMOST_STANDARD_LINT_FORMULATION_INFO, #[cfg(feature = "internal")] @@ -22,8 +22,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ #[cfg(feature = "internal")] crate::utils::internal_lints::lint_without_lint_pass::MISSING_CLIPPY_VERSION_ATTRIBUTE_INFO, #[cfg(feature = "internal")] - crate::utils::internal_lints::metadata_collector::METADATA_COLLECTOR_INFO, - #[cfg(feature = "internal")] crate::utils::internal_lints::msrv_attr_impl::MISSING_MSRV_ATTR_IMPL_INFO, #[cfg(feature = "internal")] crate::utils::internal_lints::outer_expn_data_pass::OUTER_EXPN_EXPN_DATA_INFO, @@ -146,6 +144,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::doc::NEEDLESS_DOCTEST_MAIN_INFO, crate::doc::SUSPICIOUS_DOC_COMMENTS_INFO, crate::doc::TEST_ATTR_IN_DOCTEST_INFO, + crate::doc::TOO_LONG_FIRST_DOC_PARAGRAPH_INFO, crate::doc::UNNECESSARY_SAFETY_DOC_INFO, crate::double_parens::DOUBLE_PARENS_INFO, crate::drop_forget_ref::DROP_NON_DROP_INFO, diff --git a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs index a74b3a8c836..05c3cd3c814 100644 --- a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs +++ b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs @@ -236,7 +236,7 @@ fn fn_sig_opt<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option Some(cx.tcx.fn_sig(*def_id).instantiate_identity()), - ty::FnPtr(fn_sig) => Some(*fn_sig), + ty::FnPtr(sig_tys, hdr) => Some(sig_tys.with(*hdr)), _ => None, } } diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index d0cb2488468..0e55d3db469 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -872,7 +872,7 @@ impl TyCoercionStability { | ty::Pat(..) | ty::Float(_) | ty::RawPtr(..) - | ty::FnPtr(_) + | ty::FnPtr(..) | ty::Str | ty::Slice(..) | ty::Adt(..) diff --git a/src/tools/clippy/clippy_lints/src/doc/lazy_continuation.rs b/src/tools/clippy/clippy_lints/src/doc/lazy_continuation.rs index bd1cc46e185..771bcac2441 100644 --- a/src/tools/clippy/clippy_lints/src/doc/lazy_continuation.rs +++ b/src/tools/clippy/clippy_lints/src/doc/lazy_continuation.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use itertools::Itertools; -use rustc_errors::{Applicability, SuggestionStyle}; +use rustc_errors::Applicability; use rustc_lint::LateContext; use rustc_span::{BytePos, Span}; use std::ops::Range; @@ -59,12 +59,11 @@ pub(super) fn check( && (doc_comment == "///" || doc_comment == "//!") { // suggest filling in a blank line - diag.span_suggestion_with_style( + diag.span_suggestion_verbose( line_break_span.shrink_to_lo(), "if this should be its own paragraph, add a blank doc comment line", format!("\n{doc_comment}"), Applicability::MaybeIncorrect, - SuggestionStyle::ShowAlways, ); if ccount > 0 || blockquote_level > 0 { diag.help("if this not intended to be a quote at all, escape it with `\\>`"); @@ -79,12 +78,11 @@ pub(super) fn check( if ccount == 0 && blockquote_level == 0 { // simpler suggestion style for indentation let indent = list_indentation - lcount; - diag.span_suggestion_with_style( + diag.span_suggestion_verbose( span.shrink_to_hi(), "indent this line", std::iter::repeat(" ").take(indent).join(""), Applicability::MaybeIncorrect, - SuggestionStyle::ShowAlways, ); diag.help("if this is supposed to be its own paragraph, add a blank line"); return; @@ -107,12 +105,11 @@ pub(super) fn check( suggested.push_str(text); } } - diag.span_suggestion_with_style( + diag.span_suggestion_verbose( span, "add markers to start of line", suggested, Applicability::MachineApplicable, - SuggestionStyle::ShowAlways, ); diag.help("if this not intended to be a quote at all, escape it with `\\>`"); }); diff --git a/src/tools/clippy/clippy_lints/src/doc/markdown.rs b/src/tools/clippy/clippy_lints/src/doc/markdown.rs index 41c0bcd55ad..8cdaba88e50 100644 --- a/src/tools/clippy/clippy_lints/src/doc/markdown.rs +++ b/src/tools/clippy/clippy_lints/src/doc/markdown.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::snippet_with_applicability; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::{Applicability, SuggestionStyle}; +use rustc_errors::Applicability; use rustc_lint::LateContext; use rustc_span::{BytePos, Pos, Span}; use url::Url; @@ -92,6 +92,10 @@ fn check_word(cx: &LateContext<'_>, word: &str, span: Span, code_level: isize, b && matches!(prefix.chars().last(), Some('S' | 'X')) { prefix + } else if let Some(prefix) = s.strip_suffix("ified") + && prefix.chars().all(|c| c.is_ascii_uppercase()) + { + prefix } else { s.strip_suffix('s').unwrap_or(s) }; @@ -133,24 +137,15 @@ fn check_word(cx: &LateContext<'_>, word: &str, span: Span, code_level: isize, b } if has_underscore(word) || word.contains("::") || is_camel_case(word) || word.ends_with("()") { - let mut applicability = Applicability::MachineApplicable; - span_lint_and_then( cx, DOC_MARKDOWN, span, "item in documentation is missing backticks", |diag| { + let mut applicability = Applicability::MachineApplicable; let snippet = snippet_with_applicability(cx, span, "..", &mut applicability); - diag.span_suggestion_with_style( - span, - "try", - format!("`{snippet}`"), - applicability, - // always show the suggestion in a separate line, since the - // inline presentation adds another pair of backticks - SuggestionStyle::ShowAlways, - ); + diag.span_suggestion_verbose(span, "try", format!("`{snippet}`"), applicability); }, ); } diff --git a/src/tools/clippy/clippy_lints/src/doc/mod.rs b/src/tools/clippy/clippy_lints/src/doc/mod.rs index d7b3a7c74f3..790579b21c9 100644 --- a/src/tools/clippy/clippy_lints/src/doc/mod.rs +++ b/src/tools/clippy/clippy_lints/src/doc/mod.rs @@ -1,4 +1,6 @@ mod lazy_continuation; +mod too_long_first_doc_paragraph; + use clippy_config::Conf; use clippy_utils::attrs::is_doc_hidden; use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; @@ -309,7 +311,7 @@ declare_clippy_lint! { /// ### Known problems /// Inner doc comments can only appear before items, so there are certain cases where the suggestion /// made by this lint is not valid code. For example: - /// ```rs + /// ```rust /// fn foo() {} /// ///! /// fn bar() {} @@ -422,15 +424,47 @@ declare_clippy_lint! { "require every line of a paragraph to be indented and marked" } +declare_clippy_lint! { + /// ### What it does + /// Checks if the first line in the documentation of items listed in module page is too long. + /// + /// ### Why is this bad? + /// Documentation will show the first paragraph of the doscstring in the summary page of a + /// module, so having a nice, short summary in the first paragraph is part of writing good docs. + /// + /// ### Example + /// ```no_run + /// /// A very short summary. + /// /// A much longer explanation that goes into a lot more detail about + /// /// how the thing works, possibly with doclinks and so one, + /// /// and probably spanning a many rows. + /// struct Foo {} + /// ``` + /// Use instead: + /// ```no_run + /// /// A very short summary. + /// /// + /// /// A much longer explanation that goes into a lot more detail about + /// /// how the thing works, possibly with doclinks and so one, + /// /// and probably spanning a many rows. + /// struct Foo {} + /// ``` + #[clippy::version = "1.81.0"] + pub TOO_LONG_FIRST_DOC_PARAGRAPH, + style, + "ensure that the first line of a documentation paragraph isn't too long" +} + +#[derive(Clone)] pub struct Documentation { - valid_idents: &'static FxHashSet, + valid_idents: FxHashSet, check_private_items: bool, } impl Documentation { pub fn new(conf: &'static Conf) -> Self { Self { - valid_idents: &conf.doc_valid_idents, + valid_idents: conf.doc_valid_idents.iter().cloned().collect(), check_private_items: conf.check_private_items, } } @@ -448,48 +482,60 @@ impl_lint_pass!(Documentation => [ SUSPICIOUS_DOC_COMMENTS, EMPTY_DOCS, DOC_LAZY_CONTINUATION, + TOO_LONG_FIRST_DOC_PARAGRAPH, ]); impl<'tcx> LateLintPass<'tcx> for Documentation { fn check_attributes(&mut self, cx: &LateContext<'tcx>, attrs: &'tcx [Attribute]) { - let Some(headers) = check_attrs(cx, self.valid_idents, attrs) else { + let Some(headers) = check_attrs(cx, &self.valid_idents, attrs) else { return; }; match cx.tcx.hir_node(cx.last_node_with_lint_attrs) { - Node::Item(item) => match item.kind { - ItemKind::Fn(sig, _, body_id) => { - if !(is_entrypoint_fn(cx, item.owner_id.to_def_id()) || in_external_macro(cx.tcx.sess, item.span)) { - let body = cx.tcx.hir().body(body_id); + Node::Item(item) => { + too_long_first_doc_paragraph::check( + cx, + item, + attrs, + headers.first_paragraph_len, + self.check_private_items, + ); + match item.kind { + ItemKind::Fn(sig, _, body_id) => { + if !(is_entrypoint_fn(cx, item.owner_id.to_def_id()) + || in_external_macro(cx.tcx.sess, item.span)) + { + let body = cx.tcx.hir().body(body_id); - let panic_info = FindPanicUnwrap::find_span(cx, cx.tcx.typeck(item.owner_id), body.value); - missing_headers::check( + let panic_info = FindPanicUnwrap::find_span(cx, cx.tcx.typeck(item.owner_id), body.value); + missing_headers::check( + cx, + item.owner_id, + sig, + headers, + Some(body_id), + panic_info, + self.check_private_items, + ); + } + }, + ItemKind::Trait(_, unsafety, ..) => match (headers.safety, unsafety) { + (false, Safety::Unsafe) => span_lint( cx, - item.owner_id, - sig, - headers, - Some(body_id), - panic_info, - self.check_private_items, - ); - } - }, - ItemKind::Trait(_, unsafety, ..) => match (headers.safety, unsafety) { - (false, Safety::Unsafe) => span_lint( - cx, - MISSING_SAFETY_DOC, - cx.tcx.def_span(item.owner_id), - "docs for unsafe trait missing `# Safety` section", - ), - (true, Safety::Safe) => span_lint( - cx, - UNNECESSARY_SAFETY_DOC, - cx.tcx.def_span(item.owner_id), - "docs for safe trait have unnecessary `# Safety` section", - ), + MISSING_SAFETY_DOC, + cx.tcx.def_span(item.owner_id), + "docs for unsafe trait missing `# Safety` section", + ), + (true, Safety::Safe) => span_lint( + cx, + UNNECESSARY_SAFETY_DOC, + cx.tcx.def_span(item.owner_id), + "docs for safe trait have unnecessary `# Safety` section", + ), + _ => (), + }, _ => (), - }, - _ => (), + } }, Node::TraitItem(trait_item) => { if let TraitItemKind::Fn(sig, ..) = trait_item.kind @@ -547,6 +593,7 @@ struct DocHeaders { safety: bool, errors: bool, panics: bool, + first_paragraph_len: usize, } /// Does some pre-processing on raw, desugared `#[doc]` attributes such as parsing them and @@ -653,6 +700,7 @@ fn check_doc<'a, Events: Iterator, Range, Range { if let End(TagEnd::Heading(_)) = event { diff --git a/src/tools/clippy/clippy_lints/src/doc/too_long_first_doc_paragraph.rs b/src/tools/clippy/clippy_lints/src/doc/too_long_first_doc_paragraph.rs new file mode 100644 index 00000000000..7bb3bb12f2c --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/doc/too_long_first_doc_paragraph.rs @@ -0,0 +1,91 @@ +use rustc_ast::ast::Attribute; +use rustc_errors::Applicability; +use rustc_hir::{Item, ItemKind}; +use rustc_lint::LateContext; + +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::is_from_proc_macro; +use clippy_utils::source::snippet_opt; + +use super::TOO_LONG_FIRST_DOC_PARAGRAPH; + +pub(super) fn check( + cx: &LateContext<'_>, + item: &Item<'_>, + attrs: &[Attribute], + mut first_paragraph_len: usize, + check_private_items: bool, +) { + if !check_private_items && !cx.effective_visibilities.is_exported(item.owner_id.def_id) { + return; + } + if first_paragraph_len <= 200 + || !matches!( + item.kind, + // This is the list of items which can be documented AND are displayed on the module + // page. So associated items or impl blocks are not part of this list. + ItemKind::Static(..) + | ItemKind::Const(..) + | ItemKind::Fn(..) + | ItemKind::Macro(..) + | ItemKind::Mod(..) + | ItemKind::TyAlias(..) + | ItemKind::Enum(..) + | ItemKind::Struct(..) + | ItemKind::Union(..) + | ItemKind::Trait(..) + | ItemKind::TraitAlias(..) + ) + { + return; + } + + let mut spans = Vec::new(); + let mut should_suggest_empty_doc = false; + + for attr in attrs { + if let Some(doc) = attr.doc_str() { + spans.push(attr.span); + let doc = doc.as_str(); + let doc = doc.trim(); + if spans.len() == 1 { + // We make this suggestion only if the first doc line ends with a punctuation + // because it might just need to add an empty line with `///`. + should_suggest_empty_doc = doc.ends_with('.') || doc.ends_with('!') || doc.ends_with('?'); + } + let len = doc.chars().count(); + if len >= first_paragraph_len { + break; + } + first_paragraph_len -= len; + } + } + + let &[first_span, .., last_span] = spans.as_slice() else { + return; + }; + if is_from_proc_macro(cx, item) { + return; + } + + span_lint_and_then( + cx, + TOO_LONG_FIRST_DOC_PARAGRAPH, + first_span.with_hi(last_span.lo()), + "first doc comment paragraph is too long", + |diag| { + if should_suggest_empty_doc + && let Some(second_span) = spans.get(1) + && let new_span = first_span.with_hi(second_span.lo()).with_lo(first_span.hi()) + && let Some(snippet) = snippet_opt(cx, new_span) + { + diag.span_suggestion( + new_span, + "add an empty line", + format!("{snippet}///\n"), + Applicability::MachineApplicable, + ); + } + }, + ); +} diff --git a/src/tools/clippy/clippy_lints/src/else_if_without_else.rs b/src/tools/clippy/clippy_lints/src/else_if_without_else.rs index 02f9c2c3648..5315f55ba38 100644 --- a/src/tools/clippy/clippy_lints/src/else_if_without_else.rs +++ b/src/tools/clippy/clippy_lints/src/else_if_without_else.rs @@ -1,5 +1,3 @@ -//! Lint on if expressions with an else if, but without a final else branch. - use clippy_utils::diagnostics::span_lint_and_then; use rustc_ast::ast::{Expr, ExprKind}; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; diff --git a/src/tools/clippy/clippy_lints/src/empty_enum.rs b/src/tools/clippy/clippy_lints/src/empty_enum.rs index 1869faab1d3..f4c55738cb8 100644 --- a/src/tools/clippy/clippy_lints/src/empty_enum.rs +++ b/src/tools/clippy/clippy_lints/src/empty_enum.rs @@ -1,5 +1,3 @@ -//! lint when there is an enum with no variants - use clippy_utils::diagnostics::span_lint_and_help; use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; diff --git a/src/tools/clippy/clippy_lints/src/enum_clike.rs b/src/tools/clippy/clippy_lints/src/enum_clike.rs index e54cd248ead..4755cefe784 100644 --- a/src/tools/clippy/clippy_lints/src/enum_clike.rs +++ b/src/tools/clippy/clippy_lints/src/enum_clike.rs @@ -1,6 +1,3 @@ -//! lint on C-like enums that are `repr(isize/usize)` and have values that -//! don't fit into an `i32` - use clippy_utils::consts::{mir_to_const, Constant}; use clippy_utils::diagnostics::span_lint; use rustc_hir::{Item, ItemKind}; diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs index 5a7226d590c..cabc6592258 100644 --- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs +++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::higher::VecArgs; use clippy_utils::source::snippet_opt; -use clippy_utils::ty::type_diagnostic_name; +use clippy_utils::ty::get_type_diagnostic_name; use clippy_utils::usage::{local_used_after_expr, local_used_in}; use clippy_utils::{get_path_from_caller_to_method_type, is_adjusted, path_to_local, path_to_local_id}; use rustc_errors::Applicability; @@ -139,7 +139,7 @@ fn check_clousure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tc { let callee_ty_raw = typeck.expr_ty(callee); let callee_ty = callee_ty_raw.peel_refs(); - if matches!(type_diagnostic_name(cx, callee_ty), Some(sym::Arc | sym::Rc)) + if matches!(get_type_diagnostic_name(cx, callee_ty), Some(sym::Arc | sym::Rc)) || !check_inputs(typeck, body.params, None, args) { return; @@ -158,7 +158,7 @@ fn check_clousure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tc cx.tcx.fn_sig(def).skip_binder().skip_binder() }, - ty::FnPtr(sig) => sig.skip_binder(), + ty::FnPtr(sig_tys, hdr) => sig_tys.with(*hdr).skip_binder(), ty::Closure(_, subs) => cx .tcx .signature_unclosure(subs.as_closure().sig(), Safety::Safe) diff --git a/src/tools/clippy/clippy_lints/src/float_literal.rs b/src/tools/clippy/clippy_lints/src/float_literal.rs index f095c1add91..012ad8e1a22 100644 --- a/src/tools/clippy/clippy_lints/src/float_literal.rs +++ b/src/tools/clippy/clippy_lints/src/float_literal.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::numeric_literal; use rustc_ast::ast::{self, LitFloatType, LitKind}; -use rustc_errors::{Applicability, SuggestionStyle}; +use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, FloatTy}; @@ -117,12 +117,11 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral { if type_suffix.is_none() { float_str.push_str(".0"); } - diag.span_suggestion_with_style( + diag.span_suggestion_verbose( expr.span, "consider changing the type or replacing it with", numeric_literal::format(&float_str, type_suffix, true), Applicability::MachineApplicable, - SuggestionStyle::ShowAlways, ); }, ); @@ -134,12 +133,11 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral { expr.span, "float has excessive precision", |diag| { - diag.span_suggestion_with_style( + diag.span_suggestion_verbose( expr.span, "consider changing the type or truncating it to", numeric_literal::format(&float_str, type_suffix, true), Applicability::MachineApplicable, - SuggestionStyle::ShowAlways, ); }, ); diff --git a/src/tools/clippy/clippy_lints/src/format.rs b/src/tools/clippy/clippy_lints/src/format.rs index 0b248f784b7..4dedff69b9a 100644 --- a/src/tools/clippy/clippy_lints/src/format.rs +++ b/src/tools/clippy/clippy_lints/src/format.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::macros::{find_format_arg_expr, root_macro_call_first_node, FormatArgsStorage}; -use clippy_utils::source::{snippet_opt, snippet_with_context}; +use clippy_utils::source::{snippet_with_context, SpanRangeExt}; use clippy_utils::sugg::Sugg; use rustc_ast::{FormatArgsPiece, FormatOptions, FormatTrait}; use rustc_errors::Applicability; @@ -65,7 +65,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessFormat { ([], []) => span_useless_format_empty(cx, call_site, "String::new()".to_owned(), applicability), ([], [_]) => { // Simulate macro expansion, converting {{ and }} to { and }. - let Some(snippet) = snippet_opt(cx, format_args.span) else { + let Some(snippet) = format_args.span.get_source_text(cx) else { return; }; let s_expand = snippet.replace("{{", "{").replace("}}", "}"); @@ -73,7 +73,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessFormat { span_useless_format(cx, call_site, sugg, applicability); }, ([arg], [piece]) => { - if let Ok(value) = find_format_arg_expr(expr, arg) + if let Some(value) = find_format_arg_expr(expr, arg) && let FormatArgsPiece::Placeholder(placeholder) = piece && placeholder.format_trait == FormatTrait::Display && placeholder.format_options == FormatOptions::default() diff --git a/src/tools/clippy/clippy_lints/src/format_args.rs b/src/tools/clippy/clippy_lints/src/format_args.rs index a31d5cb6ec7..020c0c5440d 100644 --- a/src/tools/clippy/clippy_lints/src/format_args.rs +++ b/src/tools/clippy/clippy_lints/src/format_args.rs @@ -7,7 +7,7 @@ use clippy_utils::macros::{ find_format_arg_expr, format_arg_removal_span, format_placeholder_format_span, is_assert_macro, is_format_macro, is_panic, matching_root_macro_call, root_macro_call_first_node, FormatArgsStorage, FormatParamUsage, MacroCall, }; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::{implements_trait, is_type_lang_item}; use itertools::Itertools; use rustc_ast::{ @@ -224,13 +224,11 @@ impl<'a, 'tcx> FormatArgsExpr<'a, 'tcx> { if let FormatArgsPiece::Placeholder(placeholder) = piece && let Ok(index) = placeholder.argument.index && let Some(arg) = self.format_args.arguments.all_args().get(index) + && let Some(arg_expr) = find_format_arg_expr(self.expr, arg) { - let arg_expr = find_format_arg_expr(self.expr, arg); - self.check_unused_format_specifier(placeholder, arg_expr); - if let Ok(arg_expr) = arg_expr - && placeholder.format_trait == FormatTrait::Display + if placeholder.format_trait == FormatTrait::Display && placeholder.format_options == FormatOptions::default() && !self.is_aliased(index) { @@ -242,28 +240,13 @@ impl<'a, 'tcx> FormatArgsExpr<'a, 'tcx> { } } - fn check_unused_format_specifier( - &self, - placeholder: &FormatPlaceholder, - arg_expr: Result<&Expr<'_>, &rustc_ast::Expr>, - ) { - let ty_or_ast_expr = arg_expr.map(|expr| self.cx.typeck_results().expr_ty(expr).peel_refs()); - - let is_format_args = match ty_or_ast_expr { - Ok(ty) => is_type_lang_item(self.cx, ty, LangItem::FormatArguments), - Err(expr) => matches!(expr.peel_parens_and_refs().kind, rustc_ast::ExprKind::FormatArgs(_)), - }; - + fn check_unused_format_specifier(&self, placeholder: &FormatPlaceholder, arg: &Expr<'_>) { let options = &placeholder.format_options; - let arg_span = match arg_expr { - Ok(expr) => expr.span, - Err(expr) => expr.span, - }; - if let Some(placeholder_span) = placeholder.span - && is_format_args && *options != FormatOptions::default() + && let ty = self.cx.typeck_results().expr_ty(arg).peel_refs() + && is_type_lang_item(self.cx, ty, LangItem::FormatArguments) { span_lint_and_then( self.cx, @@ -274,7 +257,7 @@ impl<'a, 'tcx> FormatArgsExpr<'a, 'tcx> { let mut suggest_format = |spec| { let message = format!("for the {spec} to apply consider using `format!()`"); - if let Some(mac_call) = matching_root_macro_call(self.cx, arg_span, sym::format_args_macro) { + if let Some(mac_call) = matching_root_macro_call(self.cx, arg.span, sym::format_args_macro) { diag.span_suggestion( self.cx.sess().source_map().span_until_char(mac_call.span, '!'), message, @@ -424,7 +407,7 @@ impl<'a, 'tcx> FormatArgsExpr<'a, 'tcx> { count_needed_derefs(receiver_ty, cx.typeck_results().expr_adjustments(receiver).iter()) && implements_trait(cx, target, display_trait_id, &[]) && let Some(sized_trait_id) = cx.tcx.lang_items().sized_trait() - && let Some(receiver_snippet) = snippet_opt(cx, receiver.span.source_callsite()) + && let Some(receiver_snippet) = receiver.span.source_callsite().get_source_text(cx) { let needs_ref = !implements_trait(cx, receiver_ty, sized_trait_id, &[]); if n_needed_derefs == 0 && !needs_ref { diff --git a/src/tools/clippy/clippy_lints/src/format_impl.rs b/src/tools/clippy/clippy_lints/src/format_impl.rs index e6f27cb82d1..7cd12ac7db8 100644 --- a/src/tools/clippy/clippy_lints/src/format_impl.rs +++ b/src/tools/clippy/clippy_lints/src/format_impl.rs @@ -196,7 +196,7 @@ impl<'a, 'tcx> FormatImplExpr<'a, 'tcx> { && trait_name == self.format_trait_impl.name && let Ok(index) = placeholder.argument.index && let Some(arg) = format_args.arguments.all_args().get(index) - && let Ok(arg_expr) = find_format_arg_expr(self.expr, arg) + && let Some(arg_expr) = find_format_arg_expr(self.expr, arg) { self.check_format_arg_self(arg_expr); } diff --git a/src/tools/clippy/clippy_lints/src/from_over_into.rs b/src/tools/clippy/clippy_lints/src/from_over_into.rs index 1c1d8b57bc4..b84bf7c821c 100644 --- a/src/tools/clippy/clippy_lints/src/from_over_into.rs +++ b/src/tools/clippy/clippy_lints/src/from_over_into.rs @@ -3,7 +3,7 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::macros::span_is_local; use clippy_utils::path_def_id; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_path, Visitor}; use rustc_hir::{ @@ -178,8 +178,8 @@ fn convert_to_from( return None; }; - let from = snippet_opt(cx, self_ty.span)?; - let into = snippet_opt(cx, target_ty.span)?; + let from = self_ty.span.get_source_text(cx)?; + let into = target_ty.span.get_source_text(cx)?; let mut suggestions = vec![ // impl Into for U -> impl From for U @@ -187,10 +187,10 @@ fn convert_to_from( (into_trait_seg.ident.span, String::from("From")), // impl Into for U -> impl Into for U // ~ ~ - (target_ty.span, from.clone()), + (target_ty.span, from.to_owned()), // impl Into for U -> impl Into for T // ~ ~ - (self_ty.span, into), + (self_ty.span, into.to_owned()), // fn into(self) -> T -> fn from(self) -> T // ~~~~ ~~~~ (impl_item.ident.span, String::from("from")), @@ -223,7 +223,7 @@ fn convert_to_from( } for span in finder.upper { - suggestions.push((span, from.clone())); + suggestions.push((span, from.to_owned())); } for span in finder.lower { suggestions.push((span, String::from("val"))); diff --git a/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs b/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs index 6ab7bbc2dfc..e5fa67d6964 100644 --- a/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs +++ b/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs @@ -22,8 +22,8 @@ declare_clippy_lint! { /// /// ### Known problems /// - /// This lint may suggest using (&).parse() instead of .parse() directly - /// in some cases, which is correct but adds unnecessary complexity to the code. + /// This lint may suggest using `(&).parse()` instead of `.parse()` + /// directly in some cases, which is correct but adds unnecessary complexity to the code. /// /// ### Example /// ```ignore diff --git a/src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs b/src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs index cf85c74e688..05e341e06fd 100644 --- a/src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs +++ b/src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs @@ -1,6 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_in_test; +use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::intravisit::FnKind; use rustc_hir::{Body, GenericParam, Generics, HirId, ImplItem, ImplItemKind, TraitItem, TraitItemKind}; @@ -18,20 +19,18 @@ fn report(cx: &LateContext<'_>, param: &GenericParam<'_>, generics: &Generics<'_ |diag| { if let Some(gen_span) = generics.span_for_param_suggestion() { // If there's already a generic param with the same bound, do not lint **this** suggestion. - diag.span_suggestion_with_style( + diag.span_suggestion_verbose( gen_span, "add a type parameter", format!(", {{ /* Generic name */ }}: {}", ¶m.name.ident().as_str()[5..]), - rustc_errors::Applicability::HasPlaceholders, - rustc_errors::SuggestionStyle::ShowAlways, + Applicability::HasPlaceholders, ); } else { - diag.span_suggestion_with_style( + diag.span_suggestion_verbose( generics.span, "add a type parameter", format!("<{{ /* Generic name */ }}: {}>", ¶m.name.ident().as_str()[5..]), - rustc_errors::Applicability::HasPlaceholders, - rustc_errors::SuggestionStyle::ShowAlways, + Applicability::HasPlaceholders, ); } }, diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs index b179d7b5249..93828121047 100644 --- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs +++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs @@ -8,11 +8,11 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, Ty}; -use rustc_span::{sym, Span, Symbol}; +use rustc_span::{sym, Span}; use clippy_utils::attrs::is_proc_macro; use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then}; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::is_must_use_ty; use clippy_utils::visitors::for_each_expr_without_closures; use clippy_utils::{return_ty, trait_ref_of_method}; @@ -129,9 +129,9 @@ fn check_needless_must_use( cx, DOUBLE_MUST_USE, fn_header_span, - "this function has an empty `#[must_use]` attribute, but returns a type already marked as `#[must_use]`", + "this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]`", None, - "either add some descriptive text or remove the attribute", + "either add some descriptive message or remove the attribute", ); } } @@ -155,7 +155,7 @@ fn check_must_use_candidate<'tcx>( return; } span_lint_and_then(cx, MUST_USE_CANDIDATE, fn_span, msg, |diag| { - if let Some(snippet) = snippet_opt(cx, fn_span) { + if let Some(snippet) = fn_span.get_source_text(cx) { diag.span_suggestion( fn_span, "add the attribute", @@ -193,17 +193,13 @@ fn is_mutable_pat(cx: &LateContext<'_>, pat: &hir::Pat<'_>, tys: &mut DefIdSet) } } -static KNOWN_WRAPPER_TYS: &[Symbol] = &[sym::Rc, sym::Arc]; - fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, tys: &mut DefIdSet) -> bool { match *ty.kind() { // primitive types are never mutable ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => false, ty::Adt(adt, args) => { tys.insert(adt.did()) && !ty.is_freeze(cx.tcx, cx.param_env) - || KNOWN_WRAPPER_TYS - .iter() - .any(|&sym| cx.tcx.is_diagnostic_item(sym, adt.did())) + || matches!(cx.tcx.get_diagnostic_name(adt.did()), Some(sym::Rc | sym::Arc)) && args.types().any(|ty| is_mutable_ty(cx, ty, tys)) }, ty::Tuple(args) => args.iter().any(|ty| is_mutable_ty(cx, ty, tys)), diff --git a/src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs b/src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs index 586ca58d60d..0f5ce340c44 100644 --- a/src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs +++ b/src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs @@ -1,12 +1,11 @@ +use clippy_utils::diagnostics::span_lint; +use clippy_utils::source::SpanRangeExt; use rustc_hir as hir; use rustc_hir::intravisit::FnKind; use rustc_lint::{LateContext, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_span::Span; -use clippy_utils::diagnostics::span_lint; -use clippy_utils::source::snippet_opt; - use super::TOO_MANY_LINES; pub(super) fn check_fn( @@ -22,57 +21,57 @@ pub(super) fn check_fn( return; } - let Some(code_snippet) = snippet_opt(cx, body.value.span) else { - return; - }; let mut line_count: u64 = 0; - let mut in_comment = false; - let mut code_in_line; + let too_many = body.value.span.check_source_text(cx, |src| { + let mut in_comment = false; + let mut code_in_line; - let function_lines = if matches!(body.value.kind, hir::ExprKind::Block(..)) - && code_snippet.as_bytes().first().copied() == Some(b'{') - && code_snippet.as_bytes().last().copied() == Some(b'}') - { - // Removing the braces from the enclosing block - &code_snippet[1..code_snippet.len() - 1] - } else { - &code_snippet - } - .trim() // Remove leading and trailing blank lines - .lines(); + let function_lines = if matches!(body.value.kind, hir::ExprKind::Block(..)) + && src.as_bytes().first().copied() == Some(b'{') + && src.as_bytes().last().copied() == Some(b'}') + { + // Removing the braces from the enclosing block + &src[1..src.len() - 1] + } else { + src + } + .trim() // Remove leading and trailing blank lines + .lines(); - for mut line in function_lines { - code_in_line = false; - loop { - line = line.trim_start(); - if line.is_empty() { + for mut line in function_lines { + code_in_line = false; + loop { + line = line.trim_start(); + if line.is_empty() { + break; + } + if in_comment { + if let Some(i) = line.find("*/") { + line = &line[i + 2..]; + in_comment = false; + continue; + } + } else { + let multi_idx = line.find("/*").unwrap_or(line.len()); + let single_idx = line.find("//").unwrap_or(line.len()); + code_in_line |= multi_idx > 0 && single_idx > 0; + // Implies multi_idx is below line.len() + if multi_idx < single_idx { + line = &line[multi_idx + 2..]; + in_comment = true; + continue; + } + } break; } - if in_comment { - if let Some(i) = line.find("*/") { - line = &line[i + 2..]; - in_comment = false; - continue; - } - } else { - let multi_idx = line.find("/*").unwrap_or(line.len()); - let single_idx = line.find("//").unwrap_or(line.len()); - code_in_line |= multi_idx > 0 && single_idx > 0; - // Implies multi_idx is below line.len() - if multi_idx < single_idx { - line = &line[multi_idx + 2..]; - in_comment = true; - continue; - } + if code_in_line { + line_count += 1; } - break; } - if code_in_line { - line_count += 1; - } - } + line_count > too_many_lines_threshold + }); - if line_count > too_many_lines_threshold { + if too_many { span_lint( cx, TOO_MANY_LINES, diff --git a/src/tools/clippy/clippy_lints/src/if_not_else.rs b/src/tools/clippy/clippy_lints/src/if_not_else.rs index 0ebd8d0c237..120c5396a1c 100644 --- a/src/tools/clippy/clippy_lints/src/if_not_else.rs +++ b/src/tools/clippy/clippy_lints/src/if_not_else.rs @@ -1,6 +1,3 @@ -//! lint on if branches that could be swapped so no `!` operation is necessary -//! on the condition - use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::is_else_clause; diff --git a/src/tools/clippy/clippy_lints/src/implicit_return.rs b/src/tools/clippy/clippy_lints/src/implicit_return.rs index b926e1e62ba..ba06567b957 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_return.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_return.rs @@ -3,7 +3,7 @@ use clippy_utils::source::{snippet_with_applicability, snippet_with_context, wal use clippy_utils::visitors::for_each_expr_without_closures; use clippy_utils::{get_async_fn_body, is_async_fn, is_from_proc_macro}; use core::ops::ControlFlow; -use rustc_errors::{Applicability, SuggestionStyle}; +use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, FnRetTy, HirId}; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -54,13 +54,7 @@ fn lint_return(cx: &LateContext<'_>, emission_place: HirId, span: Span) { |diag| { let mut app = Applicability::MachineApplicable; let snip = snippet_with_applicability(cx, span, "..", &mut app); - diag.span_suggestion_with_style( - span, - "add `return` as shown", - format!("return {snip}"), - app, - SuggestionStyle::ShowAlways, - ); + diag.span_suggestion_verbose(span, "add `return` as shown", format!("return {snip}"), app); }, ); } @@ -75,12 +69,11 @@ fn lint_break(cx: &LateContext<'_>, emission_place: HirId, break_span: Span, exp |diag| { let mut app = Applicability::MachineApplicable; let snip = snippet_with_context(cx, expr_span, break_span.ctxt(), "..", &mut app).0; - diag.span_suggestion_with_style( + diag.span_suggestion_verbose( break_span, "change `break` to `return` as shown", format!("return {snip}"), app, - SuggestionStyle::ShowAlways, ); }, ); diff --git a/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs b/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs index 0ef5b803a89..2ad045e1268 100644 --- a/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs +++ b/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs @@ -7,8 +7,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir::{Expr, ExprKind, HirId}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::TyCtxt; -use rustc_semver::RustcVersion; -use rustc_session::impl_lint_pass; +use rustc_session::{impl_lint_pass, RustcVersion}; use rustc_span::def_id::DefId; use rustc_span::{ExpnKind, Span}; @@ -65,18 +64,18 @@ impl IncompatibleMsrv { StabilityLevel::Stable { since: StableSince::Version(version), .. - } => Some(RustcVersion::new( - version.major.into(), - version.minor.into(), - version.patch.into(), - )), + } => Some(version), _ => None, }) { version } else if let Some(parent_def_id) = tcx.opt_parent(def_id) { self.get_def_id_version(tcx, parent_def_id) } else { - RustcVersion::new(1, 0, 0) + RustcVersion { + major: 1, + minor: 0, + patch: 0, + } }; self.is_above_msrv.insert(def_id, version); version diff --git a/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs b/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs index 5b0aadf35c6..d386bfca6ba 100644 --- a/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs +++ b/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs @@ -1,4 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::fulfill_or_allowed; use clippy_utils::source::snippet; use rustc_data_structures::fx::FxHashMap; use rustc_errors::Applicability; @@ -71,6 +72,8 @@ impl<'tcx> LateLintPass<'tcx> for InconsistentStructConstructor { && let ty = cx.typeck_results().expr_ty(expr) && let Some(adt_def) = ty.ty_adt_def() && adt_def.is_struct() + && let Some(local_def_id) = adt_def.did().as_local() + && let ty_hir_id = cx.tcx.local_def_id_to_hir_id(local_def_id) && let Some(variant) = adt_def.variants().iter().next() { let mut def_order_map = FxHashMap::default(); @@ -103,15 +106,17 @@ impl<'tcx> LateLintPass<'tcx> for InconsistentStructConstructor { snippet(cx, qpath.span(), ".."), ); - span_lint_and_sugg( - cx, - INCONSISTENT_STRUCT_CONSTRUCTOR, - expr.span, - "struct constructor field order is inconsistent with struct definition field order", - "try", - sugg, - Applicability::MachineApplicable, - ); + if !fulfill_or_allowed(cx, INCONSISTENT_STRUCT_CONSTRUCTOR, Some(ty_hir_id)) { + span_lint_and_sugg( + cx, + INCONSISTENT_STRUCT_CONSTRUCTOR, + expr.span, + "struct constructor field order is inconsistent with struct definition field order", + "try", + sugg, + Applicability::MachineApplicable, + ); + } } } } diff --git a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs index 3ac50b8f1fb..22e9674714f 100644 --- a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs +++ b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs @@ -1,5 +1,3 @@ -//! lint on indexing and slicing operations - use clippy_config::Conf; use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; diff --git a/src/tools/clippy/clippy_lints/src/infinite_iter.rs b/src/tools/clippy/clippy_lints/src/infinite_iter.rs index 676d50c4951..71c317552ee 100644 --- a/src/tools/clippy/clippy_lints/src/infinite_iter.rs +++ b/src/tools/clippy/clippy_lints/src/infinite_iter.rs @@ -1,10 +1,10 @@ use clippy_utils::diagnostics::span_lint; use clippy_utils::higher; -use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; +use clippy_utils::ty::{get_type_diagnostic_name, implements_trait}; use rustc_hir::{BorrowKind, Closure, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; -use rustc_span::symbol::{sym, Symbol}; +use rustc_span::symbol::sym; declare_clippy_lint! { /// ### What it does @@ -210,18 +210,6 @@ const COMPLETING_METHODS: [(&str, usize); 12] = [ ("product", 0), ]; -/// the paths of types that are known to be infinitely allocating -const INFINITE_COLLECTORS: &[Symbol] = &[ - sym::BinaryHeap, - sym::BTreeMap, - sym::BTreeSet, - sym::HashMap, - sym::HashSet, - sym::LinkedList, - sym::Vec, - sym::VecDeque, -]; - fn complete_infinite_iter(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness { match expr.kind { ExprKind::MethodCall(method, receiver, args, _) => { @@ -248,10 +236,19 @@ fn complete_infinite_iter(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness { } } else if method.ident.name == sym!(collect) { let ty = cx.typeck_results().expr_ty(expr); - if INFINITE_COLLECTORS - .iter() - .any(|diag_item| is_type_diagnostic_item(cx, ty, *diag_item)) - { + if matches!( + get_type_diagnostic_name(cx, ty), + Some( + sym::BinaryHeap + | sym::BTreeMap + | sym::BTreeSet + | sym::HashMap + | sym::HashSet + | sym::LinkedList + | sym::Vec + | sym::VecDeque, + ) + ) { return is_infinite(cx, receiver); } } diff --git a/src/tools/clippy/clippy_lints/src/inherent_impl.rs b/src/tools/clippy/clippy_lints/src/inherent_impl.rs index 9eed7aa9243..d39f910f993 100644 --- a/src/tools/clippy/clippy_lints/src/inherent_impl.rs +++ b/src/tools/clippy/clippy_lints/src/inherent_impl.rs @@ -1,5 +1,3 @@ -//! lint on inherent implementations - use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_lint_allowed; use rustc_data_structures::fx::FxHashMap; diff --git a/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs b/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs index 5657c58bb0a..1b900f6be8e 100644 --- a/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs +++ b/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs @@ -1,5 +1,3 @@ -//! checks for `#[inline]` on trait methods without bodies - use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::sugg::DiagExt; use rustc_errors::Applicability; diff --git a/src/tools/clippy/clippy_lints/src/int_plus_one.rs b/src/tools/clippy/clippy_lints/src/int_plus_one.rs index b8e0eef7c7e..fc575bff7e6 100644 --- a/src/tools/clippy/clippy_lints/src/int_plus_one.rs +++ b/src/tools/clippy/clippy_lints/src/int_plus_one.rs @@ -1,7 +1,5 @@ -//! lint on blocks unnecessarily using >= with a + 1 or - 1 - use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use rustc_ast::ast::{BinOpKind, Expr, ExprKind, LitKind}; use rustc_ast::token; use rustc_errors::Applicability; @@ -132,8 +130,8 @@ impl IntPlusOne { BinOpKind::Le => "<", _ => return None, }; - if let Some(snippet) = snippet_opt(cx, node.span) { - if let Some(other_side_snippet) = snippet_opt(cx, other_side.span) { + if let Some(snippet) = node.span.get_source_text(cx) { + if let Some(other_side_snippet) = other_side.span.get_source_text(cx) { let rec = match side { Side::Lhs => Some(format!("{snippet} {binop_string} {other_side_snippet}")), Side::Rhs => Some(format!("{other_side_snippet} {binop_string} {snippet}")), diff --git a/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs index 4d44bae02b8..74bf82f58bd 100644 --- a/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs +++ b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs @@ -1,5 +1,3 @@ -//! lint on enum variants that are prefixed or suffixed by the same characters - use clippy_config::Conf; use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_hir}; use clippy_utils::is_bool; diff --git a/src/tools/clippy/clippy_lints/src/items_after_statements.rs b/src/tools/clippy/clippy_lints/src/items_after_statements.rs index a88d8e24fda..4f066113aea 100644 --- a/src/tools/clippy/clippy_lints/src/items_after_statements.rs +++ b/src/tools/clippy/clippy_lints/src/items_after_statements.rs @@ -1,5 +1,3 @@ -//! lint when items are used after statements - use clippy_utils::diagnostics::span_lint_hir; use rustc_hir::{Block, ItemKind, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; diff --git a/src/tools/clippy/clippy_lints/src/items_after_test_module.rs b/src/tools/clippy/clippy_lints/src/items_after_test_module.rs index 3614fb8cc96..8caa484bb99 100644 --- a/src/tools/clippy/clippy_lints/src/items_after_test_module.rs +++ b/src/tools/clippy/clippy_lints/src/items_after_test_module.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_hir_and_then; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::{fulfill_or_allowed, is_cfg_test, is_from_proc_macro}; use rustc_errors::{Applicability, SuggestionStyle}; use rustc_hir::{HirId, Item, ItemKind, Mod}; @@ -93,11 +93,14 @@ impl LateLintPass<'_> for ItemsAfterTestModule { if let Some(prev) = mod_pos.checked_sub(1) && let prev = cx.tcx.hir().item(module.item_ids[prev]) && let items_span = last.span.with_lo(test_mod.span.hi()) - && let Some(items) = snippet_opt(cx, items_span) + && let Some(items) = items_span.get_source_text(cx) { diag.multipart_suggestion_with_style( "move the items to before the test module was defined", - vec![(prev.span.shrink_to_hi(), items), (items_span, String::new())], + vec![ + (prev.span.shrink_to_hi(), items.to_owned()), + (items_span, String::new()), + ], Applicability::MachineApplicable, SuggestionStyle::HideCodeAlways, ); diff --git a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs index 225d79aa71d..2f027c11707 100644 --- a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs +++ b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs @@ -1,5 +1,3 @@ -//! lint when there is a large size difference between variants on an enum - use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet_with_applicability; diff --git a/src/tools/clippy/clippy_lints/src/large_stack_frames.rs b/src/tools/clippy/clippy_lints/src/large_stack_frames.rs index 4abf7edc9b4..d2bdf194ada 100644 --- a/src/tools/clippy/clippy_lints/src/large_stack_frames.rs +++ b/src/tools/clippy/clippy_lints/src/large_stack_frames.rs @@ -3,7 +3,7 @@ use std::{fmt, ops}; use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::fn_has_unsatisfiable_preds; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::FnKind; use rustc_hir::{Body, FnDecl}; @@ -186,7 +186,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackFrames { // TODO: Is there a cleaner, robust way to ask this question? // The obvious `LocalDecl::is_user_variable()` panics on "unwrapping cross-crate data", // and that doesn't get us the true name in scope rather than the span text either. - if let Some(name) = snippet_opt(cx, local_span) + if let Some(name) = local_span.get_source_text(cx) && is_ident(&name) { // If the local is an ordinary named variable, diff --git a/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs b/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs index 752e1326e3e..ccab1e27d3b 100644 --- a/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs +++ b/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs @@ -3,7 +3,7 @@ use clippy_config::Conf; use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then}; use clippy_utils::{get_parent_expr, is_from_proc_macro}; use hir::def_id::DefId; -use rustc_errors::{Applicability, SuggestionStyle}; +use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::{ExprKind, Item, ItemKind, QPath, UseKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -143,12 +143,11 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants { && !is_from_proc_macro(cx, expr) { span_lint_hir_and_then(cx, LEGACY_NUMERIC_CONSTANTS, expr.hir_id, span, msg, |diag| { - diag.span_suggestion_with_style( + diag.span_suggestion_verbose( span, "use the associated constant instead", sugg, Applicability::MaybeIncorrect, - SuggestionStyle::ShowAlways, ); }); } diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index 4c737371bd2..0bc7fc2dd9d 100644 --- a/src/tools/clippy/clippy_lints/src/len_zero.rs +++ b/src/tools/clippy/clippy_lints/src/len_zero.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then}; -use clippy_utils::source::{snippet_opt, snippet_with_context}; +use clippy_utils::source::{snippet_with_context, SpanRangeExt}; use clippy_utils::sugg::{has_enclosing_paren, Sugg}; use clippy_utils::{get_item_name, get_parent_as_impl, is_lint_allowed, peel_ref_operators}; use rustc_ast::ast::LitKind; @@ -216,7 +216,7 @@ impl<'tcx> LateLintPass<'tcx> for LenZero { } fn span_without_enclosing_paren(cx: &LateContext<'_>, span: Span) -> Span { - let Some(snippet) = snippet_opt(cx, span) else { + let Some(snippet) = span.get_source_text(cx) else { return span; }; if has_enclosing_paren(snippet) { diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index ce13a9afef5..2ac06b360be 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -66,8 +66,8 @@ extern crate declare_clippy_lint; #[cfg_attr(feature = "internal", allow(clippy::missing_clippy_version_attribute))] mod utils; -mod declared_lints; -mod deprecated_lints; +pub mod declared_lints; +pub mod deprecated_lints; // begin lints modules, do not remove this comment, it’s used in `update_lints` mod absolute_paths; @@ -440,7 +440,7 @@ impl RegistrationGroups { } } -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub(crate) enum LintCategory { Cargo, Complexity, @@ -479,11 +479,39 @@ impl LintCategory { } } -pub(crate) struct LintInfo { +pub struct LintInfo { /// Double reference to maintain pointer equality - lint: &'static &'static Lint, + pub lint: &'static &'static Lint, category: LintCategory, - explanation: &'static str, + pub explanation: &'static str, + /// e.g. `clippy_lints/src/absolute_paths.rs#43` + pub location: &'static str, + pub version: Option<&'static str>, +} + +impl LintInfo { + /// Returns the lint name in lowercase without the `clippy::` prefix + #[allow(clippy::missing_panics_doc)] + pub fn name_lower(&self) -> String { + self.lint.name.strip_prefix("clippy::").unwrap().to_ascii_lowercase() + } + + /// Returns the name of the lint's category in lowercase (`style`, `pedantic`) + pub fn category_str(&self) -> &'static str { + match self.category { + Cargo => "cargo", + Complexity => "complexity", + Correctness => "correctness", + Nursery => "nursery", + Pedantic => "pedantic", + Perf => "perf", + Restriction => "restriction", + Style => "style", + Suspicious => "suspicious", + #[cfg(feature = "internal")] + Internal => "internal", + } + } } pub fn explain(name: &str) -> i32 { @@ -538,14 +566,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_removed(name, reason); } - #[cfg(feature = "internal")] - { - if std::env::var("ENABLE_METADATA_COLLECTION").eq(&Ok("1".to_string())) { - store.register_late_pass(|_| Box::new(utils::internal_lints::metadata_collector::MetadataCollector::new())); - return; - } - } - let format_args_storage = FormatArgsStorage::default(); let format_args = format_args_storage.clone(); store.register_early_pass(move || { diff --git a/src/tools/clippy/clippy_lints/src/literal_representation.rs b/src/tools/clippy/clippy_lints/src/literal_representation.rs index 259e4d6c08f..81f2a03fb55 100644 --- a/src/tools/clippy/clippy_lints/src/literal_representation.rs +++ b/src/tools/clippy/clippy_lints/src/literal_representation.rs @@ -1,10 +1,7 @@ -//! Lints concerned with the grouping of digits with underscores in integral or -//! floating-point literal expressions. - use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::numeric_literal::{NumericLiteral, Radix}; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use rustc_ast::ast::{Expr, ExprKind, LitKind}; use rustc_ast::token; use rustc_errors::Applicability; @@ -228,7 +225,7 @@ impl LiteralDigitGrouping { } fn check_lit(&self, cx: &EarlyContext<'_>, lit: token::Lit, span: Span) { - if let Some(src) = snippet_opt(cx, span) + if let Some(src) = span.get_source_text(cx) && let Ok(lit_kind) = LitKind::from_token_lit(lit) && let Some(mut num_lit) = NumericLiteral::from_lit_kind(&src, &lit_kind) { @@ -442,7 +439,7 @@ impl DecimalLiteralRepresentation { // Lint integral literals. if let Ok(lit_kind) = LitKind::from_token_lit(lit) && let LitKind::Int(val, _) = lit_kind - && let Some(src) = snippet_opt(cx, span) + && let Some(src) = span.get_source_text(cx) && let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit_kind) && num_lit.radix == Radix::Decimal && val >= u128::from(self.threshold) diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs index eea5f2a94ea..b134af500f5 100644 --- a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs @@ -3,7 +3,7 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::{ - implements_trait, implements_trait_with_env, is_copy, make_normalized_projection, + implements_trait, implements_trait_with_env, is_copy, is_type_lang_item, make_normalized_projection, make_normalized_projection_with_regions, normalize_with_regions, }; use rustc_errors::Applicability; @@ -20,9 +20,10 @@ pub(super) fn check( msrv: &Msrv, enforce_iter_loop_reborrow: bool, ) { - let Some((adjust, ty)) = is_ref_iterable(cx, self_arg, call_expr, enforce_iter_loop_reborrow) else { + let Some((adjust, ty)) = is_ref_iterable(cx, self_arg, call_expr, enforce_iter_loop_reborrow, msrv) else { return; }; + if let ty::Array(_, count) = *ty.peel_refs().kind() { if !ty.is_ref() { if !msrv.meets(msrvs::ARRAY_INTO_ITERATOR) { @@ -109,6 +110,7 @@ fn is_ref_iterable<'tcx>( self_arg: &Expr<'_>, call_expr: &Expr<'_>, enforce_iter_loop_reborrow: bool, + msrv: &Msrv, ) -> Option<(AdjustKind, Ty<'tcx>)> { let typeck = cx.typeck_results(); if let Some(trait_id) = cx.tcx.get_diagnostic_item(sym::IntoIterator) @@ -128,6 +130,12 @@ fn is_ref_iterable<'tcx>( let self_ty = typeck.expr_ty(self_arg); let self_is_copy = is_copy(cx, self_ty); + if !msrv.meets(msrvs::BOX_INTO_ITER) + && is_type_lang_item(cx, self_ty.peel_refs(), rustc_hir::LangItem::OwnedBox) + { + return None; + } + if adjustments.is_empty() && self_is_copy { // Exact type match, already checked earlier return Some((AdjustKind::None, self_ty)); diff --git a/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs b/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs index fed58f7ff14..e215097142b 100644 --- a/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs +++ b/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs @@ -122,8 +122,23 @@ struct BodyVisitor<'a, 'tcx> { /// within a relevant macro. macro_unsafe_blocks: Vec, /// When this is >0, it means that the node currently being visited is "within" a - /// macro definition. This is not necessary for correctness, it merely helps reduce the number - /// of spans we need to insert into the map, since only spans from macros are relevant. + /// macro definition. + /// This is used to detect if an expression represents a metavariable. + /// + /// For example, the following pre-expansion code that we want to lint + /// ```ignore + /// macro_rules! m { ($e:expr) => { unsafe { $e; } } } + /// m!(1); + /// ``` + /// would look like this post-expansion code: + /// ```ignore + /// unsafe { /* macro */ + /// 1 /* root */; /* macro */ + /// } + /// ``` + /// Visiting the block and the statement will increment the `expn_depth` so that it is >0, + /// and visiting the expression with a root context while `expn_depth > 0` tells us + /// that it must be a metavariable. expn_depth: u32, cx: &'a LateContext<'tcx>, lint: &'a mut ExprMetavarsInUnsafe, @@ -157,7 +172,9 @@ impl<'a, 'tcx> Visitor<'tcx> for BodyVisitor<'a, 'tcx> { && (self.lint.warn_unsafe_macro_metavars_in_private_macros || is_public_macro(self.cx, macro_def_id)) { self.macro_unsafe_blocks.push(block.hir_id); + self.expn_depth += 1; walk_block(self, block); + self.expn_depth -= 1; self.macro_unsafe_blocks.pop(); } else if ctxt.is_root() && self.expn_depth > 0 { let unsafe_block = self.macro_unsafe_blocks.last().copied(); diff --git a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs index 25c7e5d38b3..61723aec590 100644 --- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs +++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::{position_before_rarrow, snippet_block, snippet_opt}; +use clippy_utils::source::{position_before_rarrow, snippet_block, SpanRangeExt}; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; use rustc_hir::{ @@ -68,8 +68,8 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn { header_span, "this function can be simplified using the `async fn` syntax", |diag| { - if let Some(vis_snip) = snippet_opt(cx, *vis_span) - && let Some(header_snip) = snippet_opt(cx, header_span) + if let Some(vis_snip) = vis_span.get_source_text(cx) + && let Some(header_snip) = header_span.get_source_text(cx) && let Some(ret_pos) = position_before_rarrow(&header_snip) && let Some((ret_sugg, ret_snip)) = suggested_ret(cx, output) { @@ -190,6 +190,6 @@ fn suggested_ret(cx: &LateContext<'_>, output: &Ty<'_>) -> Option<(&'static str, Some((sugg, String::new())) } else { let sugg = "return the output of the future directly"; - snippet_opt(cx, output.span).map(|snip| (sugg, format!(" -> {snip}"))) + output.span.get_source_text(cx).map(|src| (sugg, format!(" -> {src}"))) } } diff --git a/src/tools/clippy/clippy_lints/src/manual_float_methods.rs b/src/tools/clippy/clippy_lints/src/manual_float_methods.rs index 6bdc79129a9..9d3ddab60bb 100644 --- a/src/tools/clippy/clippy_lints/src/manual_float_methods.rs +++ b/src/tools/clippy/clippy_lints/src/manual_float_methods.rs @@ -1,6 +1,6 @@ use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::{is_from_proc_macro, path_to_local}; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Constness, Expr, ExprKind}; @@ -103,7 +103,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods { // case somebody does that for some reason && (is_infinity(&const_1) && is_neg_infinity(&const_2) || is_neg_infinity(&const_1) && is_infinity(&const_2)) - && let Some(local_snippet) = snippet_opt(cx, first.span) + && let Some(local_snippet) = first.span.get_source_text(cx) { let variant = match (kind.node, lhs_kind.node, rhs_kind.node) { (BinOpKind::Or, BinOpKind::Eq, BinOpKind::Eq) => Variant::ManualIsInfinite, diff --git a/src/tools/clippy/clippy_lints/src/manual_hash_one.rs b/src/tools/clippy/clippy_lints/src/manual_hash_one.rs index 1c568b1b74f..11716a539ab 100644 --- a/src/tools/clippy/clippy_lints/src/manual_hash_one.rs +++ b/src/tools/clippy/clippy_lints/src/manual_hash_one.rs @@ -1,7 +1,7 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_hir_and_then; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::visitors::{is_local_used, local_used_once}; use clippy_utils::{is_trait_method, path_to_local_id}; use rustc_errors::Applicability; @@ -107,8 +107,8 @@ impl LateLintPass<'_> for ManualHashOne { finish_expr.span, "manual implementation of `BuildHasher::hash_one`", |diag| { - if let Some(build_hasher) = snippet_opt(cx, build_hasher.span) - && let Some(hashed_value) = snippet_opt(cx, hashed_value.span) + if let Some(build_hasher) = build_hasher.span.get_source_text(cx) + && let Some(hashed_value) = hashed_value.span.get_source_text(cx) { diag.multipart_suggestion( "try", diff --git a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs index 28cfe22835a..6b1d90483cc 100644 --- a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs +++ b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs @@ -2,7 +2,7 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_config::Conf; use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then}; use clippy_utils::is_doc_hidden; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use rustc_ast::ast::{self, VisibilityKind}; use rustc_ast::attr; use rustc_data_structures::fx::FxHashSet; @@ -124,7 +124,7 @@ impl EarlyLintPass for ManualNonExhaustiveStruct { |diag| { if !item.attrs.iter().any(|attr| attr.has_name(sym::non_exhaustive)) && let header_span = cx.sess().source_map().span_until_char(item.span, delimiter) - && let Some(snippet) = snippet_opt(cx, header_span) + && let Some(snippet) = header_span.get_source_text(cx) { diag.span_suggestion( header_span, @@ -194,7 +194,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustiveEnum { "this seems like a manual implementation of the non-exhaustive pattern", |diag| { let header_span = cx.sess().source_map().span_until_char(enum_span, '{'); - if let Some(snippet) = snippet_opt(cx, header_span) { + if let Some(snippet) = header_span.get_source_text(cx) { diag.span_suggestion( header_span, "add the attribute", diff --git a/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs b/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs index 07d4abbf5cd..9afb2b5bc84 100644 --- a/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs +++ b/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use rustc_ast::LitKind; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; @@ -143,8 +143,8 @@ impl LateLintPass<'_> for ManualRangePatterns { pat.span, "this OR pattern can be rewritten using a range", |diag| { - if let Some(min) = snippet_opt(cx, min.span) - && let Some(max) = snippet_opt(cx, max.span) + if let Some(min) = min.span.get_source_text(cx) + && let Some(max) = max.span.get_source_text(cx) { diag.span_suggestion( pat.span, diff --git a/src/tools/clippy/clippy_lints/src/manual_retain.rs b/src/tools/clippy/clippy_lints/src/manual_retain.rs index 09f6362b4dd..d4e53f8f74b 100644 --- a/src/tools/clippy/clippy_lints/src/manual_retain.rs +++ b/src/tools/clippy/clippy_lints/src/manual_retain.rs @@ -2,14 +2,13 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet; -use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item}; +use clippy_utils::ty::{get_type_diagnostic_name, is_type_lang_item}; use clippy_utils::{match_def_path, paths, SpanlessEq}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::ExprKind::Assign; use rustc_lint::{LateContext, LateLintPass}; -use rustc_semver::RustcVersion; use rustc_session::impl_lint_pass; use rustc_span::symbol::sym; use rustc_span::Span; @@ -21,16 +20,6 @@ const ACCEPTABLE_METHODS: [&[&str]; 5] = [ &paths::SLICE_INTO, &paths::VEC_DEQUE_ITER, ]; -const ACCEPTABLE_TYPES: [(rustc_span::Symbol, Option); 7] = [ - (sym::BinaryHeap, Some(msrvs::BINARY_HEAP_RETAIN)), - (sym::BTreeSet, Some(msrvs::BTREE_SET_RETAIN)), - (sym::BTreeMap, Some(msrvs::BTREE_MAP_RETAIN)), - (sym::HashSet, Some(msrvs::HASH_SET_RETAIN)), - (sym::HashMap, Some(msrvs::HASH_MAP_RETAIN)), - (sym::Vec, None), - (sym::VecDeque, None), -]; -const MAP_TYPES: [rustc_span::Symbol; 2] = [sym::BTreeMap, sym::HashMap]; declare_clippy_lint! { /// ### What it does @@ -265,16 +254,22 @@ fn match_acceptable_def_path(cx: &LateContext<'_>, collect_def_id: DefId) -> boo } fn match_acceptable_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>, msrv: &Msrv) -> bool { - let expr_ty = cx.typeck_results().expr_ty(expr).peel_refs(); - ACCEPTABLE_TYPES.iter().any(|(ty, acceptable_msrv)| { - is_type_diagnostic_item(cx, expr_ty, *ty) - && acceptable_msrv.map_or(true, |acceptable_msrv| msrv.meets(acceptable_msrv)) - }) + let ty = cx.typeck_results().expr_ty(expr).peel_refs(); + let required = match get_type_diagnostic_name(cx, ty) { + Some(sym::BinaryHeap) => msrvs::BINARY_HEAP_RETAIN, + Some(sym::BTreeSet) => msrvs::BTREE_SET_RETAIN, + Some(sym::BTreeMap) => msrvs::BTREE_MAP_RETAIN, + Some(sym::HashSet) => msrvs::HASH_SET_RETAIN, + Some(sym::HashMap) => msrvs::HASH_MAP_RETAIN, + Some(sym::Vec | sym::VecDeque) => return true, + _ => return false, + }; + msrv.meets(required) } fn match_map_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { - let expr_ty = cx.typeck_results().expr_ty(expr).peel_refs(); - MAP_TYPES.iter().any(|ty| is_type_diagnostic_item(cx, expr_ty, *ty)) + let ty = cx.typeck_results().expr_ty(expr).peel_refs(); + matches!(get_type_diagnostic_name(cx, ty), Some(sym::BTreeMap | sym::HashMap)) } fn make_span_lint_and_sugg(cx: &LateContext<'_>, span: Span, sugg: String) { diff --git a/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs b/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs index 90cfdecc199..b666e77c09e 100644 --- a/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs @@ -96,7 +96,7 @@ fn check_arm<'tcx>( // collapsing patterns need an explicit field name in struct pattern matching // ex: Struct {x: Some(1)} let replace_msg = if is_innermost_parent_pat_struct { - format!(", prefixed by {}:", snippet(cx, binding_span, "their field name")) + format!(", prefixed by `{}`:", snippet(cx, binding_span, "their field name")) } else { String::new() }; diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs index 2d4c8daf5cb..d5d83df9347 100644 --- a/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs +++ b/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs @@ -1,6 +1,6 @@ use clippy_utils::consts::ConstEvalCtxt; use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt}; +use clippy_utils::source::{indent_of, reindent_multiline, SpanRangeExt}; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::usage::contains_return_break_continue_macro; use clippy_utils::{is_res_lang_ctor, path_to_local_id, peel_blocks, sugg}; @@ -67,11 +67,11 @@ fn check_and_lint<'tcx>( && path_to_local_id(peel_blocks(then_expr), binding_hir_id) && cx.typeck_results().expr_adjustments(then_expr).is_empty() && let Some(ty_name) = find_type_name(cx, ty) - && let Some(or_body_snippet) = snippet_opt(cx, else_expr.span) + && let Some(or_body_snippet) = else_expr.span.get_source_text(cx) && let Some(indent) = indent_of(cx, expr.span) && ConstEvalCtxt::new(cx).eval_simple(else_expr).is_some() { - lint(cx, expr, let_expr, ty_name, or_body_snippet, indent); + lint(cx, expr, let_expr, ty_name, &or_body_snippet, indent); } } @@ -110,7 +110,7 @@ fn lint<'tcx>( expr: &Expr<'tcx>, scrutinee: &'tcx Expr<'_>, ty_name: &str, - or_body_snippet: String, + or_body_snippet: &str, indent: usize, ) { let reindented_or_body = reindent_multiline(or_body_snippet.into(), true, Some(indent)); diff --git a/src/tools/clippy/clippy_lints/src/matches/single_match.rs b/src/tools/clippy/clippy_lints/src/matches/single_match.rs index 24dea03601c..b6930f7b9d1 100644 --- a/src/tools/clippy/clippy_lints/src/matches/single_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/single_match.rs @@ -22,7 +22,7 @@ use super::{MATCH_BOOL, SINGLE_MATCH, SINGLE_MATCH_ELSE}; /// span, e.g. a string literal `"//"`, but we know that this isn't the case for empty /// match arms. fn empty_arm_has_comment(cx: &LateContext<'_>, span: Span) -> bool { - if let Some(ff) = span.get_source_text(cx) + if let Some(ff) = span.get_source_range(cx) && let Some(text) = ff.as_str() { text.as_bytes().windows(2).any(|w| w == b"//" || w == b"/*") diff --git a/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs b/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs index a5df863d800..740cce0a6c2 100644 --- a/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs +++ b/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt}; +use clippy_utils::source::{indent_of, reindent_multiline, SpanRangeExt}; use clippy_utils::ty::is_type_lang_item; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; @@ -49,10 +49,12 @@ pub(super) fn check<'tcx>( "case-sensitive file extension comparison", |diag| { diag.help("consider using a case-insensitive comparison instead"); - if let Some(mut recv_source) = snippet_opt(cx, recv.span) { - if !cx.typeck_results().expr_ty(recv).is_ref() { - recv_source = format!("&{recv_source}"); - } + if let Some(recv_source) = recv.span.get_source_text(cx) { + let recv_source = if cx.typeck_results().expr_ty(recv).is_ref() { + recv_source.to_owned() + } else { + format!("&{recv_source}") + }; let suggestion_source = reindent_multiline( format!( diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs index 2e43d19a699..4fbf661727d 100644 --- a/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs +++ b/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs @@ -1,7 +1,7 @@ use super::FILTER_MAP_BOOL_THEN; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::paths::BOOL_THEN; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::is_copy; use clippy_utils::{is_from_proc_macro, is_trait_method, match_def_path, peel_blocks}; use rustc_errors::Applicability; @@ -42,9 +42,9 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, arg: & .iter() .filter(|adj| matches!(adj.kind, Adjust::Deref(_))) .count() - && let Some(param_snippet) = snippet_opt(cx, param.span) - && let Some(filter) = snippet_opt(cx, recv.span) - && let Some(map) = snippet_opt(cx, then_body.span) + && let Some(param_snippet) = param.span.get_source_text(cx) + && let Some(filter) = recv.span.get_source_text(cx) + && let Some(map) = then_body.span.get_source_text(cx) { span_lint_and_sugg( cx, diff --git a/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs b/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs index 917a8e33eb9..f4840785584 100644 --- a/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::implements_trait; use clippy_utils::{is_path_diagnostic_item, sugg}; use rustc_errors::Applicability; @@ -39,7 +39,7 @@ fn extract_turbofish(cx: &LateContext<'_>, expr: &hir::Expr<'_>, ty: Ty<'_>) -> } let call_site = expr.span.source_callsite(); - if let Some(snippet) = snippet_opt(cx, call_site) + if let Some(snippet) = call_site.get_source_text(cx) && let snippet_split = snippet.split("::").collect::>() && let Some((_, elements)) = snippet_split.split_last() { diff --git a/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs b/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs index c6285c87a26..9daad1a8a94 100644 --- a/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs +++ b/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs @@ -74,7 +74,7 @@ pub(super) fn check<'tcx>( "&" }; - diag.span_suggestion_with_style( + diag.span_suggestion_verbose( span, "using `[]` is clearer and more concise", format!( @@ -82,7 +82,6 @@ pub(super) fn check<'tcx>( snippet_with_applicability(cx, recv.span, "..", &mut applicability) ), applicability, - rustc_errors::SuggestionStyle::ShowAlways, ); }, ); diff --git a/src/tools/clippy/clippy_lints/src/methods/is_digit_ascii_radix.rs b/src/tools/clippy/clippy_lints/src/methods/is_digit_ascii_radix.rs index 22d896433f0..40b48ccca5d 100644 --- a/src/tools/clippy/clippy_lints/src/methods/is_digit_ascii_radix.rs +++ b/src/tools/clippy/clippy_lints/src/methods/is_digit_ascii_radix.rs @@ -1,5 +1,3 @@ -//! Lint for `c.is_digit(10)` - use super::IS_DIGIT_ASCII_RADIX; use clippy_config::msrvs::{self, Msrv}; use clippy_utils::consts::{ConstEvalCtxt, FullInt}; diff --git a/src/tools/clippy/clippy_lints/src/methods/join_absolute_paths.rs b/src/tools/clippy/clippy_lints/src/methods/join_absolute_paths.rs index aa1ec60d434..2dad7fcf3c1 100644 --- a/src/tools/clippy/clippy_lints/src/methods/join_absolute_paths.rs +++ b/src/tools/clippy/clippy_lints/src/methods/join_absolute_paths.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::expr_or_init; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::snippet; use clippy_utils::ty::is_type_diagnostic_item; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; @@ -25,7 +25,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, recv: &'tcx Expr<'tcx>, join_a join_arg.span, "argument to `Path::join` starts with a path separator", |diag| { - let arg_str = snippet_opt(cx, spanned.span).unwrap_or_else(|| "..".to_string()); + let arg_str = snippet(cx, spanned.span, ".."); let no_separator = if sym_str.starts_with('/') { arg_str.replacen('/', "", 1) diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs b/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs index b1af0083e65..b1a8e1e5e47 100644 --- a/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs +++ b/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt}; +use clippy_utils::source::{indent_of, reindent_multiline, SpanRangeExt}; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::{is_res_lang_ctor, path_res, path_to_local_id}; use rustc_errors::Applicability; @@ -23,11 +23,11 @@ pub(super) fn check<'tcx>( && let ExprKind::Call(err_path, [err_arg]) = or_expr.kind && is_res_lang_ctor(cx, path_res(cx, err_path), ResultErr) && is_ok_wrapping(cx, map_expr) - && let Some(recv_snippet) = snippet_opt(cx, recv.span) - && let Some(err_arg_snippet) = snippet_opt(cx, err_arg.span) + && let Some(recv_snippet) = recv.span.get_source_text(cx) + && let Some(err_arg_snippet) = err_arg.span.get_source_text(cx) && let Some(indent) = indent_of(cx, expr.span) { - let reindented_err_arg_snippet = reindent_multiline(err_arg_snippet.into(), true, Some(indent + 4)); + let reindented_err_arg_snippet = reindent_multiline(err_arg_snippet.as_str().into(), true, Some(indent + 4)); span_lint_and_sugg( cx, MANUAL_OK_OR, diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_try_fold.rs b/src/tools/clippy/clippy_lints/src/methods/manual_try_fold.rs index f93edded729..11fba35c16e 100644 --- a/src/tools/clippy/clippy_lints/src/methods/manual_try_fold.rs +++ b/src/tools/clippy/clippy_lints/src/methods/manual_try_fold.rs @@ -1,6 +1,6 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::implements_trait; use clippy_utils::{is_from_proc_macro, is_trait_method}; use rustc_errors::Applicability; @@ -31,13 +31,15 @@ pub(super) fn check<'tcx>( && let Res::Def(DefKind::Ctor(_, _), _) = cx.qpath_res(&qpath, path.hir_id) && let ExprKind::Closure(closure) = acc.kind && !is_from_proc_macro(cx, expr) - && let Some(args_snip) = closure.fn_arg_span.and_then(|fn_arg_span| snippet_opt(cx, fn_arg_span)) + && let Some(args_snip) = closure + .fn_arg_span + .and_then(|fn_arg_span| fn_arg_span.get_source_text(cx)) { let init_snip = rest .is_empty() .then_some(first.span) - .and_then(|span| snippet_opt(cx, span)) - .unwrap_or("...".to_owned()); + .and_then(|span| span.get_source_text(cx)) + .map_or_else(|| "...".to_owned(), |src| src.to_owned()); span_lint_and_sugg( cx, diff --git a/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs b/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs index def8be2ef73..22a03825194 100644 --- a/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs +++ b/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs @@ -58,7 +58,7 @@ fn try_get_caller_ty_name_and_method_name( fn is_map_to_option(cx: &LateContext<'_>, map_arg: &Expr<'_>) -> bool { let map_closure_ty = cx.typeck_results().expr_ty(map_arg); match map_closure_ty.kind() { - ty::Closure(_, _) | ty::FnDef(_, _) | ty::FnPtr(_) => { + ty::Closure(_, _) | ty::FnDef(_, _) | ty::FnPtr(..) => { let map_closure_sig = match map_closure_ty.kind() { ty::Closure(_, args) => args.as_closure().sig(), _ => map_closure_ty.fn_sig(cx.tcx), diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index 1d7b10fe8f0..d7126990edb 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -2702,10 +2702,10 @@ declare_clippy_lint! { /// } /// }) /// } - /// ``` + /// ``` /// - /// After: - /// ```rust + /// After: + /// ```rust /// use std::{fmt, num::ParseIntError}; /// /// #[derive(Debug)] diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_character_iteration.rs b/src/tools/clippy/clippy_lints/src/methods/needless_character_iteration.rs index e3d78207715..332da722a37 100644 --- a/src/tools/clippy/clippy_lints/src/methods/needless_character_iteration.rs +++ b/src/tools/clippy/clippy_lints/src/methods/needless_character_iteration.rs @@ -7,7 +7,7 @@ use rustc_span::Span; use super::utils::get_last_chain_binding_hir_id; use super::NEEDLESS_CHARACTER_ITERATION; use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::{match_def_path, path_to_local_id, peel_blocks}; fn peels_expr_ref<'a, 'tcx>(mut expr: &'a Expr<'tcx>) -> &'a Expr<'tcx> { @@ -35,7 +35,7 @@ fn handle_expr( && path_to_local_id(receiver, first_param) && let char_arg_ty = cx.typeck_results().expr_ty_adjusted(receiver).peel_refs() && *char_arg_ty.kind() == ty::Char - && let Some(snippet) = snippet_opt(cx, before_chars) + && let Some(snippet) = before_chars.get_source_text(cx) { span_lint_and_sugg( cx, @@ -79,7 +79,7 @@ fn handle_expr( && let Some(fn_def_id) = cx.qpath_res(&path, fn_path.hir_id).opt_def_id() && match_def_path(cx, fn_def_id, &["core", "char", "methods", "", "is_ascii"]) && path_to_local_id(peels_expr_ref(arg), first_param) - && let Some(snippet) = snippet_opt(cx, before_chars) + && let Some(snippet) = before_chars.get_source_text(cx) { span_lint_and_sugg( cx, diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs index 46b457daf70..f61923e5bf5 100644 --- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs @@ -2,7 +2,7 @@ use super::NEEDLESS_COLLECT; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then}; use clippy_utils::source::{snippet, snippet_with_applicability}; use clippy_utils::sugg::Sugg; -use clippy_utils::ty::{is_type_diagnostic_item, make_normalized_projection, make_projection}; +use clippy_utils::ty::{get_type_diagnostic_name, make_normalized_projection, make_projection}; use clippy_utils::{ can_move_expr_to_closure, fn_def_id, get_enclosing_block, higher, is_trait_method, path_to_local, path_to_local_id, CaptureKind, @@ -88,9 +88,10 @@ pub(super) fn check<'tcx>( Node::LetStmt(l) => { if let PatKind::Binding(BindingMode::NONE | BindingMode::MUT, id, _, None) = l.pat.kind && let ty = cx.typeck_results().expr_ty(collect_expr) - && [sym::Vec, sym::VecDeque, sym::BinaryHeap, sym::LinkedList] - .into_iter() - .any(|item| is_type_diagnostic_item(cx, ty, item)) + && matches!( + get_type_diagnostic_name(cx, ty), + Some(sym::Vec | sym::VecDeque | sym::BinaryHeap | sym::LinkedList) + ) && let iter_ty = cx.typeck_results().expr_ty(iter_expr) && let Some(block) = get_enclosing_block(cx, l.hir_id) && let Some(iter_calls) = detect_iter_and_into_iters(block, id, cx, get_captured_ids(cx, iter_ty)) diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_option_as_deref.rs b/src/tools/clippy/clippy_lints/src/methods/needless_option_as_deref.rs index eaae8613d44..9f714fdd47b 100644 --- a/src/tools/clippy/clippy_lints/src/methods/needless_option_as_deref.rs +++ b/src/tools/clippy/clippy_lints/src/methods/needless_option_as_deref.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::path_res; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::usage::local_used_after_expr; use rustc_errors::Applicability; @@ -32,7 +32,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, name expr.span, "derefed type is same as origin", "try", - snippet_opt(cx, recv.span).unwrap(), + recv.span.get_source_text(cx).unwrap().to_owned(), Applicability::MachineApplicable, ); } diff --git a/src/tools/clippy/clippy_lints/src/methods/string_lit_chars_any.rs b/src/tools/clippy/clippy_lints/src/methods/string_lit_chars_any.rs index 5f6f027a3b5..cc0d432b799 100644 --- a/src/tools/clippy/clippy_lints/src/methods/string_lit_chars_any.rs +++ b/src/tools/clippy/clippy_lints/src/methods/string_lit_chars_any.rs @@ -1,6 +1,6 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::{is_from_proc_macro, is_trait_method, path_to_local}; use itertools::Itertools; use rustc_ast::LitKind; @@ -34,7 +34,7 @@ pub(super) fn check<'tcx>( _ => return, } && !is_from_proc_macro(cx, expr) - && let Some(scrutinee_snip) = snippet_opt(cx, scrutinee.span) + && let Some(scrutinee_snip) = scrutinee.span.get_source_text(cx) { // Normalize the char using `map` so `join` doesn't use `Display`, if we don't then // something like `r"\"` will become `'\'`, which is of course invalid diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_get_then_check.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_get_then_check.rs index f6184222d8e..64eb8411795 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_get_then_check.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_get_then_check.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::is_type_diagnostic_item; use rustc_errors::Applicability; @@ -38,11 +38,11 @@ pub(super) fn check( return; }; let both_calls_span = get_call_span.with_hi(call_span.hi()); - if let Some(snippet) = snippet_opt(cx, both_calls_span) - && let Some(arg_snippet) = snippet_opt(cx, arg.span) + if let Some(snippet) = both_calls_span.get_source_text(cx) + && let Some(arg_snippet) = arg.span.get_source_text(cx) { let generics_snippet = if let Some(generics) = path.args - && let Some(generics_snippet) = snippet_opt(cx, generics.span_ext) + && let Some(generics_snippet) = generics.span_ext.get_source_text(cx) { format!("::{generics_snippet}") } else { @@ -63,7 +63,7 @@ pub(super) fn check( suggestion, Applicability::MaybeIncorrect, ); - } else if let Some(caller_snippet) = snippet_opt(cx, get_caller.span) { + } else if let Some(caller_snippet) = get_caller.span.get_source_text(cx) { let full_span = get_caller.span.with_hi(call_span.hi()); span_lint_and_then( diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs index 70885e46e95..4d18bc7ac77 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs @@ -1,7 +1,7 @@ use super::utils::clone_or_copy_needed; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher::ForLoop; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::{get_iterator_item_ty, implements_trait}; use clippy_utils::visitors::for_each_expr_without_closures; use clippy_utils::{can_mut_borrow_both, fn_def_id, get_parent_expr, path_to_local}; @@ -40,7 +40,7 @@ pub fn check_for_loop_iter( && let Some(ForLoop { pat, body, .. }) = ForLoop::hir(grandparent) && let (clone_or_copy_needed, references_to_binding) = clone_or_copy_needed(cx, pat, body) && !clone_or_copy_needed - && let Some(receiver_snippet) = snippet_opt(cx, receiver.span) + && let Some(receiver_snippet) = receiver.span.get_source_text(cx) { // Issue 12098 // https://github.com/rust-lang/rust-clippy/issues/12098 @@ -100,7 +100,7 @@ pub fn check_for_loop_iter( && implements_trait(cx, collection_ty, into_iterator_trait_id, &[]) && let Some(into_iter_item_ty) = cx.get_associated_type(collection_ty, into_iterator_trait_id, "Item") && iter_item_ty == into_iter_item_ty - && let Some(collection_snippet) = snippet_opt(cx, collection.span) + && let Some(collection_snippet) = collection.span.get_source_text(cx) { collection_snippet } else { @@ -122,7 +122,7 @@ pub fn check_for_loop_iter( } else { Applicability::MachineApplicable }; - diag.span_suggestion(expr.span, "use", snippet, applicability); + diag.span_suggestion(expr.span, "use", snippet.to_owned(), applicability); if !references_to_binding.is_empty() { diag.multipart_suggestion( "remove any references to the binding", diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs index 4429f032605..b84594c0da1 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs @@ -64,9 +64,9 @@ pub(super) fn check<'tcx>( // but prefer to avoid changing the signature of the function itself. if let hir::ExprKind::MethodCall(.., span) = expr.kind { span_lint_and_then(cx, UNNECESSARY_LAZY_EVALUATIONS, expr.span, msg, |diag| { - diag.span_suggestion( + diag.span_suggestion_verbose( span, - format!("use `{simplify_using}(..)` instead"), + format!("use `{simplify_using}` instead"), format!("{simplify_using}({})", snippet(cx, body_expr.span, "..")), applicability, ); diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs index fed2b128dcf..69c5bc57e29 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -2,7 +2,7 @@ use super::implicit_clone::is_clone_like; use super::unnecessary_iter_cloned::{self, is_into_iter}; use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; -use clippy_utils::source::{snippet, snippet_opt}; +use clippy_utils::source::{snippet, SpanRangeExt}; use clippy_utils::ty::{get_iterator_item_ty, implements_trait, is_copy, is_type_diagnostic_item, is_type_lang_item}; use clippy_utils::visitors::find_all_ret_expressions; use clippy_utils::{ @@ -133,7 +133,7 @@ fn check_addr_of_expr( && (*referent_ty != receiver_ty || (matches!(referent_ty.kind(), ty::Array(..)) && is_copy(cx, *referent_ty)) || is_cow_into_owned(cx, method_name, method_def_id)) - && let Some(receiver_snippet) = snippet_opt(cx, receiver.span) + && let Some(receiver_snippet) = receiver.span.get_source_text(cx) { if receiver_ty == target_ty && n_target_refs >= n_receiver_refs { span_lint_and_sugg( @@ -167,7 +167,7 @@ fn check_addr_of_expr( parent.span, format!("unnecessary use of `{method_name}`"), "use", - receiver_snippet, + receiver_snippet.to_owned(), Applicability::MachineApplicable, ); } else { @@ -217,7 +217,7 @@ fn check_into_iter_call_arg( && let parent_ty = cx.typeck_results().expr_ty(parent) && implements_trait(cx, parent_ty, iterator_trait_id, &[]) && let Some(item_ty) = get_iterator_item_ty(cx, parent_ty) - && let Some(receiver_snippet) = snippet_opt(cx, receiver.span) + && let Some(receiver_snippet) = receiver.span.get_source_text(cx) { if unnecessary_iter_cloned::check_for_loop_iter(cx, parent, method_name, receiver, true) { return true; @@ -309,8 +309,8 @@ fn check_split_call_arg(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symb if let Some(parent) = get_parent_expr(cx, expr) && let Some((fn_name, argument_expr)) = get_fn_name_and_arg(cx, parent) && fn_name.as_str() == "split" - && let Some(receiver_snippet) = snippet_opt(cx, receiver.span) - && let Some(arg_snippet) = snippet_opt(cx, argument_expr.span) + && let Some(receiver_snippet) = receiver.span.get_source_text(cx) + && let Some(arg_snippet) = argument_expr.span.get_source_text(cx) { // We may end-up here because of an expression like `x.to_string().split(…)` where the type of `x` // implements `AsRef` but does not implement `Deref`. In this case, we have to @@ -405,7 +405,7 @@ fn check_other_call_arg<'tcx>( None } && can_change_type(cx, maybe_arg, receiver_ty) - && let Some(receiver_snippet) = snippet_opt(cx, receiver.span) + && let Some(receiver_snippet) = receiver.span.get_source_text(cx) { span_lint_and_sugg( cx, @@ -695,7 +695,7 @@ fn check_if_applicable_to_argument<'tcx>(cx: &LateContext<'tcx>, arg: &Expr<'tcx && let arg_ty = arg_ty.peel_refs() // For now we limit this lint to `String` and `Vec`. && (is_str_and_string(cx, arg_ty, original_arg_ty) || is_slice_and_vec(cx, arg_ty, original_arg_ty)) - && let Some(snippet) = snippet_opt(cx, caller.span) + && let Some(snippet) = caller.span.get_source_text(cx) { span_lint_and_sugg( cx, @@ -706,7 +706,7 @@ fn check_if_applicable_to_argument<'tcx>(cx: &LateContext<'tcx>, arg: &Expr<'tcx if original_arg_ty.is_array() { format!("{snippet}.as_slice()") } else { - snippet + snippet.to_owned() }, Applicability::MaybeIncorrect, ); diff --git a/src/tools/clippy/clippy_lints/src/methods/unused_enumerate_index.rs b/src/tools/clippy/clippy_lints/src/methods/unused_enumerate_index.rs index 3004d9c4233..ee5177d1ffa 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unused_enumerate_index.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unused_enumerate_index.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_hir_and_then; -use clippy_utils::source::{snippet, snippet_opt}; +use clippy_utils::source::{snippet, SpanRangeExt}; use clippy_utils::{expr_or_init, is_trait_method, pat_is_wild}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, FnDecl, PatKind, TyKind}; @@ -81,8 +81,14 @@ pub(super) fn check(cx: &LateContext<'_>, call_expr: &Expr<'_>, recv: &Expr<'_>, let new_closure_param = match find_elem_explicit_type_span(closure.fn_decl) { // We have an explicit type. Get its snippet, that of the binding name, and do `binding: ty`. // Fallback to `..` if we fail getting either snippet. - Some(ty_span) => snippet_opt(cx, elem.span) - .and_then(|binding_name| snippet_opt(cx, ty_span).map(|ty_name| format!("{binding_name}: {ty_name}"))) + Some(ty_span) => elem + .span + .get_source_text(cx) + .and_then(|binding_name| { + ty_span + .get_source_text(cx) + .map(|ty_name| format!("{binding_name}: {ty_name}")) + }) .unwrap_or_else(|| "..".to_string()), // Otherwise, we have no explicit type. We can replace with the binding name of the element. None => snippet(cx, elem.span, "..").into_owned(), diff --git a/src/tools/clippy/clippy_lints/src/min_ident_chars.rs b/src/tools/clippy/clippy_lints/src/min_ident_chars.rs index 53fa444e93c..c83e5198c27 100644 --- a/src/tools/clippy/clippy_lints/src/min_ident_chars.rs +++ b/src/tools/clippy/clippy_lints/src/min_ident_chars.rs @@ -41,14 +41,14 @@ declare_clippy_lint! { impl_lint_pass!(MinIdentChars => [MIN_IDENT_CHARS]); pub struct MinIdentChars { - allowed_idents_below_min_chars: &'static FxHashSet, + allowed_idents_below_min_chars: FxHashSet, min_ident_chars_threshold: u64, } impl MinIdentChars { pub fn new(conf: &'static Conf) -> Self { Self { - allowed_idents_below_min_chars: &conf.allowed_idents_below_min_chars, + allowed_idents_below_min_chars: conf.allowed_idents_below_min_chars.iter().cloned().collect(), min_ident_chars_threshold: conf.min_ident_chars_threshold, } } diff --git a/src/tools/clippy/clippy_lints/src/misc_early/unneeded_field_pattern.rs b/src/tools/clippy/clippy_lints/src/misc_early/unneeded_field_pattern.rs index 6db03adf44a..33ab94e00a5 100644 --- a/src/tools/clippy/clippy_lints/src/misc_early/unneeded_field_pattern.rs +++ b/src/tools/clippy/clippy_lints/src/misc_early/unneeded_field_pattern.rs @@ -1,5 +1,6 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; +use itertools::Itertools; use rustc_ast::ast::{Pat, PatKind}; use rustc_lint::EarlyContext; @@ -45,19 +46,6 @@ pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) { "you matched a field with a wildcard pattern, consider using `..` instead", ); } else { - let mut normal = vec![]; - - for field in pfields { - match field.pat.kind { - PatKind::Wild => {}, - _ => { - if let Some(n) = snippet_opt(cx, field.span) { - normal.push(n); - } - }, - } - } - #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")] span_lint_and_then( cx, @@ -65,7 +53,16 @@ pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) { field.span, "you matched a field with a wildcard pattern, consider using `..` instead", |diag| { - diag.help(format!("try with `{type_name} {{ {}, .. }}`", normal[..].join(", "))); + diag.help(format!( + "try with `{type_name} {{ {}, .. }}`", + pfields + .iter() + .filter_map(|f| match f.pat.kind { + PatKind::Wild => None, + _ => f.span.get_source_text(cx), + }) + .format(", "), + )); }, ); } diff --git a/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs b/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs index cdf6645b3df..59f29d242ab 100644 --- a/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs +++ b/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; use clippy_utils::def_path_def_ids; use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::def_id::DefIdMap; @@ -73,7 +73,7 @@ impl LateLintPass<'_> for ImportRename { && let Some(name) = self.renames.get(&id) // Remove semicolon since it is not present for nested imports && let span_without_semi = cx.sess().source_map().span_until_char(item.span, ';') - && let Some(snip) = snippet_opt(cx, span_without_semi) + && let Some(snip) = span_without_semi.get_source_text(cx) && let Some(import) = match snip.split_once(" as ") { None => Some(snip.as_str()), Some((import, rename)) => { diff --git a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs index 6964d8c8dbb..0b3769ecb7c 100644 --- a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs +++ b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs @@ -166,7 +166,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> { ExprKind::Call(func, _) => { let typ = self.cx.typeck_results().expr_ty(func); match typ.kind() { - ty::FnDef(..) | ty::FnPtr(_) => { + ty::FnDef(..) | ty::FnPtr(..) => { let sig = typ.fn_sig(self.cx.tcx); if self.cx.tcx.instantiate_bound_regions_with_erased(sig).output().kind() == &ty::Never { self.report_diverging_sub_expr(e); diff --git a/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs index da74a7c7145..0bde0da3cd8 100644 --- a/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs +++ b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs @@ -130,7 +130,7 @@ fn collect_unsafe_exprs<'tcx>( ExprKind::Call(path_expr, _) => { let sig = match *cx.typeck_results().expr_ty(path_expr).kind() { ty::FnDef(id, _) => cx.tcx.fn_sig(id).skip_binder(), - ty::FnPtr(sig) => sig, + ty::FnPtr(sig_tys, hdr) => sig_tys.with(hdr), _ => return Continue(Descend::Yes), }; if sig.safety() == Safety::Unsafe { diff --git a/src/tools/clippy/clippy_lints/src/mut_key.rs b/src/tools/clippy/clippy_lints/src/mut_key.rs index 83af9979b9e..f52b3a6a5a1 100644 --- a/src/tools/clippy/clippy_lints/src/mut_key.rs +++ b/src/tools/clippy/clippy_lints/src/mut_key.rs @@ -125,14 +125,12 @@ impl<'tcx> MutableKeyType<'tcx> { // generics (because the compiler cannot ensure immutability for unknown types). fn check_ty_(&mut self, cx: &LateContext<'tcx>, span: Span, ty: Ty<'tcx>) { let ty = ty.peel_refs(); - if let ty::Adt(def, args) = ty.kind() { - let is_keyed_type = [sym::HashMap, sym::BTreeMap, sym::HashSet, sym::BTreeSet] - .iter() - .any(|diag_item| cx.tcx.is_diagnostic_item(*diag_item, def.did())); - if !is_keyed_type { - return; - } - + if let ty::Adt(def, args) = ty.kind() + && matches!( + cx.tcx.get_diagnostic_name(def.did()), + Some(sym::HashMap | sym::BTreeMap | sym::HashSet | sym::BTreeSet) + ) + { let subst_ty = args.type_at(0); if self.interior_mut.is_interior_mut_ty(cx, subst_ty) { span_lint(cx, MUTABLE_KEY_TYPE, span, "mutable key type"); diff --git a/src/tools/clippy/clippy_lints/src/mut_reference.rs b/src/tools/clippy/clippy_lints/src/mut_reference.rs index 0a3b769c3e6..3c0f06f66d1 100644 --- a/src/tools/clippy/clippy_lints/src/mut_reference.rs +++ b/src/tools/clippy/clippy_lints/src/mut_reference.rs @@ -79,7 +79,7 @@ fn check_arguments<'tcx>( fn_kind: &str, ) { match type_definition.kind() { - ty::FnDef(..) | ty::FnPtr(_) => { + ty::FnDef(..) | ty::FnPtr(..) => { let parameters = type_definition.fn_sig(cx.tcx).skip_binder().inputs(); for (argument, parameter) in iter::zip(arguments, parameters) { match parameter.kind() { diff --git a/src/tools/clippy/clippy_lints/src/mutex_atomic.rs b/src/tools/clippy/clippy_lints/src/mutex_atomic.rs index 853e476a006..38841496458 100644 --- a/src/tools/clippy/clippy_lints/src/mutex_atomic.rs +++ b/src/tools/clippy/clippy_lints/src/mutex_atomic.rs @@ -1,7 +1,3 @@ -//! Checks for usage of mutex where an atomic value could be used -//! -//! This lint is **allow** by default - use clippy_utils::diagnostics::span_lint; use clippy_utils::ty::is_type_diagnostic_item; use rustc_hir::Expr; diff --git a/src/tools/clippy/clippy_lints/src/needless_bool.rs b/src/tools/clippy/clippy_lints/src/needless_bool.rs index 9cb4fa41c73..df155a7a412 100644 --- a/src/tools/clippy/clippy_lints/src/needless_bool.rs +++ b/src/tools/clippy/clippy_lints/src/needless_bool.rs @@ -1,7 +1,3 @@ -//! Checks for needless boolean results of if-else expressions -//! -//! This lint is **warn** by default - use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::sugg::Sugg; diff --git a/src/tools/clippy/clippy_lints/src/needless_continue.rs b/src/tools/clippy/clippy_lints/src/needless_continue.rs index b97cb4579ca..ce97370d4d9 100644 --- a/src/tools/clippy/clippy_lints/src/needless_continue.rs +++ b/src/tools/clippy/clippy_lints/src/needless_continue.rs @@ -1,38 +1,3 @@ -//! Checks for continue statements in loops that are redundant. -//! -//! For example, the lint would catch -//! -//! ```rust -//! let mut a = 1; -//! let x = true; -//! -//! while a < 5 { -//! a = 6; -//! if x { -//! // ... -//! } else { -//! continue; -//! } -//! println!("Hello, world"); -//! } -//! ``` -//! -//! And suggest something like this: -//! -//! ```rust -//! let mut a = 1; -//! let x = true; -//! -//! while a < 5 { -//! a = 6; -//! if x { -//! // ... -//! println!("Hello, world"); -//! } -//! } -//! ``` -//! -//! This lint is **warn** by default. use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::source::{indent_of, snippet, snippet_block}; use rustc_ast::ast; diff --git a/src/tools/clippy/clippy_lints/src/needless_if.rs b/src/tools/clippy/clippy_lints/src/needless_if.rs index 1d6233d432a..8e14fbf2f80 100644 --- a/src/tools/clippy/clippy_lints/src/needless_if.rs +++ b/src/tools/clippy/clippy_lints/src/needless_if.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::higher::If; use clippy_utils::is_from_proc_macro; -use clippy_utils::source::{snippet_opt, SpanRangeExt}; +use clippy_utils::source::SpanRangeExt; use rustc_errors::Applicability; use rustc_hir::{ExprKind, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -57,7 +57,7 @@ impl LateLintPass<'_> for NeedlessIf { src.bytes() .all(|ch| matches!(ch, b'{' | b'}') || ch.is_ascii_whitespace()) }) - && let Some(cond_snippet) = snippet_opt(cx, cond.span) + && let Some(cond_snippet) = cond.span.get_source_text(cx) && !is_from_proc_macro(cx, expr) { span_lint_and_sugg( diff --git a/src/tools/clippy/clippy_lints/src/needless_late_init.rs b/src/tools/clippy/clippy_lints/src/needless_late_init.rs index 4bfc30fa5cf..46cdb82130f 100644 --- a/src/tools/clippy/clippy_lints/src/needless_late_init.rs +++ b/src/tools/clippy/clippy_lints/src/needless_late_init.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::path_to_local; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::{SourceText, SpanRangeExt}; use clippy_utils::ty::needs_ordered_drop; use clippy_utils::visitors::{for_each_expr, for_each_expr_without_closures, is_local_used}; use core::ops::ControlFlow; @@ -236,7 +236,7 @@ fn first_usage<'tcx>( }) } -fn local_snippet_without_semicolon(cx: &LateContext<'_>, local: &LetStmt<'_>) -> Option { +fn local_snippet_without_semicolon(cx: &LateContext<'_>, local: &LetStmt<'_>) -> Option { let span = local.span.with_hi(match local.ty { // let : ; // ~~~~~~~~~~~~~~~ @@ -246,7 +246,7 @@ fn local_snippet_without_semicolon(cx: &LateContext<'_>, local: &LetStmt<'_>) -> None => local.pat.span.hi(), }); - snippet_opt(cx, span) + span.get_source_text(cx) } fn check<'tcx>( @@ -275,7 +275,10 @@ fn check<'tcx>( |diag| { diag.multipart_suggestion( format!("move the declaration `{binding_name}` here"), - vec![(local_stmt.span, String::new()), (assign.lhs_span, let_snippet)], + vec![ + (local_stmt.span, String::new()), + (assign.lhs_span, let_snippet.to_owned()), + ], Applicability::MachineApplicable, ); }, diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs index a0bbf6b14b2..addb4b1aee8 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_self; use clippy_utils::ptr::get_spans; -use clippy_utils::source::{snippet, snippet_opt}; +use clippy_utils::source::{snippet, SpanRangeExt}; use clippy_utils::ty::{ implements_trait, implements_trait_with_env_from_iter, is_copy, is_type_diagnostic_item, is_type_lang_item, }; @@ -242,8 +242,8 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { for (span, suggestion) in clone_spans { diag.span_suggestion( span, - snippet_opt(cx, span) - .map_or("change the call to".into(), |x| format!("change `{x}` to")), + span.get_source_text(cx) + .map_or("change the call to".to_owned(), |src| format!("change `{src}` to")), suggestion, Applicability::Unspecified, ); @@ -267,8 +267,8 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { for (span, suggestion) in clone_spans { diag.span_suggestion( span, - snippet_opt(cx, span) - .map_or("change the call to".into(), |x| format!("change `{x}` to")), + span.get_source_text(cx) + .map_or("change the call to".to_owned(), |src| format!("change `{src}` to")), suggestion, Applicability::Unspecified, ); diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs index 8232e69db39..b181791699a 100644 --- a/src/tools/clippy/clippy_lints/src/no_effect.rs +++ b/src/tools/clippy/clippy_lints/src/no_effect.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then}; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::has_drop; use clippy_utils::{ in_automatically_derived, is_inside_always_const_context, is_lint_allowed, path_to_local, peel_blocks, @@ -268,34 +268,31 @@ fn check_unnecessary_operation(cx: &LateContext<'_>, stmt: &Stmt<'_>) { && reduced.iter().all(|e| e.span.ctxt() == ctxt) { if let ExprKind::Index(..) = &expr.kind { - if is_inside_always_const_context(cx.tcx, expr.hir_id) { - return; + if !is_inside_always_const_context(cx.tcx, expr.hir_id) + && let [arr, func] = &*reduced + && let Some(arr) = arr.span.get_source_text(cx) + && let Some(func) = func.span.get_source_text(cx) + { + span_lint_hir_and_then( + cx, + UNNECESSARY_OPERATION, + expr.hir_id, + stmt.span, + "unnecessary operation", + |diag| { + diag.span_suggestion( + stmt.span, + "statement can be written as", + format!("assert!({arr}.len() > {func});"), + Applicability::MaybeIncorrect, + ); + }, + ); } - let snippet = - if let (Some(arr), Some(func)) = (snippet_opt(cx, reduced[0].span), snippet_opt(cx, reduced[1].span)) { - format!("assert!({arr}.len() > {func});") - } else { - return; - }; - span_lint_hir_and_then( - cx, - UNNECESSARY_OPERATION, - expr.hir_id, - stmt.span, - "unnecessary operation", - |diag| { - diag.span_suggestion( - stmt.span, - "statement can be written as", - snippet, - Applicability::MaybeIncorrect, - ); - }, - ); } else { let mut snippet = String::new(); for e in reduced { - if let Some(snip) = snippet_opt(cx, e.span) { + if let Some(snip) = e.span.get_source_text(cx) { snippet.push_str(&snip); snippet.push(';'); } else { diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index 6915cd40615..25f547f1a43 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -1,7 +1,3 @@ -//! Checks for usage of const which the type is not `Freeze` (`Cell`-free). -//! -//! This lint is **warn** by default. - use std::ptr; use clippy_config::Conf; @@ -188,7 +184,7 @@ impl_lint_pass!(NonCopyConst<'_> => [DECLARE_INTERIOR_MUTABLE_CONST, BORROW_INTE impl<'tcx> NonCopyConst<'tcx> { pub fn new(tcx: TyCtxt<'tcx>, conf: &'static Conf) -> Self { Self { - interior_mut: InteriorMut::new(tcx, &conf.ignore_interior_mutability), + interior_mut: InteriorMut::without_pointers(tcx, &conf.ignore_interior_mutability), } } diff --git a/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs b/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs index 2aaf1e6ff46..51ba29d7389 100644 --- a/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs +++ b/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs @@ -1,7 +1,7 @@ use clippy_config::types::MacroMatcher; use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::{SourceText, SpanRangeExt}; use rustc_ast::ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; @@ -34,7 +34,7 @@ declare_clippy_lint! { } /// The (callsite span, (open brace, close brace), source snippet) -type MacroInfo = (Span, (char, char), String); +type MacroInfo = (Span, (char, char), SourceText); pub struct MacroBraces { macro_braces: FxHashMap, @@ -94,7 +94,7 @@ fn is_offending_macro(cx: &EarlyContext<'_>, span: Span, mac_braces: &MacroBrace if let ExpnKind::Macro(MacroKind::Bang, mac_name) = span.ctxt().outer_expn_data().kind && let name = mac_name.as_str() && let Some(&braces) = mac_braces.macro_braces.get(name) - && let Some(snip) = snippet_opt(cx, span_call_site) + && let Some(snip) = span_call_site.get_source_text(cx) // we must check only invocation sites // https://github.com/rust-lang/rust-clippy/issues/7422 && snip.starts_with(&format!("{name}!")) diff --git a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs index bc71a4790b9..8b9f899d82d 100644 --- a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs +++ b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs @@ -35,7 +35,7 @@ impl ArithmeticSideEffects { ("f64", FxHashSet::from_iter(["f64"])), ("std::string::String", FxHashSet::from_iter(["str"])), ]); - for [lhs, rhs] in &conf.arithmetic_side_effects_allowed_binary { + for (lhs, rhs) in &conf.arithmetic_side_effects_allowed_binary { allowed_binary.entry(lhs).or_default().insert(rhs); } for s in &conf.arithmetic_side_effects_allowed { diff --git a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs index 641d881d974..11c97b4ef00 100644 --- a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs +++ b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::implements_trait; use clippy_utils::visitors::for_each_expr_without_closures; use clippy_utils::{binop_traits, eq_expr_value, trait_ref_of_method}; @@ -46,8 +46,8 @@ pub(super) fn check<'tcx>( expr.span, "manual implementation of an assign operation", |diag| { - if let (Some(snip_a), Some(snip_r)) = - (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span)) + if let Some(snip_a) = assignee.span.get_source_text(cx) + && let Some(snip_r) = rhs.span.get_source_text(cx) { diag.span_suggestion( expr.span, diff --git a/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs b/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs index 311cbd050a1..8daedd1c901 100644 --- a/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs +++ b/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::{eq_expr_value, sugg}; use rustc_errors::Applicability; use rustc_hir as hir; @@ -42,7 +42,9 @@ fn lint_misrefactored_assign_op( expr.span, "variable appears on both sides of an assignment operation", |diag| { - if let (Some(snip_a), Some(snip_r)) = (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs_other.span)) { + if let Some(snip_a) = assignee.span.get_source_text(cx) + && let Some(snip_r) = rhs_other.span.get_source_text(cx) + { let a = &sugg::Sugg::hir(cx, assignee, ".."); let r = &sugg::Sugg::hir(cx, rhs, ".."); let long = format!("{snip_a} = {}", sugg::make_binop(op, a, r)); diff --git a/src/tools/clippy/clippy_lints/src/operators/mod.rs b/src/tools/clippy/clippy_lints/src/operators/mod.rs index 9baecff801f..9e8a821c3f4 100644 --- a/src/tools/clippy/clippy_lints/src/operators/mod.rs +++ b/src/tools/clippy/clippy_lints/src/operators/mod.rs @@ -80,7 +80,7 @@ declare_clippy_lint! { /// ```no_run /// // `n` can be any number, including `i32::MAX`. /// fn foo(n: i32) -> i32 { - /// n + 1 + /// n + 1 /// } /// ``` /// diff --git a/src/tools/clippy/clippy_lints/src/operators/needless_bitwise_bool.rs b/src/tools/clippy/clippy_lints/src/operators/needless_bitwise_bool.rs index ab5fb178700..9d8e833ef6d 100644 --- a/src/tools/clippy/clippy_lints/src/operators/needless_bitwise_bool.rs +++ b/src/tools/clippy/clippy_lints/src/operators/needless_bitwise_bool.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::LateContext; @@ -24,8 +24,8 @@ pub(super) fn check(cx: &LateContext<'_>, e: &Expr<'_>, op: BinOpKind, lhs: &Exp e.span, "use of bitwise operator instead of lazy operator between booleans", |diag| { - if let Some(lhs_snip) = snippet_opt(cx, lhs.span) - && let Some(rhs_snip) = snippet_opt(cx, rhs.span) + if let Some(lhs_snip) = lhs.span.get_source_text(cx) + && let Some(rhs_snip) = rhs.span.get_source_text(cx) { let sugg = format!("{lhs_snip} {op_str} {rhs_snip}"); diag.span_suggestion(e.span, "try", sugg, Applicability::MachineApplicable); diff --git a/src/tools/clippy/clippy_lints/src/operators/ptr_eq.rs b/src/tools/clippy/clippy_lints/src/operators/ptr_eq.rs index 607930561e0..861564d5456 100644 --- a/src/tools/clippy/clippy_lints/src/operators/ptr_eq.rs +++ b/src/tools/clippy/clippy_lints/src/operators/ptr_eq.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::std_or_core; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; @@ -22,8 +22,8 @@ pub(super) fn check<'tcx>( if let Some(left_var) = expr_as_cast_to_raw_pointer(cx, left) && let Some(right_var) = expr_as_cast_to_raw_pointer(cx, right) - && let Some(left_snip) = snippet_opt(cx, left_var.span) - && let Some(right_snip) = snippet_opt(cx, right_var.span) + && let Some(left_snip) = left_var.span.get_source_text(cx) + && let Some(right_snip) = right_var.span.get_source_text(cx) { let Some(top_crate) = std_or_core(cx) else { return }; span_lint_and_sugg( diff --git a/src/tools/clippy/clippy_lints/src/pathbuf_init_then_push.rs b/src/tools/clippy/clippy_lints/src/pathbuf_init_then_push.rs index 18bfb588a11..d7fa48c1e38 100644 --- a/src/tools/clippy/clippy_lints/src/pathbuf_init_then_push.rs +++ b/src/tools/clippy/clippy_lints/src/pathbuf_init_then_push.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::path_to_local_id; -use clippy_utils::source::{snippet, snippet_opt}; +use clippy_utils::source::{snippet, SpanRangeExt}; use clippy_utils::ty::is_type_diagnostic_item; use rustc_ast::{LitKind, StrStyle}; use rustc_errors::Applicability; @@ -74,7 +74,7 @@ impl<'tcx> PathbufPushSearcher<'tcx> { && let Some(arg) = self.arg && let ExprKind::Lit(x) = arg.kind && let LitKind::Str(_, StrStyle::Cooked) = x.node - && let Some(s) = snippet_opt(cx, arg.span) + && let Some(s) = arg.span.get_source_text(cx) { Some(format!(" = PathBuf::from({s});")) } else { @@ -84,8 +84,8 @@ impl<'tcx> PathbufPushSearcher<'tcx> { fn gen_pathbuf_join(&self, cx: &LateContext<'_>) -> Option { let arg = self.arg?; - let arg_str = snippet_opt(cx, arg.span)?; - let init_val = snippet_opt(cx, self.init_val.span)?; + let arg_str = arg.span.get_source_text(cx)?; + let init_val = self.init_val.span.get_source_text(cx)?; Some(format!(" = {init_val}.join({arg_str});")) } diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs index 02c05e0aaf9..125f694996c 100644 --- a/src/tools/clippy/clippy_lints/src/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/ptr.rs @@ -1,7 +1,5 @@ -//! Checks for usage of `&Vec[_]` and `&String`. - use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then, span_lint_hir_and_then}; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::expr_sig; use clippy_utils::visitors::contains_unsafe_block; use clippy_utils::{get_expr_use_or_unification_node, is_lint_allowed, path_def_id, path_to_local}; @@ -243,7 +241,7 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { .chain(result.replacements.iter().map(|r| { ( r.expr_span, - format!("{}{}", snippet_opt(cx, r.self_span).unwrap(), r.replacement), + format!("{}{}", r.self_span.get_source_text(cx).unwrap(), r.replacement), ) })) .collect(), @@ -372,7 +370,7 @@ impl fmt::Display for DerefTyDisplay<'_, '_> { DerefTy::Path => f.write_str("Path"), DerefTy::Slice(hir_ty, ty) => { f.write_char('[')?; - match hir_ty.and_then(|s| snippet_opt(self.0, s)) { + match hir_ty.and_then(|s| s.get_source_text(self.0)) { Some(s) => f.write_str(&s)?, None => ty.fmt(f)?, } @@ -413,6 +411,7 @@ impl<'tcx> DerefTy<'tcx> { } } +#[expect(clippy::too_many_lines)] fn check_fn_args<'cx, 'tcx: 'cx>( cx: &'cx LateContext<'tcx>, fn_sig: ty::FnSig<'tcx>, @@ -488,8 +487,6 @@ fn check_fn_args<'cx, 'tcx: 'cx>( return None; } - let ty_name = snippet_opt(cx, ty.span()).unwrap_or_else(|| args.type_at(1).to_string()); - span_lint_hir_and_then( cx, PTR_ARG, @@ -500,7 +497,10 @@ fn check_fn_args<'cx, 'tcx: 'cx>( diag.span_suggestion( hir_ty.span, "change this to", - format!("&{}{ty_name}", mutability.prefix_str()), + match ty.span().get_source_text(cx) { + Some(s) => format!("&{}{s}", mutability.prefix_str()), + None => format!("&{}{}", mutability.prefix_str(), args.type_at(1)), + }, Applicability::Unspecified, ); }, diff --git a/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs b/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs index 7c82895d609..87a52cb2186 100644 --- a/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs +++ b/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -120,8 +120,8 @@ fn build_suggestion( receiver_expr: &Expr<'_>, cast_lhs_expr: &Expr<'_>, ) -> Option { - let receiver = snippet_opt(cx, receiver_expr.span)?; - let cast_lhs = snippet_opt(cx, cast_lhs_expr.span)?; + let receiver = receiver_expr.span.get_source_text(cx)?; + let cast_lhs = cast_lhs_expr.span.get_source_text(cx)?; Some(format!("{receiver}.{}({cast_lhs})", method.suggestion())) } diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs index a1231c082e6..bfdc1cbeed7 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then}; use clippy_utils::mir::{visit_local_usage, LocalUsage, PossibleBorrowerMap}; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::{has_drop, is_copy, is_type_diagnostic_item, is_type_lang_item, walk_ptrs_ty_depth}; use clippy_utils::{fn_has_unsatisfiable_preds, match_def_path, paths}; use rustc_errors::Applicability; @@ -208,7 +208,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone { .assert_crate_local() .lint_root; - if let Some(snip) = snippet_opt(cx, span) + if let Some(snip) = span.get_source_text(cx) && let Some(dot) = snip.rfind('.') { let sugg_span = span.with_lo(span.lo() + BytePos(u32::try_from(dot).unwrap())); diff --git a/src/tools/clippy/clippy_lints/src/reference.rs b/src/tools/clippy/clippy_lints/src/reference.rs index 8f32cf5f2a1..2b4ef21fc48 100644 --- a/src/tools/clippy/clippy_lints/src/reference.rs +++ b/src/tools/clippy/clippy_lints/src/reference.rs @@ -1,10 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::{snippet_opt, snippet_with_applicability}; +use clippy_utils::source::{snippet_with_applicability, SpanRangeExt}; use rustc_ast::ast::{Expr, ExprKind, Mutability, UnOp}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::declare_lint_pass; -use rustc_span::BytePos; +use rustc_span::{BytePos, Span}; declare_clippy_lint! { /// ### What it does @@ -56,11 +56,11 @@ impl EarlyLintPass for DerefAddrOf { { let mut applicability = Applicability::MachineApplicable; let sugg = if e.span.from_expansion() { - if let Some(macro_source) = snippet_opt(cx, e.span) { + if let Some(macro_source) = e.span.get_source_text(cx) { // Remove leading whitespace from the given span // e.g: ` $visitor` turns into `$visitor` - let trim_leading_whitespaces = |span| { - snippet_opt(cx, span) + let trim_leading_whitespaces = |span: Span| { + span.get_source_text(cx) .and_then(|snip| { #[expect(clippy::cast_possible_truncation)] snip.find(|c: char| !c.is_whitespace()) diff --git a/src/tools/clippy/clippy_lints/src/regex.rs b/src/tools/clippy/clippy_lints/src/regex.rs index 95014b23043..f6ef02b7c23 100644 --- a/src/tools/clippy/clippy_lints/src/regex.rs +++ b/src/tools/clippy/clippy_lints/src/regex.rs @@ -2,7 +2,7 @@ use std::fmt::Display; use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::{def_path_def_ids, path_def_id, paths}; use rustc_ast::ast::{LitKind, StrStyle}; use rustc_hir::def_id::DefIdMap; @@ -122,7 +122,7 @@ fn lint_syntax_error(cx: &LateContext<'_>, error: ®ex_syntax::Error, unescape }; if let Some((primary, auxiliary, kind)) = parts - && let Some(literal_snippet) = snippet_opt(cx, base) + && let Some(literal_snippet) = base.get_source_text(cx) && let Some(inner) = literal_snippet.get(offset as usize..) // Only convert to native rustc spans if the parsed regex matches the // source snippet exactly, to ensure the span offsets are correct diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs index 13016cdadb0..5ce091b7a7a 100644 --- a/src/tools/clippy/clippy_lints/src/returns.rs +++ b/src/tools/clippy/clippy_lints/src/returns.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then}; -use clippy_utils::source::{snippet_opt, snippet_with_context}; +use clippy_utils::source::{snippet_with_context, SpanRangeExt}; use clippy_utils::sugg::has_enclosing_paren; use clippy_utils::visitors::{for_each_expr, Descend}; use clippy_utils::{ @@ -250,20 +250,25 @@ impl<'tcx> LateLintPass<'tcx> for Return { |err| { err.span_label(local.span, "unnecessary `let` binding"); - if let Some(mut snippet) = snippet_opt(cx, initexpr.span) { - if binary_expr_needs_parentheses(initexpr) { - if !has_enclosing_paren(&snippet) { - snippet = format!("({snippet})"); + if let Some(src) = initexpr.span.get_source_text(cx) { + let sugg = if binary_expr_needs_parentheses(initexpr) { + if has_enclosing_paren(&src) { + src.to_owned() + } else { + format!("({src})") } } else if !cx.typeck_results().expr_adjustments(retexpr).is_empty() { - if !has_enclosing_paren(&snippet) { - snippet = format!("({snippet})"); + if has_enclosing_paren(&src) { + format!("{src} as _") + } else { + format!("({src}) as _") } - snippet.push_str(" as _"); - } + } else { + src.to_owned() + }; err.multipart_suggestion( "return the expression directly", - vec![(local.span, String::new()), (retexpr.span, snippet)], + vec![(local.span, String::new()), (retexpr.span, sugg)], Applicability::MachineApplicable, ); } else { @@ -394,7 +399,7 @@ fn check_final_expr<'tcx>( // Returns may be used to turn an expression into a statement in rustc's AST. // This allows the addition of attributes, like `#[allow]` (See: clippy#9361) - // `#[expect(clippy::needless_return)]` needs to be handled separatly to + // `#[expect(clippy::needless_return)]` needs to be handled separately to // actually fulfill the expectation (clippy::#12998) match cx.tcx.hir().attrs(expr.hir_id) { [] => {}, diff --git a/src/tools/clippy/clippy_lints/src/single_range_in_vec_init.rs b/src/tools/clippy/clippy_lints/src/single_range_in_vec_init.rs index e0558429638..44e585953bf 100644 --- a/src/tools/clippy/clippy_lints/src/single_range_in_vec_init.rs +++ b/src/tools/clippy/clippy_lints/src/single_range_in_vec_init.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::get_trait_def_id; use clippy_utils::higher::VecArgs; use clippy_utils::macros::root_macro_call_first_node; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::implements_trait; use rustc_ast::{LitIntType, LitKind, UintTy}; use rustc_errors::Applicability; @@ -92,12 +92,12 @@ impl LateLintPass<'_> for SingleRangeInVecInit { if matches!(lang_item, LangItem::Range) && let ty = cx.typeck_results().expr_ty(start.expr) - && let Some(snippet) = snippet_opt(cx, span) + && let Some(snippet) = span.get_source_text(cx) // `is_from_proc_macro` will skip any `vec![]`. Let's not! && snippet.starts_with(suggested_type.starts_with()) && snippet.ends_with(suggested_type.ends_with()) - && let Some(start_snippet) = snippet_opt(cx, start.span) - && let Some(end_snippet) = snippet_opt(cx, end.span) + && let Some(start_snippet) = start.span.get_source_text(cx) + && let Some(end_snippet) = end.span.get_source_text(cx) { let should_emit_every_value = if let Some(step_def_id) = get_trait_def_id(cx.tcx, &["core", "iter", "Step"]) && implements_trait(cx, ty, step_def_id, &[]) diff --git a/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs b/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs index 01f0e3cfadb..7750d8909d3 100644 --- a/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs +++ b/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs @@ -1,6 +1,3 @@ -//! Lint on use of `size_of` or `size_of_val` of T in an expression -//! expecting a count of T - use clippy_utils::diagnostics::span_lint_and_help; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; diff --git a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs index 974e21df817..44283a49e84 100644 --- a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs +++ b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs @@ -9,7 +9,6 @@ use rustc_hir::def_id::DefId; use rustc_hir::{HirId, Path, PathSegment}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_semver::RustcVersion; use rustc_session::impl_lint_pass; use rustc_span::symbol::kw; use rustc_span::{sym, Span}; @@ -185,9 +184,7 @@ fn is_stable(cx: &LateContext<'_>, mut def_id: DefId, msrv: &Msrv) -> bool { } = stability.level { let stable = match since { - StableSince::Version(v) => { - msrv.meets(RustcVersion::new(v.major.into(), v.minor.into(), v.patch.into())) - }, + StableSince::Version(v) => msrv.meets(v), StableSince::Current => msrv.current().is_none(), StableSince::Err => false, }; diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs index cfc387886dc..6ca4ca000e9 100644 --- a/src/tools/clippy/clippy_lints/src/strings.rs +++ b/src/tools/clippy/clippy_lints/src/strings.rs @@ -190,7 +190,7 @@ impl<'tcx> LateLintPass<'tcx> for StringAdd { } }, ExprKind::Index(target, _idx, _) => { - let e_ty = cx.typeck_results().expr_ty(target).peel_refs(); + let e_ty = cx.typeck_results().expr_ty_adjusted(target).peel_refs(); if e_ty.is_str() || is_type_lang_item(cx, e_ty, LangItem::String) { span_lint( cx, diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs index 59b74122f30..2e87d36df31 100644 --- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs +++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs @@ -1,7 +1,7 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_config::Conf; use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg}; -use clippy_utils::source::{snippet, snippet_opt, snippet_with_applicability}; +use clippy_utils::source::{snippet, snippet_with_applicability, SpanRangeExt}; use clippy_utils::{is_from_proc_macro, SpanlessEq, SpanlessHash}; use core::hash::{Hash, Hasher}; use itertools::Itertools; @@ -206,8 +206,7 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds { let fixed_trait_snippet = unique_traits .iter() - .filter_map(|b| snippet_opt(cx, b.span)) - .collect::>() + .filter_map(|b| b.span.get_source_text(cx)) .join(" + "); span_lint_and_sugg( @@ -462,9 +461,8 @@ fn rollup_traits( let traits = comparable_bounds .iter() - .filter_map(|&(_, span)| snippet_opt(cx, span)) - .collect::>(); - let traits = traits.join(" + "); + .filter_map(|&(_, span)| span.get_source_text(cx)) + .join(" + "); span_lint_and_sugg( cx, diff --git a/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs b/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs index afc53e6f32d..978d49f09c3 100644 --- a/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs +++ b/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_from_proc_macro; -use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt}; +use clippy_utils::source::{indent_of, reindent_multiline, SourceText, SpanRangeExt}; use rustc_errors::Applicability; use rustc_hir::{Block, Expr, ExprKind, MatchSource, Node, StmtKind}; use rustc_lint::LateContext; @@ -79,7 +79,7 @@ fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Exp && block.expr.is_none() && let Some(last_stmt) = block.stmts.iter().last() && let StmtKind::Semi(last_expr) = last_stmt.kind - && let Some(snip) = snippet_opt(cx, last_expr.span) + && let Some(snip) = last_expr.span.get_source_text(cx) { Some((last_stmt.span, snip)) } else { @@ -90,24 +90,24 @@ fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Exp db.span_suggestion( span, "remove the semicolon from the last statement in the block", - sugg, + sugg.as_str(), Applicability::MaybeIncorrect, ); or = "or "; applicability = Applicability::MaybeIncorrect; }); - let arg_snippets: Vec = args_to_recover + let arg_snippets: Vec<_> = args_to_recover .iter() - .filter_map(|arg| snippet_opt(cx, arg.span)) + .filter_map(|arg| arg.span.get_source_text(cx)) .collect(); - let arg_snippets_without_empty_blocks: Vec = args_to_recover + let arg_snippets_without_empty_blocks: Vec<_> = args_to_recover .iter() .filter(|arg| !is_empty_block(arg)) - .filter_map(|arg| snippet_opt(cx, arg.span)) + .filter_map(|arg| arg.span.get_source_text(cx)) .collect(); - if let Some(call_snippet) = snippet_opt(cx, expr.span) { + if let Some(call_snippet) = expr.span.get_source_text(cx) { let sugg = fmt_stmts_and_call( cx, expr, @@ -161,8 +161,8 @@ fn fmt_stmts_and_call( cx: &LateContext<'_>, call_expr: &Expr<'_>, call_snippet: &str, - args_snippets: &[impl AsRef], - non_empty_block_args_snippets: &[impl AsRef], + args_snippets: &[SourceText], + non_empty_block_args_snippets: &[SourceText], ) -> String { let call_expr_indent = indent_of(cx, call_expr.span).unwrap_or(0); let call_snippet_with_replacements = args_snippets diff --git a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs index 448946bd66d..af7abd009d2 100644 --- a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs +++ b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs @@ -34,11 +34,18 @@ declare_clippy_lint! { /// ```rust,ignore /// use std::io; /// fn foo(w: &mut W) -> io::Result<()> { - /// // must be `w.write_all(b"foo")?;` /// w.write(b"foo")?; /// Ok(()) /// } /// ``` + /// Use instead: + /// ```rust,ignore + /// use std::io; + /// fn foo(w: &mut W) -> io::Result<()> { + /// w.write_all(b"foo")?; + /// Ok(()) + /// } + /// ``` #[clippy::version = "pre 1.29.0"] pub UNUSED_IO_AMOUNT, correctness, @@ -235,7 +242,7 @@ fn unpack_match<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> { /// If `expr` is an (e).await, return the inner expression "e" that's being /// waited on. Otherwise return None. -fn unpack_await<'a>(expr: &'a hir::Expr<'a>) -> &hir::Expr<'a> { +fn unpack_await<'a>(expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> { if let ExprKind::Match(expr, _, hir::MatchSource::AwaitDesugar) = expr.kind { if let ExprKind::Call(func, [ref arg_0, ..]) = expr.kind { if matches!( diff --git a/src/tools/clippy/clippy_lints/src/unused_unit.rs b/src/tools/clippy/clippy_lints/src/unused_unit.rs index b70aa768b46..65f431d338b 100644 --- a/src/tools/clippy/clippy_lints/src/unused_unit.rs +++ b/src/tools/clippy/clippy_lints/src/unused_unit.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::{position_before_rarrow, snippet_opt}; +use clippy_utils::source::{position_before_rarrow, SpanRangeExt}; use rustc_ast::visit::FnKind; use rustc_ast::{ast, ClosureBinder}; use rustc_errors::Applicability; @@ -128,15 +128,17 @@ fn is_unit_expr(expr: &ast::Expr) -> bool { fn lint_unneeded_unit_return(cx: &EarlyContext<'_>, ty: &ast::Ty, span: Span) { let (ret_span, appl) = - snippet_opt(cx, span.with_hi(ty.span.hi())).map_or((ty.span, Applicability::MaybeIncorrect), |fn_source| { - position_before_rarrow(&fn_source).map_or((ty.span, Applicability::MaybeIncorrect), |rpos| { - ( - #[expect(clippy::cast_possible_truncation)] - ty.span.with_lo(BytePos(span.lo().0 + rpos as u32)), - Applicability::MachineApplicable, - ) - }) - }); + span.with_hi(ty.span.hi()) + .get_source_text(cx) + .map_or((ty.span, Applicability::MaybeIncorrect), |src| { + position_before_rarrow(&src).map_or((ty.span, Applicability::MaybeIncorrect), |rpos| { + ( + #[expect(clippy::cast_possible_truncation)] + ty.span.with_lo(BytePos(span.lo().0 + rpos as u32)), + Applicability::MachineApplicable, + ) + }) + }); span_lint_and_sugg( cx, UNUSED_UNIT, diff --git a/src/tools/clippy/clippy_lints/src/unwrap.rs b/src/tools/clippy/clippy_lints/src/unwrap.rs index c0d9bcdd259..0b4ea0752b6 100644 --- a/src/tools/clippy/clippy_lints/src/unwrap.rs +++ b/src/tools/clippy/clippy_lints/src/unwrap.rs @@ -89,15 +89,15 @@ enum UnwrappableKind { impl UnwrappableKind { fn success_variant_pattern(self) -> &'static str { match self { - UnwrappableKind::Option => "Some(..)", - UnwrappableKind::Result => "Ok(..)", + UnwrappableKind::Option => "Some()", + UnwrappableKind::Result => "Ok()", } } fn error_variant_pattern(self) -> &'static str { match self { UnwrappableKind::Option => "None", - UnwrappableKind::Result => "Err(..)", + UnwrappableKind::Result => "Err()", } } } diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs index 93785b45c27..5da48f4f7fb 100644 --- a/src/tools/clippy/clippy_lints/src/use_self.rs +++ b/src/tools/clippy/clippy_lints/src/use_self.rs @@ -229,7 +229,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { && let impl_ty = cx.tcx.type_of(impl_id).instantiate_identity() && same_type_and_consts(ty, impl_ty) // Ensure the type we encounter and the one from the impl have the same lifetime parameters. It may be that - // the lifetime parameters of `ty` are ellided (`impl<'a> Foo<'a> { fn new() -> Self { Foo{..} } }`, in + // the lifetime parameters of `ty` are elided (`impl<'a> Foo<'a> { fn new() -> Self { Foo{..} } }`, in // which case we must still trigger the lint. && (has_no_lifetime(ty) || same_lifetimes(ty, impl_ty)) { diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index 316c1f32d3a..0cce45290cf 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -1,6 +1,3 @@ -//! A group of attributes that can be attached to Rust code in order -//! to generate a clippy lint detecting said code automatically. - use clippy_utils::{get_attr, higher}; use rustc_ast::ast::{LitFloatType, LitKind}; use rustc_ast::LitIntType; diff --git a/src/tools/clippy/clippy_lints/src/utils/format_args_collector.rs b/src/tools/clippy/clippy_lints/src/utils/format_args_collector.rs index 5acfd35fd6a..f50ce6c99de 100644 --- a/src/tools/clippy/clippy_lints/src/utils/format_args_collector.rs +++ b/src/tools/clippy/clippy_lints/src/utils/format_args_collector.rs @@ -1,5 +1,5 @@ use clippy_utils::macros::FormatArgsStorage; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use itertools::Itertools; use rustc_ast::{Crate, Expr, ExprKind, FormatArgs}; use rustc_data_structures::fx::FxHashMap; @@ -75,38 +75,21 @@ fn has_span_from_proc_macro(cx: &EarlyContext<'_>, args: &FormatArgs) -> bool { // `format!("{} {} {c}", "one", "two", c = "three")` // ^^ ^^ ^^^^^^ - let between_spans = once(args.span) + !once(args.span) .chain(argument_span) .tuple_windows() - .map(|(start, end)| start.between(end)); - - for between_span in between_spans { - let mut seen_comma = false; - - let Some(snippet) = snippet_opt(cx, between_span) else { - return true; - }; - for token in tokenize(&snippet) { - match token.kind { - TokenKind::LineComment { .. } | TokenKind::BlockComment { .. } | TokenKind::Whitespace => {}, - TokenKind::Comma if !seen_comma => seen_comma = true, - // named arguments, `start_val, name = end_val` - // ^^^^^^^^^ between_span - TokenKind::Ident | TokenKind::Eq if seen_comma => {}, - // An unexpected token usually indicates that we crossed a macro boundary - // - // `println!(some_proc_macro!("input {}"), a)` - // ^^^ between_span - // `println!("{}", val!(x))` - // ^^^^^^^ between_span - _ => return true, - } - } - - if !seen_comma { - return true; - } - } - - false + .map(|(start, end)| start.between(end)) + .all(|sp| { + sp.check_source_text(cx, |src| { + // text should be either `, name` or `, name =` + let mut iter = tokenize(src).filter(|t| { + !matches!( + t.kind, + TokenKind::LineComment { .. } | TokenKind::BlockComment { .. } | TokenKind::Whitespace + ) + }); + iter.next().is_some_and(|t| matches!(t.kind, TokenKind::Comma)) + && iter.all(|t| matches!(t.kind, TokenKind::Ident | TokenKind::Eq)) + }) + }) } diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs index 1d294c2944b..f662c7651f6 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs @@ -3,7 +3,6 @@ pub mod collapsible_calls; pub mod interning_defined_symbol; pub mod invalid_paths; pub mod lint_without_lint_pass; -pub mod metadata_collector; pub mod msrv_attr_impl; pub mod outer_expn_data_pass; pub mod produce_ice; diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs index df342e48d63..20526113d69 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs @@ -9,7 +9,6 @@ use rustc_hir::intravisit::Visitor; use rustc_hir::{ExprKind, HirId, Item, MutTy, Mutability, Path, TyKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; -use rustc_semver::RustcVersion; use rustc_session::impl_lint_pass; use rustc_span::source_map::Spanned; use rustc_span::symbol::Symbol; @@ -92,7 +91,12 @@ pub struct LintWithoutLintPass { registered_lints: FxHashSet, } -impl_lint_pass!(LintWithoutLintPass => [DEFAULT_LINT, LINT_WITHOUT_LINT_PASS, INVALID_CLIPPY_VERSION_ATTRIBUTE, MISSING_CLIPPY_VERSION_ATTRIBUTE]); +impl_lint_pass!(LintWithoutLintPass => [ + DEFAULT_LINT, + LINT_WITHOUT_LINT_PASS, + INVALID_CLIPPY_VERSION_ATTRIBUTE, + MISSING_CLIPPY_VERSION_ATTRIBUTE, +]); impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { @@ -220,7 +224,7 @@ fn check_invalid_clippy_version_attribute(cx: &LateContext<'_>, item: &'_ Item<' return; } - if RustcVersion::parse(value.as_str()).is_err() { + if rustc_attr::parse_version(value).is_none() { span_lint_and_help( cx, INVALID_CLIPPY_VERSION_ATTRIBUTE, diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs deleted file mode 100644 index 57f45aa3e48..00000000000 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs +++ /dev/null @@ -1,1078 +0,0 @@ -//! This lint is used to collect metadata about clippy lints. This metadata is exported as a json -//! file and then used to generate the [clippy lint list](https://rust-lang.github.io/rust-clippy/master/index.html) -//! -//! This module and therefore the entire lint is guarded by a feature flag called `internal` -//! -//! The module transforms all lint names to ascii lowercase to ensure that we don't have mismatches -//! during any comparison or mapping. (Please take care of this, it's not fun to spend time on such -//! a simple mistake) - -use crate::utils::internal_lints::lint_without_lint_pass::{extract_clippy_version_value, is_lint_ref_type}; -use clippy_config::{get_configuration_metadata, ClippyConfiguration}; - -use clippy_utils::diagnostics::span_lint; -use clippy_utils::ty::{match_type, walk_ptrs_ty_depth}; -use clippy_utils::{last_path_segment, match_function_call, match_path, paths}; -use itertools::Itertools; -use rustc_ast as ast; -use rustc_data_structures::fx::FxHashMap; -use rustc_hir::def::DefKind; -use rustc_hir::intravisit::Visitor; -use rustc_hir::{self as hir, intravisit, Closure, ExprKind, Item, ItemKind, Mutability, QPath}; -use rustc_lint::{unerased_lint_store, CheckLintNameResult, LateContext, LateLintPass, LintContext, LintId}; -use rustc_middle::hir::nested_filter; -use rustc_session::impl_lint_pass; -use rustc_span::symbol::Ident; -use rustc_span::{sym, Loc, Span, Symbol}; -use serde::ser::SerializeStruct; -use serde::{Serialize, Serializer}; -use std::collections::{BTreeSet, BinaryHeap}; -use std::fmt::Write as _; -use std::fs::{self, File}; -use std::io::prelude::*; -use std::path::{Path, PathBuf}; -use std::process::Command; -use std::{env, fmt}; - -/// This is the json output file of the lint collector. -const JSON_OUTPUT_FILE: &str = "../util/gh-pages/lints.json"; -/// This is the markdown output file of the lint collector. -const MARKDOWN_OUTPUT_FILE: &str = "../book/src/lint_configuration.md"; -/// These groups will be ignored by the lint group matcher. This is useful for collections like -/// `clippy::all` -const IGNORED_LINT_GROUPS: [&str; 1] = ["clippy::all"]; -/// Lints within this group will be excluded from the collection. These groups -/// have to be defined without the `clippy::` prefix. -const EXCLUDED_LINT_GROUPS: [&str; 1] = ["internal"]; -/// Collected deprecated lint will be assigned to this group in the JSON output -const DEPRECATED_LINT_GROUP_STR: &str = "deprecated"; -/// This is the lint level for deprecated lints that will be displayed in the lint list -const DEPRECATED_LINT_LEVEL: &str = "none"; -/// This array holds Clippy's lint groups with their corresponding default lint level. The -/// lint level for deprecated lints is set in `DEPRECATED_LINT_LEVEL`. -const DEFAULT_LINT_LEVELS: &[(&str, &str)] = &[ - ("correctness", "deny"), - ("suspicious", "warn"), - ("restriction", "allow"), - ("style", "warn"), - ("pedantic", "allow"), - ("complexity", "warn"), - ("perf", "warn"), - ("cargo", "allow"), - ("nursery", "allow"), -]; -/// This prefix is in front of the lint groups in the lint store. The prefix will be trimmed -/// to only keep the actual lint group in the output. -const CLIPPY_LINT_GROUP_PREFIX: &str = "clippy::"; -const LINT_EMISSION_FUNCTIONS: [&[&str]; 7] = [ - &["clippy_utils", "diagnostics", "span_lint"], - &["clippy_utils", "diagnostics", "span_lint_and_help"], - &["clippy_utils", "diagnostics", "span_lint_and_note"], - &["clippy_utils", "diagnostics", "span_lint_hir"], - &["clippy_utils", "diagnostics", "span_lint_and_sugg"], - &["clippy_utils", "diagnostics", "span_lint_and_then"], - &["clippy_utils", "diagnostics", "span_lint_hir_and_then"], -]; -const SUGGESTION_DIAG_METHODS: [(&str, bool); 9] = [ - ("span_suggestion", false), - ("span_suggestion_short", false), - ("span_suggestion_verbose", false), - ("span_suggestion_hidden", false), - ("tool_only_span_suggestion", false), - ("multipart_suggestion", true), - ("multipart_suggestions", true), - ("tool_only_multipart_suggestion", true), - ("span_suggestions", true), -]; - -/// The index of the applicability name of `paths::APPLICABILITY_VALUES` -const APPLICABILITY_NAME_INDEX: usize = 2; -/// This applicability will be set for unresolved applicability values. -const APPLICABILITY_UNRESOLVED_STR: &str = "Unresolved"; -/// The version that will be displayed if none has been defined -const VERSION_DEFAULT_STR: &str = "Unknown"; - -const CHANGELOG_PATH: &str = "../CHANGELOG.md"; - -declare_clippy_lint! { - /// ### What it does - /// Collects metadata about clippy lints for the website. - /// - /// This lint will be used to report problems of syntax parsing. You should hopefully never - /// see this but never say never I guess ^^ - /// - /// ### Why is this bad? - /// This is not a bad thing but definitely a hacky way to do it. See - /// issue [#4310](https://github.com/rust-lang/rust-clippy/issues/4310) for a discussion - /// about the implementation. - /// - /// ### Known problems - /// Hopefully none. It would be pretty uncool to have a problem here :) - /// - /// ### Example output - /// ```json,ignore - /// { - /// "id": "metadata_collector", - /// "id_span": { - /// "path": "clippy_lints/src/utils/internal_lints/metadata_collector.rs", - /// "line": 1 - /// }, - /// "group": "clippy::internal", - /// "docs": " ### What it does\nCollects metadata about clippy lints for the website. [...] " - /// } - /// ``` - #[clippy::version = "1.56.0"] - pub METADATA_COLLECTOR, - internal, - "A busy bee collection metadata about lints" -} - -impl_lint_pass!(MetadataCollector => [METADATA_COLLECTOR]); - -#[allow(clippy::module_name_repetitions)] -#[derive(Debug, Clone)] -pub struct MetadataCollector { - /// All collected lints - /// - /// We use a Heap here to have the lints added in alphabetic order in the export - lints: BinaryHeap, - applicability_info: FxHashMap, - config: Vec, - clippy_project_root: PathBuf, -} - -impl MetadataCollector { - pub fn new() -> Self { - Self { - lints: BinaryHeap::::default(), - applicability_info: FxHashMap::::default(), - config: get_configuration_metadata(), - clippy_project_root: env::current_dir() - .expect("failed to get current dir") - .ancestors() - .nth(1) - .expect("failed to get project root") - .to_path_buf(), - } - } - - fn get_lint_configs(&self, lint_name: &str) -> Option { - self.config - .iter() - .filter(|config| config.lints.iter().any(|&lint| lint == lint_name)) - .map(ToString::to_string) - .reduce(|acc, x| acc + "\n\n" + &x) - .map(|configurations| { - format!( - r#" -### Configuration -This lint has the following configuration variables: - -{configurations} -"# - ) - }) - } - - fn configs_to_markdown(&self, map_fn: fn(&ClippyConfiguration) -> String) -> String { - self.config - .iter() - .filter(|config| config.deprecation_reason.is_none()) - .filter(|config| !config.lints.is_empty()) - .map(map_fn) - .join("\n") - } - - fn get_markdown_docs(&self) -> String { - format!( - r#"# Lint Configuration Options - -The following list shows each configuration option, along with a description, its default value, an example -and lints affected. - ---- - -{}"#, - self.configs_to_markdown(ClippyConfiguration::to_markdown_paragraph), - ) - } -} - -impl Drop for MetadataCollector { - /// You might ask: How hacky is this? - /// My answer: YES - fn drop(&mut self) { - // The metadata collector gets dropped twice, this makes sure that we only write - // when the list is full - if self.lints.is_empty() { - return; - } - - let mut applicability_info = std::mem::take(&mut self.applicability_info); - - // Add deprecated lints - self.lints.extend( - crate::deprecated_lints::DEPRECATED - .iter() - .zip(crate::deprecated_lints::DEPRECATED_VERSION) - .filter_map(|((lint, reason), version)| LintMetadata::new_deprecated(lint, reason, version)), - ); - // Mapping the final data - let mut lints = std::mem::take(&mut self.lints).into_sorted_vec(); - for x in &mut lints { - x.applicability = Some(applicability_info.remove(&x.id).unwrap_or_default()); - replace_produces(&x.id, &mut x.docs, &self.clippy_project_root); - } - - collect_renames(&mut lints); - - // Outputting json - fs::write(JSON_OUTPUT_FILE, serde_json::to_string_pretty(&lints).unwrap()).unwrap(); - - // Outputting markdown - let mut file = File::create(MARKDOWN_OUTPUT_FILE).unwrap(); - writeln!( - file, - " - -{}", - self.get_markdown_docs(), - ) - .unwrap(); - - // Write configuration links to CHANGELOG.md - let changelog = fs::read_to_string(CHANGELOG_PATH).unwrap(); - let mut changelog_file = File::create(CHANGELOG_PATH).unwrap(); - let position = changelog - .find("") - .unwrap(); - writeln!( - changelog_file, - "{}\n{}\n", - &changelog[..position], - self.configs_to_markdown(ClippyConfiguration::to_markdown_link) - ) - .unwrap(); - } -} - -#[derive(Debug, Clone, Serialize, PartialEq, Eq, PartialOrd, Ord)] -struct LintMetadata { - id: String, - id_span: Option, - group: String, - level: String, - docs: String, - version: String, - /// This field is only used in the output and will only be - /// mapped shortly before the actual output. - applicability: Option, - /// All the past names of lints which have been renamed. - #[serde(skip_serializing_if = "BTreeSet::is_empty")] - former_ids: BTreeSet, -} - -impl LintMetadata { - fn new( - id: String, - id_span: SerializableSpan, - group: String, - level: &'static str, - version: String, - docs: String, - ) -> Self { - Self { - id, - id_span: Some(id_span), - group, - level: level.to_string(), - version, - docs, - applicability: None, - former_ids: BTreeSet::new(), - } - } - - fn new_deprecated(name: &str, reason: &str, version: &str) -> Option { - // The reason starts with a lowercase letter and end without a period. - // This needs to be fixed for the website. - let mut reason = reason.to_owned(); - if let Some(reason) = reason.get_mut(0..1) { - reason.make_ascii_uppercase(); - } - name.strip_prefix("clippy::").map(|name| Self { - id: name.into(), - id_span: None, - group: DEPRECATED_LINT_GROUP_STR.into(), - level: DEPRECATED_LINT_LEVEL.into(), - version: version.into(), - docs: format!( - "### What it does\n\n\ - Nothing. This lint has been deprecated\n\n\ - ### Deprecation reason\n\n{reason}.\n", - ), - applicability: None, - former_ids: BTreeSet::new(), - }) - } -} - -fn replace_produces(lint_name: &str, docs: &mut String, clippy_project_root: &Path) { - let mut doc_lines = docs.lines().map(ToString::to_string).collect::>(); - let mut lines = doc_lines.iter_mut(); - - 'outer: loop { - // Find the start of the example - - // ```rust - loop { - match lines.next() { - Some(line) if line.trim_start().starts_with("```rust") => { - if line.contains("ignore") || line.contains("no_run") { - // A {{produces}} marker may have been put on a ignored code block by mistake, - // just seek to the end of the code block and continue checking. - if lines.any(|line| line.trim_start().starts_with("```")) { - continue; - } - - panic!("lint `{lint_name}` has an unterminated code block") - } - - break; - }, - Some(line) if line.trim_start() == "{{produces}}" => { - panic!("lint `{lint_name}` has marker {{{{produces}}}} with an ignored or missing code block") - }, - Some(line) => { - let line = line.trim(); - // These are the two most common markers of the corrections section - if line.eq_ignore_ascii_case("Use instead:") || line.eq_ignore_ascii_case("Could be written as:") { - break 'outer; - } - }, - None => break 'outer, - } - } - - // Collect the example - let mut example = Vec::new(); - loop { - match lines.next() { - Some(line) if line.trim_start() == "```" => break, - Some(line) => example.push(line), - None => panic!("lint `{lint_name}` has an unterminated code block"), - } - } - - // Find the {{produces}} and attempt to generate the output - loop { - match lines.next() { - Some(line) if line.is_empty() => {}, - Some(line) if line.trim() == "{{produces}}" => { - let output = get_lint_output(lint_name, &example, clippy_project_root); - line.replace_range( - .., - &format!( - "
    \ - Produces\n\ - \n\ - ```text\n\ - {output}\n\ - ```\n\ -
    " - ), - ); - - break; - }, - // No {{produces}}, we can move on to the next example - Some(_) => break, - None => break 'outer, - } - } - } - - *docs = cleanup_docs(&doc_lines); -} - -fn get_lint_output(lint_name: &str, example: &[&mut String], clippy_project_root: &Path) -> String { - let dir = tempfile::tempdir().unwrap_or_else(|e| panic!("failed to create temp dir: {e}")); - let file = dir.path().join("lint_example.rs"); - - let mut source = String::new(); - let unhidden = example - .iter() - .map(|line| line.trim_start().strip_prefix("# ").unwrap_or(line)); - - // Get any attributes - let mut lines = unhidden.peekable(); - while let Some(line) = lines.peek() { - if line.starts_with("#!") { - source.push_str(line); - source.push('\n'); - lines.next(); - } else { - break; - } - } - - let needs_main = !example.iter().any(|line| line.contains("fn main")); - if needs_main { - source.push_str("fn main() {\n"); - } - - for line in lines { - source.push_str(line); - source.push('\n'); - } - - if needs_main { - source.push_str("}\n"); - } - - if let Err(e) = fs::write(&file, &source) { - panic!("failed to write to `{}`: {e}", file.as_path().to_string_lossy()); - } - - let prefixed_name = format!("{CLIPPY_LINT_GROUP_PREFIX}{lint_name}"); - - let mut cmd = Command::new(env::var("CARGO").unwrap_or("cargo".into())); - - cmd.current_dir(clippy_project_root) - .env("CARGO_INCREMENTAL", "0") - .env("CLIPPY_ARGS", "") - .env("CLIPPY_DISABLE_DOCS_LINKS", "1") - // We need to disable this to enable all lints - .env("ENABLE_METADATA_COLLECTION", "0") - .args(["run", "--bin", "clippy-driver"]) - .args(["--target-dir", "./clippy_lints/target"]) - .args(["--", "--error-format=json"]) - .args(["--edition", "2021"]) - .arg("-Cdebuginfo=0") - .args(["-A", "clippy::all"]) - .args(["-W", &prefixed_name]) - .args(["-L", "./target/debug"]) - .args(["-Z", "no-codegen"]); - - let output = cmd - .arg(file.as_path()) - .output() - .unwrap_or_else(|e| panic!("failed to run `{cmd:?}`: {e}")); - - let tmp_file_path = file.to_string_lossy(); - let stderr = std::str::from_utf8(&output.stderr).unwrap(); - let msgs = stderr - .lines() - .filter(|line| line.starts_with('{')) - .map(|line| serde_json::from_str(line).unwrap()) - .collect::>(); - - let mut rendered = String::new(); - let iter = msgs - .iter() - .filter(|msg| matches!(&msg["code"]["code"], serde_json::Value::String(s) if s == &prefixed_name)); - - for message in iter { - let rendered_part = message["rendered"].as_str().expect("rendered field should exist"); - rendered.push_str(rendered_part); - } - - if rendered.is_empty() { - let rendered: Vec<&str> = msgs.iter().filter_map(|msg| msg["rendered"].as_str()).collect(); - let non_json: Vec<&str> = stderr.lines().filter(|line| !line.starts_with('{')).collect(); - panic!( - "did not find lint `{lint_name}` in output of example, got:\n{}\n{}", - non_json.join("\n"), - rendered.join("\n") - ); - } - - // The reader doesn't need to see `/tmp/.tmpfiy2Qd/lint_example.rs` :) - rendered.trim_end().replace(&*tmp_file_path, "lint_example.rs") -} - -#[derive(Debug, Clone, Serialize, PartialEq, Eq, PartialOrd, Ord)] -struct SerializableSpan { - path: String, - line: usize, -} - -impl fmt::Display for SerializableSpan { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}:{}", self.path.rsplit('/').next().unwrap_or_default(), self.line) - } -} - -impl SerializableSpan { - fn from_item(cx: &LateContext<'_>, item: &Item<'_>) -> Self { - Self::from_span(cx, item.ident.span) - } - - fn from_span(cx: &LateContext<'_>, span: Span) -> Self { - let loc: Loc = cx.sess().source_map().lookup_char_pos(span.lo()); - - Self { - path: format!("{}", loc.file.name.prefer_remapped_unconditionaly()), - line: loc.line, - } - } -} - -#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord)] -struct ApplicabilityInfo { - /// Indicates if any of the lint emissions uses multiple spans. This is related to - /// [rustfix#141](https://github.com/rust-lang/rustfix/issues/141) as such suggestions can - /// currently not be applied automatically. - is_multi_part_suggestion: bool, - applicability: Option, -} - -impl Serialize for ApplicabilityInfo { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - let mut s = serializer.serialize_struct("ApplicabilityInfo", 2)?; - s.serialize_field("is_multi_part_suggestion", &self.is_multi_part_suggestion)?; - if let Some(index) = self.applicability { - s.serialize_field( - "applicability", - &paths::APPLICABILITY_VALUES[index][APPLICABILITY_NAME_INDEX], - )?; - } else { - s.serialize_field("applicability", APPLICABILITY_UNRESOLVED_STR)?; - } - s.end() - } -} - -// ================================================================== -// Lint pass -// ================================================================== -impl<'hir> LateLintPass<'hir> for MetadataCollector { - /// Collecting lint declarations like: - /// ```rust, ignore - /// declare_clippy_lint! { - /// /// ### What it does - /// /// Something IDK. - /// pub SOME_LINT, - /// internal, - /// "Who am I?" - /// } - /// ``` - fn check_item(&mut self, cx: &LateContext<'hir>, item: &'hir Item<'_>) { - if let ItemKind::Static(ty, Mutability::Not, _) = item.kind { - // Normal lint - if is_lint_ref_type(cx, ty) - // item validation - // disallow check - && let lint_name = sym_to_string(item.ident.name).to_ascii_lowercase() - // metadata extraction - && let Some((group, level)) = get_lint_group_and_level_or_lint(cx, &lint_name, item) - && let Some(mut raw_docs) = extract_attr_docs_or_lint(cx, item) - { - if let Some(configuration_section) = self.get_lint_configs(&lint_name) { - raw_docs.push_str(&configuration_section); - } - let version = get_lint_version(cx, item); - - self.lints.push(LintMetadata::new( - lint_name, - SerializableSpan::from_item(cx, item), - group, - level, - version, - raw_docs, - )); - } - } - } - - /// Collecting constant applicability from the actual lint emissions - /// - /// Example: - /// ```rust, ignore - /// span_lint_and_sugg( - /// cx, - /// SOME_LINT, - /// item.span, - /// "Le lint message", - /// "Here comes help:", - /// "#![allow(clippy::all)]", - /// Applicability::MachineApplicable, // <-- Extracts this constant value - /// ); - /// ``` - fn check_expr(&mut self, cx: &LateContext<'hir>, expr: &'hir hir::Expr<'_>) { - if let Some(args) = match_lint_emission(cx, expr) { - let emission_info = extract_emission_info(cx, args); - if emission_info.is_empty() { - // See: - // - src/misc.rs:734:9 - // - src/methods/mod.rs:3545:13 - // - src/methods/mod.rs:3496:13 - // We are basically unable to resolve the lint name itself. - return; - } - - for (lint_name, applicability, is_multi_part) in emission_info { - let app_info = self.applicability_info.entry(lint_name).or_default(); - app_info.applicability = applicability; - app_info.is_multi_part_suggestion = is_multi_part; - } - } - } -} - -// ================================================================== -// Lint definition extraction -// ================================================================== -fn sym_to_string(sym: Symbol) -> String { - sym.as_str().to_string() -} - -fn extract_attr_docs_or_lint(cx: &LateContext<'_>, item: &Item<'_>) -> Option { - extract_attr_docs(cx, item).or_else(|| { - lint_collection_error_item(cx, item, "could not collect the lint documentation"); - None - }) -} - -/// This function collects all documentation that has been added to an item using -/// `#[doc = r""]` attributes. Several attributes are aggravated using line breaks -/// -/// ```ignore -/// #[doc = r"Hello world!"] -/// #[doc = r"=^.^="] -/// struct SomeItem {} -/// ``` -/// -/// Would result in `Hello world!\n=^.^=\n` -fn extract_attr_docs(cx: &LateContext<'_>, item: &Item<'_>) -> Option { - let attrs = cx.tcx.hir().attrs(item.hir_id()); - let mut lines = attrs.iter().filter_map(ast::Attribute::doc_str); - - if let Some(line) = lines.next() { - let raw_docs = lines.fold(String::from(line.as_str()) + "\n", |s, line| s + line.as_str() + "\n"); - return Some(raw_docs); - } - - None -} - -/// This function may modify the doc comment to ensure that the string can be displayed using a -/// markdown viewer in Clippy's lint list. The following modifications could be applied: -/// * Removal of leading space after a new line. (Important to display tables) -/// * Ensures that code blocks only contain language information -fn cleanup_docs(docs_collection: &Vec) -> String { - let mut in_code_block = false; - let mut is_code_block_rust = false; - - let mut docs = String::new(); - for line in docs_collection { - // Rustdoc hides code lines starting with `# ` and this removes them from Clippy's lint list :) - if is_code_block_rust && line.trim_start().starts_with("# ") { - continue; - } - - // The line should be represented in the lint list, even if it's just an empty line - docs.push('\n'); - if let Some(info) = line.trim_start().strip_prefix("```") { - in_code_block = !in_code_block; - is_code_block_rust = false; - if in_code_block { - let lang = info - .trim() - .split(',') - // remove rustdoc directives - .find(|&s| !matches!(s, "" | "ignore" | "no_run" | "should_panic")) - // if no language is present, fill in "rust" - .unwrap_or("rust"); - let len_diff = line.len() - line.trim_start().len(); - if len_diff != 0 { - // We put back the indentation. - docs.push_str(&line[..len_diff]); - } - docs.push_str("```"); - docs.push_str(lang); - - is_code_block_rust = lang == "rust"; - continue; - } - } - // This removes the leading space that the macro translation introduces - if let Some(stripped_doc) = line.strip_prefix(' ') { - docs.push_str(stripped_doc); - } else if !line.is_empty() { - docs.push_str(line); - } - } - - docs -} - -fn get_lint_version(cx: &LateContext<'_>, item: &Item<'_>) -> String { - extract_clippy_version_value(cx, item).map_or_else( - || VERSION_DEFAULT_STR.to_string(), - |version| version.as_str().to_string(), - ) -} - -fn get_lint_group_and_level_or_lint( - cx: &LateContext<'_>, - lint_name: &str, - item: &Item<'_>, -) -> Option<(String, &'static str)> { - let result = unerased_lint_store(cx.tcx.sess).check_lint_name( - lint_name, - Some(sym::clippy), - &std::iter::once(Ident::with_dummy_span(sym::clippy)).collect(), - ); - if let CheckLintNameResult::Tool(lint_lst, None) = result { - if let Some(group) = get_lint_group(cx, lint_lst[0]) { - if EXCLUDED_LINT_GROUPS.contains(&group.as_str()) { - return None; - } - - if let Some(level) = get_lint_level_from_group(&group) { - Some((group, level)) - } else { - lint_collection_error_item( - cx, - item, - &format!("Unable to determine lint level for found group `{group}`"), - ); - None - } - } else { - lint_collection_error_item(cx, item, "Unable to determine lint group"); - None - } - } else { - lint_collection_error_item(cx, item, "Unable to find lint in lint_store"); - None - } -} - -fn get_lint_group(cx: &LateContext<'_>, lint_id: LintId) -> Option { - for (group_name, lints, _) in unerased_lint_store(cx.tcx.sess).get_lint_groups() { - if IGNORED_LINT_GROUPS.contains(&group_name) { - continue; - } - - if lints.iter().any(|group_lint| *group_lint == lint_id) { - let group = group_name.strip_prefix(CLIPPY_LINT_GROUP_PREFIX).unwrap_or(group_name); - return Some((*group).to_string()); - } - } - - None -} - -fn get_lint_level_from_group(lint_group: &str) -> Option<&'static str> { - DEFAULT_LINT_LEVELS - .iter() - .find_map(|(group_name, group_level)| (*group_name == lint_group).then_some(*group_level)) -} - -fn collect_renames(lints: &mut Vec) { - for lint in lints { - let mut collected = String::new(); - let mut names = vec![lint.id.clone()]; - - loop { - if let Some(lint_name) = names.pop() { - for (k, v) in crate::deprecated_lints::RENAMED { - if let Some(name) = v.strip_prefix(CLIPPY_LINT_GROUP_PREFIX) - && name == lint_name - && let Some(past_name) = k.strip_prefix(CLIPPY_LINT_GROUP_PREFIX) - { - lint.former_ids.insert(past_name.to_owned()); - writeln!(collected, "* `{past_name}`").unwrap(); - names.push(past_name.to_string()); - } - } - - continue; - } - - break; - } - - if !collected.is_empty() { - write!( - &mut lint.docs, - r#" -### Past names - -{collected} -"# - ) - .unwrap(); - } - } -} - -// ================================================================== -// Lint emission -// ================================================================== -fn lint_collection_error_item(cx: &LateContext<'_>, item: &Item<'_>, message: &str) { - span_lint( - cx, - METADATA_COLLECTOR, - item.ident.span, - format!("metadata collection error for `{}`: {message}", item.ident.name), - ); -} - -// ================================================================== -// Applicability -// ================================================================== -/// This function checks if a given expression is equal to a simple lint emission function call. -/// It will return the function arguments if the emission matched any function. -fn match_lint_emission<'hir>(cx: &LateContext<'hir>, expr: &'hir hir::Expr<'_>) -> Option<&'hir [hir::Expr<'hir>]> { - LINT_EMISSION_FUNCTIONS - .iter() - .find_map(|emission_fn| match_function_call(cx, expr, emission_fn)) -} - -fn take_higher_applicability(a: Option, b: Option) -> Option { - a.map_or(b, |a| a.max(b.unwrap_or_default()).into()) -} - -fn extract_emission_info<'hir>( - cx: &LateContext<'hir>, - args: &'hir [hir::Expr<'hir>], -) -> Vec<(String, Option, bool)> { - let mut lints = Vec::new(); - let mut applicability = None; - let mut multi_part = false; - - for arg in args { - let (arg_ty, _) = walk_ptrs_ty_depth(cx.typeck_results().expr_ty(arg)); - - if match_type(cx, arg_ty, &paths::LINT) { - // If we found the lint arg, extract the lint name - let mut resolved_lints = resolve_lints(cx, arg); - lints.append(&mut resolved_lints); - } else if match_type(cx, arg_ty, &paths::APPLICABILITY) { - applicability = resolve_applicability(cx, arg); - } else if arg_ty.is_closure() { - multi_part |= check_is_multi_part(cx, arg); - applicability = applicability.or_else(|| resolve_applicability(cx, arg)); - } - } - - lints - .into_iter() - .map(|lint_name| (lint_name, applicability, multi_part)) - .collect() -} - -/// Resolves the possible lints that this expression could reference -fn resolve_lints<'hir>(cx: &LateContext<'hir>, expr: &'hir hir::Expr<'hir>) -> Vec { - let mut resolver = LintResolver::new(cx); - resolver.visit_expr(expr); - resolver.lints -} - -/// This function tries to resolve the linked applicability to the given expression. -fn resolve_applicability<'hir>(cx: &LateContext<'hir>, expr: &'hir hir::Expr<'hir>) -> Option { - let mut resolver = ApplicabilityResolver::new(cx); - resolver.visit_expr(expr); - resolver.complete() -} - -fn check_is_multi_part<'hir>(cx: &LateContext<'hir>, closure_expr: &'hir hir::Expr<'hir>) -> bool { - if let ExprKind::Closure(&Closure { body, .. }) = closure_expr.kind { - let mut scanner = IsMultiSpanScanner::new(cx); - intravisit::walk_body(&mut scanner, cx.tcx.hir().body(body)); - return scanner.is_multi_part(); - } else if let Some(local) = get_parent_local(cx, closure_expr) { - if let Some(local_init) = local.init { - return check_is_multi_part(cx, local_init); - } - } - - false -} - -struct LintResolver<'a, 'hir> { - cx: &'a LateContext<'hir>, - lints: Vec, -} - -impl<'a, 'hir> LintResolver<'a, 'hir> { - fn new(cx: &'a LateContext<'hir>) -> Self { - Self { - cx, - lints: Vec::::default(), - } - } -} - -impl<'a, 'hir> Visitor<'hir> for LintResolver<'a, 'hir> { - type NestedFilter = nested_filter::All; - - fn nested_visit_map(&mut self) -> Self::Map { - self.cx.tcx.hir() - } - - fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) { - if let ExprKind::Path(qpath) = &expr.kind - && let QPath::Resolved(_, path) = qpath - && let (expr_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(expr)) - && match_type(self.cx, expr_ty, &paths::LINT) - { - if let hir::def::Res::Def(DefKind::Static { .. }, _) = path.res { - let lint_name = last_path_segment(qpath).ident.name; - self.lints.push(sym_to_string(lint_name).to_ascii_lowercase()); - } else if let Some(local) = get_parent_local(self.cx, expr) { - if let Some(local_init) = local.init { - intravisit::walk_expr(self, local_init); - } - } - } - - intravisit::walk_expr(self, expr); - } -} - -/// This visitor finds the highest applicability value in the visited expressions -struct ApplicabilityResolver<'a, 'hir> { - cx: &'a LateContext<'hir>, - /// This is the index of highest `Applicability` for `paths::APPLICABILITY_VALUES` - applicability_index: Option, -} - -impl<'a, 'hir> ApplicabilityResolver<'a, 'hir> { - fn new(cx: &'a LateContext<'hir>) -> Self { - Self { - cx, - applicability_index: None, - } - } - - fn add_new_index(&mut self, new_index: usize) { - self.applicability_index = take_higher_applicability(self.applicability_index, Some(new_index)); - } - - fn complete(self) -> Option { - self.applicability_index - } -} - -impl<'a, 'hir> Visitor<'hir> for ApplicabilityResolver<'a, 'hir> { - type NestedFilter = nested_filter::All; - - fn nested_visit_map(&mut self) -> Self::Map { - self.cx.tcx.hir() - } - - fn visit_path(&mut self, path: &hir::Path<'hir>, _id: hir::HirId) { - for (index, enum_value) in paths::APPLICABILITY_VALUES.iter().enumerate() { - if match_path(path, enum_value) { - self.add_new_index(index); - return; - } - } - } - - fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) { - let (expr_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(expr)); - - if match_type(self.cx, expr_ty, &paths::APPLICABILITY) - && let Some(local) = get_parent_local(self.cx, expr) - && let Some(local_init) = local.init - { - intravisit::walk_expr(self, local_init); - }; - - intravisit::walk_expr(self, expr); - } -} - -/// This returns the parent local node if the expression is a reference one -fn get_parent_local<'hir>(cx: &LateContext<'hir>, expr: &'hir hir::Expr<'hir>) -> Option<&'hir hir::LetStmt<'hir>> { - if let ExprKind::Path(QPath::Resolved(_, path)) = expr.kind { - if let hir::def::Res::Local(local_hir) = path.res { - return get_parent_local_hir_id(cx, local_hir); - } - } - - None -} - -fn get_parent_local_hir_id<'hir>(cx: &LateContext<'hir>, hir_id: hir::HirId) -> Option<&'hir hir::LetStmt<'hir>> { - match cx.tcx.parent_hir_node(hir_id) { - hir::Node::LetStmt(local) => Some(local), - hir::Node::Pat(pattern) => get_parent_local_hir_id(cx, pattern.hir_id), - _ => None, - } -} - -/// This visitor finds the highest applicability value in the visited expressions -struct IsMultiSpanScanner<'a, 'hir> { - cx: &'a LateContext<'hir>, - suggestion_count: usize, -} - -impl<'a, 'hir> IsMultiSpanScanner<'a, 'hir> { - fn new(cx: &'a LateContext<'hir>) -> Self { - Self { - cx, - suggestion_count: 0, - } - } - - /// Add a new single expression suggestion to the counter - fn add_single_span_suggestion(&mut self) { - self.suggestion_count += 1; - } - - /// Signals that a suggestion with possible multiple spans was found - fn add_multi_part_suggestion(&mut self) { - self.suggestion_count += 2; - } - - /// Checks if the suggestions include multiple spans - fn is_multi_part(&self) -> bool { - self.suggestion_count > 1 - } -} - -impl<'a, 'hir> Visitor<'hir> for IsMultiSpanScanner<'a, 'hir> { - type NestedFilter = nested_filter::All; - - fn nested_visit_map(&mut self) -> Self::Map { - self.cx.tcx.hir() - } - - fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) { - // Early return if the lint is already multi span - if self.is_multi_part() { - return; - } - - if let ExprKind::MethodCall(path, recv, _, _arg_span) = &expr.kind { - let (self_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(recv)); - if match_type(self.cx, self_ty, &paths::DIAG) { - let called_method = path.ident.name.as_str().to_string(); - for (method_name, is_multi_part) in &SUGGESTION_DIAG_METHODS { - if *method_name == called_method { - if *is_multi_part { - self.add_multi_part_suggestion(); - } else { - self.add_single_span_suggestion(); - } - break; - } - } - } - } - - intravisit::walk_expr(self, expr); - } -} diff --git a/src/tools/clippy/clippy_lints/src/vec.rs b/src/tools/clippy/clippy_lints/src/vec.rs index 228db14d1b7..d3e49bff422 100644 --- a/src/tools/clippy/clippy_lints/src/vec.rs +++ b/src/tools/clippy/clippy_lints/src/vec.rs @@ -5,7 +5,7 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_config::Conf; use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_hir_and_then; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::is_copy; use clippy_utils::visitors::for_each_local_use_after_expr; use clippy_utils::{get_parent_expr, higher, is_in_test, is_trait_method}; @@ -214,9 +214,11 @@ impl SuggestedType { } fn snippet(self, cx: &LateContext<'_>, args_span: Option, len_span: Option) -> String { - let maybe_args = args_span.and_then(|sp| snippet_opt(cx, sp)).unwrap_or_default(); + let maybe_args = args_span + .and_then(|sp| sp.get_source_text(cx)) + .map_or(String::new(), |x| x.to_owned()); let maybe_len = len_span - .and_then(|sp| snippet_opt(cx, sp).map(|s| format!("; {s}"))) + .and_then(|sp| sp.get_source_text(cx).map(|s| format!("; {s}"))) .unwrap_or_default(); match self { diff --git a/src/tools/clippy/clippy_lints/src/visibility.rs b/src/tools/clippy/clippy_lints/src/visibility.rs index 63f3a5d7f83..7a85196ceca 100644 --- a/src/tools/clippy/clippy_lints/src/visibility.rs +++ b/src/tools/clippy/clippy_lints/src/visibility.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use rustc_ast::ast::{Item, VisibilityKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; @@ -82,9 +82,7 @@ impl EarlyLintPass for Visibility { if !in_external_macro(cx.sess(), item.span) && let VisibilityKind::Restricted { path, shorthand, .. } = &item.vis.kind { - if **path == kw::SelfLower - && let Some(false) = is_from_proc_macro(cx, item.vis.span) - { + if **path == kw::SelfLower && !is_from_proc_macro(cx, item.vis.span) { span_lint_and_then( cx, NEEDLESS_PUB_SELF, @@ -104,7 +102,7 @@ impl EarlyLintPass for Visibility { if (**path == kw::Super || **path == kw::SelfLower || **path == kw::Crate) && !*shorthand && let [.., last] = &*path.segments - && let Some(false) = is_from_proc_macro(cx, item.vis.span) + && !is_from_proc_macro(cx, item.vis.span) { #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")] span_lint_and_then( @@ -125,7 +123,7 @@ impl EarlyLintPass for Visibility { if *shorthand && let [.., last] = &*path.segments - && let Some(false) = is_from_proc_macro(cx, item.vis.span) + && !is_from_proc_macro(cx, item.vis.span) { #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")] span_lint_and_then( @@ -147,6 +145,6 @@ impl EarlyLintPass for Visibility { } } -fn is_from_proc_macro(cx: &EarlyContext<'_>, span: Span) -> Option { - snippet_opt(cx, span).map(|s| !s.starts_with("pub")) +fn is_from_proc_macro(cx: &EarlyContext<'_>, span: Span) -> bool { + !span.check_source_text(cx, |src| src.starts_with("pub")) } diff --git a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs index c4d64ee4609..7d9e58ad2f8 100644 --- a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs +++ b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs @@ -100,14 +100,14 @@ declare_clippy_lint! { pub struct WildcardImports { warn_on_all: bool, - allowed_segments: &'static FxHashSet, + allowed_segments: FxHashSet, } impl WildcardImports { pub fn new(conf: &'static Conf) -> Self { Self { warn_on_all: conf.warn_on_all_wildcard_imports, - allowed_segments: &conf.allowed_wildcard_imports, + allowed_segments: conf.allowed_wildcard_imports.iter().cloned().collect(), } } } @@ -181,7 +181,7 @@ impl WildcardImports { fn check_exceptions(&self, cx: &LateContext<'_>, item: &Item<'_>, segments: &[PathSegment<'_>]) -> bool { item.span.from_expansion() || is_prelude_import(segments) - || is_allowed_via_config(segments, self.allowed_segments) + || is_allowed_via_config(segments, &self.allowed_segments) || (is_super_only_import(segments) && is_in_test(cx.tcx, item.hir_id())) } } diff --git a/src/tools/clippy/clippy_lints/src/write.rs b/src/tools/clippy/clippy_lints/src/write.rs index 54e7e92f0c4..ec5a5896fb2 100644 --- a/src/tools/clippy/clippy_lints/src/write.rs +++ b/src/tools/clippy/clippy_lints/src/write.rs @@ -2,7 +2,7 @@ use clippy_config::Conf; use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; use clippy_utils::is_in_test; use clippy_utils::macros::{format_arg_removal_span, root_macro_call_first_node, FormatArgsStorage, MacroCall}; -use clippy_utils::source::{expand_past_previous_comma, snippet_opt}; +use clippy_utils::source::{expand_past_previous_comma, SpanRangeExt}; use rustc_ast::token::LitKind; use rustc_ast::{ FormatArgPosition, FormatArgPositionKind, FormatArgs, FormatArgsPiece, FormatOptions, FormatPlaceholder, @@ -397,7 +397,7 @@ fn check_newline(cx: &LateContext<'_>, format_args: &FormatArgs, macro_call: &Ma format!("using `{name}!()` with a format string that ends in a single newline"), |diag| { let name_span = cx.sess().source_map().span_until_char(macro_call.span, '!'); - let Some(format_snippet) = snippet_opt(cx, format_string_span) else { + let Some(format_snippet) = format_string_span.get_source_text(cx) else { return; }; @@ -492,7 +492,7 @@ fn check_literal(cx: &LateContext<'_>, format_args: &FormatArgs, name: &str) { && let Some(arg) = format_args.arguments.by_index(index) && let rustc_ast::ExprKind::Lit(lit) = &arg.expr.kind && !arg.expr.span.from_expansion() - && let Some(value_string) = snippet_opt(cx, arg.expr.span) + && let Some(value_string) = arg.expr.span.get_source_text(cx) { let (replacement, replace_raw) = match lit.kind { LitKind::Str | LitKind::StrRaw(_) => match extract_str_literal(&value_string) { @@ -515,7 +515,7 @@ fn check_literal(cx: &LateContext<'_>, format_args: &FormatArgs, name: &str) { _ => continue, }; - let Some(format_string_snippet) = snippet_opt(cx, format_args.span) else { + let Some(format_string_snippet) = format_args.span.get_source_text(cx) else { continue; }; let format_string_is_raw = format_string_snippet.starts_with('r'); diff --git a/src/tools/clippy/clippy_utils/Cargo.toml b/src/tools/clippy/clippy_utils/Cargo.toml index 9fefd94d339..629ce9d04d4 100644 --- a/src/tools/clippy/clippy_utils/Cargo.toml +++ b/src/tools/clippy/clippy_utils/Cargo.toml @@ -8,7 +8,6 @@ publish = false clippy_config = { path = "../clippy_config" } arrayvec = { version = "0.7", default-features = false } itertools = "0.12" -rustc-semver = "1.1" # FIXME(f16_f128): remove when no longer needed for parsing rustc_apfloat = "0.2.0" diff --git a/src/tools/clippy/clippy_utils/src/attrs.rs b/src/tools/clippy/clippy_utils/src/attrs.rs index d2200bcf710..42c8b218d14 100644 --- a/src/tools/clippy/clippy_utils/src/attrs.rs +++ b/src/tools/clippy/clippy_utils/src/attrs.rs @@ -7,7 +7,7 @@ use rustc_session::Session; use rustc_span::{sym, Span}; use std::str::FromStr; -use crate::source::snippet_opt; +use crate::source::SpanRangeExt; use crate::tokenize_with_text; /// Deprecation status of attributes known by Clippy. @@ -179,25 +179,23 @@ pub fn has_non_exhaustive_attr(tcx: TyCtxt<'_>, adt: AdtDef<'_>) -> bool { /// Checks if the given span contains a `#[cfg(..)]` attribute pub fn span_contains_cfg(cx: &LateContext<'_>, s: Span) -> bool { - let Some(snip) = snippet_opt(cx, s) else { - // Assume true. This would require either an invalid span, or one which crosses file boundaries. - return true; - }; - let mut iter = tokenize_with_text(&snip); + s.check_source_text(cx, |src| { + let mut iter = tokenize_with_text(src); - // Search for the token sequence [`#`, `[`, `cfg`] - while iter.any(|(t, _)| matches!(t, TokenKind::Pound)) { - let mut iter = iter.by_ref().skip_while(|(t, _)| { - matches!( - t, - TokenKind::Whitespace | TokenKind::LineComment { .. } | TokenKind::BlockComment { .. } - ) - }); - if matches!(iter.next(), Some((TokenKind::OpenBracket, _))) - && matches!(iter.next(), Some((TokenKind::Ident, "cfg"))) - { - return true; + // Search for the token sequence [`#`, `[`, `cfg`] + while iter.any(|(t, _)| matches!(t, TokenKind::Pound)) { + let mut iter = iter.by_ref().skip_while(|(t, _)| { + matches!( + t, + TokenKind::Whitespace | TokenKind::LineComment { .. } | TokenKind::BlockComment { .. } + ) + }); + if matches!(iter.next(), Some((TokenKind::OpenBracket, _))) + && matches!(iter.next(), Some((TokenKind::Ident, "cfg"))) + { + return true; + } } - } - false + false + }) } diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs index 7f2234b310b..2bd6837d973 100644 --- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs +++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs @@ -123,16 +123,14 @@ fn qpath_search_pat(path: &QPath<'_>) -> (Pat, Pat) { fn path_search_pat(path: &Path<'_>) -> (Pat, Pat) { let (head, tail) = match path.segments { - [head, .., tail] => (head, tail), - [p] => (p, p), [] => return (Pat::Str(""), Pat::Str("")), + [p] => (Pat::Sym(p.ident.name), p), + // QPath::Resolved can have a path that looks like `::baz` where + // the path (`Bar::baz`) has it's span covering the whole QPath. + [.., tail] => (Pat::Str(""), tail), }; ( - if head.ident.name == kw::PathRoot { - Pat::Str("::") - } else { - Pat::Sym(head.ident.name) - }, + head, if tail.args.is_some() { Pat::Str(">") } else { diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index e907e4058e5..760d5bc95f7 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -687,7 +687,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> { if let Some(expr_span) = walk_span_to_context(expr.span, span.ctxt) && let expr_lo = expr_span.lo() && expr_lo >= span.lo - && let Some(src) = (span.lo..expr_lo).get_source_text(&self.tcx) + && let Some(src) = (span.lo..expr_lo).get_source_range(&self.tcx) && let Some(src) = src.as_str() { use rustc_lexer::TokenKind::{BlockComment, LineComment, OpenBrace, Semi, Whitespace}; diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index f325e4eaf15..f61ef9ac1b0 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -1,6 +1,6 @@ use crate::consts::ConstEvalCtxt; use crate::macros::macro_backtrace; -use crate::source::{snippet_opt, walk_span_to_context, SpanRange, SpanRangeExt}; +use crate::source::{walk_span_to_context, SpanRange, SpanRangeExt}; use crate::tokenize_with_text; use rustc_ast::ast::InlineAsmTemplatePiece; use rustc_data_structures::fx::FxHasher; @@ -588,10 +588,9 @@ fn reduce_exprkind<'hir>(cx: &LateContext<'_>, kind: &'hir ExprKind<'hir>) -> &' // block with an empty span. ([], None) if block.span.is_empty() => &ExprKind::Tup(&[]), // `{}` => `()` - ([], None) => match snippet_opt(cx, block.span) { - // Don't reduce if there are any tokens contained in the braces - Some(snip) - if tokenize(&snip) + ([], None) + if block.span.check_source_text(cx, |src| { + tokenize(src) .map(|t| t.kind) .filter(|t| { !matches!( @@ -599,11 +598,10 @@ fn reduce_exprkind<'hir>(cx: &LateContext<'_>, kind: &'hir ExprKind<'hir>) -> &' TokenKind::LineComment { .. } | TokenKind::BlockComment { .. } | TokenKind::Whitespace ) }) - .ne([TokenKind::OpenBrace, TokenKind::CloseBrace].iter().copied()) => - { - kind - }, - _ => &ExprKind::Tup(&[]), + .eq([TokenKind::OpenBrace, TokenKind::CloseBrace].iter().copied()) + }) => + { + &ExprKind::Tup(&[]) }, ([], Some(expr)) => match expr.kind { // `{ return .. }` => `return ..` @@ -1191,9 +1189,9 @@ fn eq_span_tokens( pred: impl Fn(TokenKind) -> bool, ) -> bool { fn f(cx: &LateContext<'_>, left: Range, right: Range, pred: impl Fn(TokenKind) -> bool) -> bool { - if let Some(lsrc) = left.get_source_text(cx) + if let Some(lsrc) = left.get_source_range(cx) && let Some(lsrc) = lsrc.as_str() - && let Some(rsrc) = right.get_source_text(cx) + && let Some(rsrc) = right.get_source_range(cx) && let Some(rsrc) = rsrc.as_str() { let pred = |t: &(_, _)| pred(t.0); diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 28755ae0710..5db14872c36 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -149,6 +149,7 @@ macro_rules! extract_msrv_attr { /// If the given expression is a local binding, find the initializer expression. /// If that initializer expression is another local binding, find its initializer again. +/// /// This process repeats as long as possible (but usually no more than once). Initializer /// expressions with adjustments are ignored. If this is not desired, use [`find_binding_init`] /// instead. @@ -179,6 +180,7 @@ pub fn expr_or_init<'a, 'b, 'tcx: 'b>(cx: &LateContext<'tcx>, mut expr: &'a Expr } /// Finds the initializer expression for a local binding. Returns `None` if the binding is mutable. +/// /// By only considering immutable bindings, we guarantee that the returned expression represents the /// value of the binding wherever it is referenced. /// @@ -431,12 +433,12 @@ pub fn qpath_generic_tys<'tcx>(qpath: &QPath<'tcx>) -> impl Iterator( path_def_id(cx, maybe_path).map_or(false, |id| cx.tcx.is_diagnostic_item(diag_item, id)) } -/// THIS METHOD IS DEPRECATED and will eventually be removed since it does not match against the +/// THIS METHOD IS DEPRECATED. Matches a `Path` against a slice of segment string literals. +/// +/// This method is deprecated and will eventually be removed since it does not match against the /// entire path or resolved `DefId`. Prefer using `match_def_path`. Consider getting a `DefId` from /// `QPath::Resolved.1.res.opt_def_id()`. /// -/// Matches a `Path` against a slice of segment string literals. -/// /// There is also `match_qpath` if you are dealing with a `rustc_hir::QPath` instead of a /// `rustc_hir::Path`. /// @@ -905,6 +907,7 @@ pub fn is_default_equivalent_call(cx: &LateContext<'_>, repl_func: &Expr<'_>) -> } /// Returns true if the expr is equal to `Default::default()` of it's type when evaluated. +/// /// It doesn't cover all cases, for example indirect function calls (some of std /// functions are supported) but it is the best we have. pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { @@ -1061,6 +1064,7 @@ impl std::ops::BitOrAssign for CaptureKind { } /// Given an expression referencing a local, determines how it would be captured in a closure. +/// /// Note as this will walk up to parent expressions until the capture can be determined it should /// only be used while making a closure somewhere a value is consumed. e.g. a block, match arm, or /// function argument (other than a receiver). @@ -2365,8 +2369,9 @@ pub fn fn_def_id_with_node_args<'tcx>( } /// Returns `Option` where String is a textual representation of the type encapsulated in -/// the slice iff the given expression is a slice of primitives (as defined in the -/// `is_recursively_primitive_type` function) and `None` otherwise. +/// the slice iff the given expression is a slice of primitives. +/// +/// (As defined in the `is_recursively_primitive_type` function.) Returns `None` otherwise. pub fn is_slice_of_primitives(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option { let expr_type = cx.typeck_results().expr_ty_adjusted(expr); let expr_kind = expr_type.kind(); diff --git a/src/tools/clippy/clippy_utils/src/macros.rs b/src/tools/clippy/clippy_utils/src/macros.rs index 455239cc37f..1d7479bff82 100644 --- a/src/tools/clippy/clippy_utils/src/macros.rs +++ b/src/tools/clippy/clippy_utils/src/macros.rs @@ -150,10 +150,11 @@ pub fn first_node_macro_backtrace(cx: &LateContext<'_>, node: &impl HirNode) -> } /// If `node` is the "first node" in a macro expansion, returns `Some` with the `ExpnId` of the -/// macro call site (i.e. the parent of the macro expansion). This generally means that `node` -/// is the outermost node of an entire macro expansion, but there are some caveats noted below. -/// This is useful for finding macro calls while visiting the HIR without processing the macro call -/// at every node within its expansion. +/// macro call site (i.e. the parent of the macro expansion). +/// +/// This generally means that `node` is the outermost node of an entire macro expansion, but there +/// are some caveats noted below. This is useful for finding macro calls while visiting the HIR +/// without processing the macro call at every node within its expansion. /// /// If you already have immediate access to the parent node, it is simpler to /// just check the context of that span directly (e.g. `parent.span.from_expansion()`). @@ -426,12 +427,8 @@ impl FormatArgsStorage { } } -/// Attempt to find the [`rustc_hir::Expr`] that corresponds to the [`FormatArgument`]'s value, if -/// it cannot be found it will return the [`rustc_ast::Expr`]. -pub fn find_format_arg_expr<'hir, 'ast>( - start: &'hir Expr<'hir>, - target: &'ast FormatArgument, -) -> Result<&'hir Expr<'hir>, &'ast rustc_ast::Expr> { +/// Attempt to find the [`rustc_hir::Expr`] that corresponds to the [`FormatArgument`]'s value +pub fn find_format_arg_expr<'hir>(start: &'hir Expr<'hir>, target: &FormatArgument) -> Option<&'hir Expr<'hir>> { let SpanData { lo, hi, @@ -449,7 +446,6 @@ pub fn find_format_arg_expr<'hir, 'ast>( ControlFlow::Continue(()) } }) - .ok_or(&target.expr) } /// Span of the `:` and format specifiers diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 553af913ef9..d9befb3c157 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -18,7 +18,6 @@ use rustc_middle::mir::{ use rustc_middle::traits::{BuiltinImplSource, ImplSource, ObligationCause}; use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::{self, GenericArgKind, TraitRef, Ty, TyCtxt}; -use rustc_semver::RustcVersion; use rustc_span::symbol::sym; use rustc_span::Span; use rustc_trait_selection::traits::{ObligationCtxt, SelectionContext}; @@ -110,7 +109,7 @@ fn check_rvalue<'tcx>( ) -> McfResult { match rvalue { Rvalue::ThreadLocalRef(_) => Err((span, "cannot access thread local storage in const fn".into())), - Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => { + Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) => { check_place(tcx, *place, span, body, msrv) }, Rvalue::CopyForDeref(place) => check_place(tcx, *place, span, body, msrv), @@ -391,11 +390,7 @@ fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: &Msrv) -> bool { StableSince::Err => return false, }; - msrv.meets(RustcVersion::new( - u32::from(const_stab_rust_version.major), - u32::from(const_stab_rust_version.minor), - u32::from(const_stab_rust_version.patch), - )) + msrv.meets(const_stab_rust_version) } else { // Unstable const fn with the feature enabled. msrv.current().is_none() diff --git a/src/tools/clippy/clippy_utils/src/source.rs b/src/tools/clippy/clippy_utils/src/source.rs index 96dd3c55d37..482e1e0147b 100644 --- a/src/tools/clippy/clippy_utils/src/source.rs +++ b/src/tools/clippy/clippy_utils/src/source.rs @@ -16,7 +16,7 @@ use rustc_span::{ }; use std::borrow::Cow; use std::fmt; -use std::ops::Range; +use std::ops::{Deref, Index, Range}; pub trait HasSession { fn sess(&self) -> &Session; @@ -94,10 +94,16 @@ impl IntoSpan for Range { } pub trait SpanRangeExt: SpanRange { + /// Attempts to get a handle to the source text. Returns `None` if either the span is malformed, + /// or the source text is not accessible. + fn get_source_text(self, cx: &impl HasSession) -> Option { + get_source_range(cx.sess().source_map(), self.into_range()).and_then(SourceText::new) + } + /// Gets the source file, and range in the file, of the given span. Returns `None` if the span /// extends through multiple files, or is malformed. - fn get_source_text(self, cx: &impl HasSession) -> Option { - get_source_text(cx.sess().source_map(), self.into_range()) + fn get_source_range(self, cx: &impl HasSession) -> Option { + get_source_range(cx.sess().source_map(), self.into_range()) } /// Calls the given function with the source text referenced and returns the value. Returns @@ -144,32 +150,70 @@ pub trait SpanRangeExt: SpanRange { fn trim_start(self, cx: &impl HasSession) -> Range { trim_start(cx.sess().source_map(), self.into_range()) } - - /// Writes the referenced source text to the given writer. Will return `Err` if the source text - /// could not be retrieved. - fn write_source_text_to(self, cx: &impl HasSession, dst: &mut impl fmt::Write) -> fmt::Result { - write_source_text_to(cx.sess().source_map(), self.into_range(), dst) - } - - /// Extracts the referenced source text as an owned string. - fn source_text_to_string(self, cx: &impl HasSession) -> Option { - self.with_source_text(cx, ToOwned::to_owned) - } } impl SpanRangeExt for T {} -fn get_source_text(sm: &SourceMap, sp: Range) -> Option { +/// Handle to a range of text in a source file. +pub struct SourceText(SourceFileRange); +impl SourceText { + /// Takes ownership of the source file handle if the source text is accessible. + pub fn new(text: SourceFileRange) -> Option { + if text.as_str().is_some() { + Some(Self(text)) + } else { + None + } + } + + /// Gets the source text. + pub fn as_str(&self) -> &str { + self.0.as_str().unwrap() + } + + /// Converts this into an owned string. + pub fn to_owned(&self) -> String { + self.as_str().to_owned() + } +} +impl Deref for SourceText { + type Target = str; + fn deref(&self) -> &Self::Target { + self.as_str() + } +} +impl AsRef for SourceText { + fn as_ref(&self) -> &str { + self.as_str() + } +} +impl Index for SourceText +where + str: Index, +{ + type Output = >::Output; + fn index(&self, idx: T) -> &Self::Output { + &self.as_str()[idx] + } +} +impl fmt::Display for SourceText { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.as_str().fmt(f) + } +} + +fn get_source_range(sm: &SourceMap, sp: Range) -> Option { let start = sm.lookup_byte_offset(sp.start); let end = sm.lookup_byte_offset(sp.end); if !Lrc::ptr_eq(&start.sf, &end.sf) || start.pos > end.pos { return None; } + sm.ensure_source_file_source_present(&start.sf); let range = start.pos.to_usize()..end.pos.to_usize(); Some(SourceFileRange { sf: start.sf, range }) } fn with_source_text(sm: &SourceMap, sp: Range, f: impl for<'a> FnOnce(&'a str) -> T) -> Option { - if let Some(src) = get_source_text(sm, sp) + if let Some(src) = get_source_range(sm, sp) && let Some(src) = src.as_str() { Some(f(src)) @@ -183,7 +227,7 @@ fn with_source_text_and_range( sp: Range, f: impl for<'a> FnOnce(&'a str, Range) -> T, ) -> Option { - if let Some(src) = get_source_text(sm, sp) + if let Some(src) = get_source_range(sm, sp) && let Some(text) = &src.sf.src { Some(f(text, src.range)) @@ -198,7 +242,7 @@ fn map_range( sp: Range, f: impl for<'a> FnOnce(&'a str, Range) -> Option>, ) -> Option> { - if let Some(src) = get_source_text(sm, sp.clone()) + if let Some(src) = get_source_range(sm, sp.clone()) && let Some(text) = &src.sf.src && let Some(range) = f(text, src.range.clone()) { @@ -232,13 +276,6 @@ fn trim_start(sm: &SourceMap, sp: Range) -> Range { .unwrap_or(sp) } -fn write_source_text_to(sm: &SourceMap, sp: Range, dst: &mut impl fmt::Write) -> fmt::Result { - match with_source_text(sm, sp, |src| dst.write_str(src)) { - Some(x) => x, - None => Err(fmt::Error), - } -} - pub struct SourceFileRange { pub sf: Lrc, pub range: Range, @@ -247,7 +284,11 @@ impl SourceFileRange { /// Attempts to get the text from the source file. This can fail if the source text isn't /// loaded. pub fn as_str(&self) -> Option<&str> { - self.sf.src.as_ref().and_then(|x| x.get(self.range.clone())) + self.sf + .src + .as_ref() + .or_else(|| self.sf.external_src.get().and_then(|src| src.get_source())) + .and_then(|x| x.get(self.range.clone())) } } @@ -548,9 +589,10 @@ pub fn snippet_block_with_context<'a>( (reindent_multiline(snip, true, indent), from_macro) } -/// Same as `snippet_with_applicability`, but first walks the span up to the given context. This -/// will result in the macro call, rather than the expansion, if the span is from a child context. -/// If the span is not from a child context, it will be used directly instead. +/// Same as `snippet_with_applicability`, but first walks the span up to the given context. +/// +/// This will result in the macro call, rather than the expansion, if the span is from a child +/// context. If the span is not from a child context, it will be used directly instead. /// /// e.g. Given the expression `&vec![]`, getting a snippet from the span for `vec![]` as a HIR node /// would result in `box []`. If given the context of the address of expression, this function will @@ -593,9 +635,10 @@ fn snippet_with_context_sess<'a>( } /// Walks the span up to the target context, thereby returning the macro call site if the span is -/// inside a macro expansion, or the original span if it is not. Note this will return `None` in the -/// case of the span being in a macro expansion, but the target context is from expanding a macro -/// argument. +/// inside a macro expansion, or the original span if it is not. +/// +/// Note this will return `None` in the case of the span being in a macro expansion, but the target +/// context is from expanding a macro argument. /// /// Given the following /// diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index bd48990aea9..f80981c11af 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -160,8 +160,10 @@ pub fn get_type_diagnostic_name(cx: &LateContext<'_>, ty: Ty<'_>) -> Option, ty: Ty<'_>) -> bool { matches!( get_type_diagnostic_name(cx, ty), @@ -398,8 +400,10 @@ fn is_normalizable_helper<'tcx>( } /// Returns `true` if the given type is a non aggregate primitive (a `bool` or `char`, any -/// integer or floating-point number type). For checking aggregation of primitive types (e.g. -/// tuples and slices of primitive type) see `is_recursively_primitive_type` +/// integer or floating-point number type). +/// +/// For checking aggregation of primitive types (e.g. tuples and slices of primitive type) see +/// `is_recursively_primitive_type` pub fn is_non_aggregate_primitive_type(ty: Ty<'_>) -> bool { matches!(ty.kind(), ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_)) } @@ -455,11 +459,6 @@ pub fn is_type_lang_item(cx: &LateContext<'_>, ty: Ty<'_>, lang_item: LangItem) } } -/// Gets the diagnostic name of the type, if it has one -pub fn type_diagnostic_name(cx: &LateContext<'_>, ty: Ty<'_>) -> Option { - ty.ty_adt_def().and_then(|adt| cx.tcx.get_diagnostic_name(adt.did())) -} - /// Return `true` if the passed `typ` is `isize` or `usize`. pub fn is_isize_or_usize(typ: Ty<'_>) -> bool { matches!(typ.kind(), ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize)) @@ -476,9 +475,10 @@ pub fn match_type(cx: &LateContext<'_>, ty: Ty<'_>, path: &[&str]) -> bool { } } -/// Checks if the drop order for a type matters. Some std types implement drop solely to -/// deallocate memory. For these types, and composites containing them, changing the drop order -/// won't result in any observable side effects. +/// Checks if the drop order for a type matters. +/// +/// Some std types implement drop solely to deallocate memory. For these types, and composites +/// containing them, changing the drop order won't result in any observable side effects. pub fn needs_ordered_drop<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { fn needs_ordered_drop_inner<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, seen: &mut FxHashSet>) -> bool { if !seen.insert(ty) { @@ -541,7 +541,7 @@ pub fn peel_mid_ty_refs_is_mutable(ty: Ty<'_>) -> (Ty<'_>, usize, Mutability) { /// Returns `true` if the given type is an `unsafe` function. pub fn type_is_unsafe_function<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { match ty.kind() { - ty::FnDef(..) | ty::FnPtr(_) => ty.fn_sig(cx.tcx).safety() == Safety::Unsafe, + ty::FnDef(..) | ty::FnPtr(..) => ty.fn_sig(cx.tcx).safety() == Safety::Unsafe, _ => false, } } @@ -721,7 +721,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option Some(ExprFnSig::Sig(sig, None)), + ty::FnPtr(sig_tys, hdr) => Some(ExprFnSig::Sig(sig_tys.with(hdr), None)), ty::Dynamic(bounds, _, _) => { let lang_items = cx.tcx.lang_items(); match bounds.principal() { @@ -1311,6 +1311,7 @@ pub fn deref_chain<'cx, 'tcx>(cx: &'cx LateContext<'tcx>, ty: Ty<'tcx>) -> impl } /// Checks if a Ty<'_> has some inherent method Symbol. +/// /// This does not look for impls in the type's `Deref::Target` type. /// If you need this, you should wrap this call in `clippy_utils::ty::deref_chain().any(...)`. pub fn get_adt_inherent_method<'a>(cx: &'a LateContext<'_>, ty: Ty<'_>, method_name: Symbol) -> Option<&'a AssocItem> { diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs index 2a5d3536ff6..e5b6d3965e9 100644 --- a/src/tools/clippy/clippy_utils/src/visitors.rs +++ b/src/tools/clippy/clippy_utils/src/visitors.rs @@ -441,7 +441,7 @@ pub fn is_expr_unsafe<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> bool { ty::FnDef(id, _) if self.cx.tcx.fn_sig(id).skip_binder().safety() == Safety::Unsafe => { self.is_unsafe = true; }, - ty::FnPtr(sig) if sig.safety() == Safety::Unsafe => self.is_unsafe = true, + ty::FnPtr(_, hdr) if hdr.safety == Safety::Unsafe => self.is_unsafe = true, _ => walk_expr(self, e), }, ExprKind::Path(ref p) diff --git a/src/tools/clippy/declare_clippy_lint/src/lib.rs b/src/tools/clippy/declare_clippy_lint/src/lib.rs index ca070f6c250..6aa24329b06 100644 --- a/src/tools/clippy/declare_clippy_lint/src/lib.rs +++ b/src/tools/clippy/declare_clippy_lint/src/lib.rs @@ -1,4 +1,4 @@ -#![feature(let_chains)] +#![feature(let_chains, proc_macro_span)] // warn on lints, that are included in `rust-lang/rust`s bootstrap #![warn(rust_2018_idioms, unused_lifetimes)] @@ -23,6 +23,7 @@ fn parse_attr(path: [&'static str; LEN], attr: &Attribute) -> struct ClippyLint { attrs: Vec, + version: Option, explanation: String, name: Ident, category: Ident, @@ -41,8 +42,14 @@ impl Parse for ClippyLint { let value = lit.value(); let line = value.strip_prefix(' ').unwrap_or(&value); - if line.starts_with("```") { - explanation += "```\n"; + if let Some(lang) = line.strip_prefix("```") { + let tag = lang.split_once(',').map_or(lang, |(left, _)| left); + if !in_code && matches!(tag, "" | "rust" | "ignore" | "should_panic" | "no_run" | "compile_fail") { + explanation += "```rust\n"; + } else { + explanation += line; + explanation.push('\n'); + } in_code = !in_code; } else if !(in_code && line.starts_with("# ")) { explanation += line; @@ -68,6 +75,7 @@ impl Parse for ClippyLint { Ok(Self { attrs, + version, explanation, name, category, @@ -123,6 +131,7 @@ impl Parse for ClippyLint { pub fn declare_clippy_lint(input: TokenStream) -> TokenStream { let ClippyLint { attrs, + version, explanation, name, category, @@ -146,6 +155,14 @@ pub fn declare_clippy_lint(input: TokenStream) -> TokenStream { (&mut category[0..1]).make_ascii_uppercase(); let category_variant = format_ident!("{category}"); + let name_span = name.span().unwrap(); + let location = format!("{}#L{}", name_span.source_file().path().display(), name_span.line()); + + let version = match version { + Some(version) => quote!(Some(#version)), + None => quote!(None), + }; + let output = quote! { rustc_session::declare_tool_lint! { #(#attrs)* @@ -159,6 +176,8 @@ pub fn declare_clippy_lint(input: TokenStream) -> TokenStream { lint: &#name, category: crate::LintCategory::#category_variant, explanation: #explanation, + location: #location, + version: #version, }; }; diff --git a/src/tools/clippy/lintcheck/src/json.rs b/src/tools/clippy/lintcheck/src/json.rs index 4211bce90b2..ee0c80aea52 100644 --- a/src/tools/clippy/lintcheck/src/json.rs +++ b/src/tools/clippy/lintcheck/src/json.rs @@ -12,21 +12,21 @@ const TRUNCATION_TOTAL_TARGET: usize = 1000; #[derive(Debug, Deserialize, Serialize)] struct LintJson { - lint: String, - krate: String, - file_name: String, - byte_pos: (u32, u32), - file_link: String, + /// The lint name e.g. `clippy::bytes_nth` + name: String, + /// The filename and line number e.g. `anyhow-1.0.86/src/error.rs:42` + file_line: String, + file_url: String, rendered: String, } impl LintJson { fn key(&self) -> impl Ord + '_ { - (self.lint.as_str(), self.file_name.as_str(), self.byte_pos) + (self.name.as_str(), self.file_line.as_str()) } fn info_text(&self, action: &str) -> String { - format!("{action} `{}` in `{}` at {}", self.lint, self.krate, self.file_link) + format!("{action} `{}` at [`{}`]({})", self.name, self.file_line, self.file_url) } } @@ -36,13 +36,16 @@ pub(crate) fn output(clippy_warnings: Vec) -> String { .into_iter() .map(|warning| { let span = warning.span(); + let file_name = span + .file_name + .strip_prefix("target/lintcheck/sources/") + .unwrap_or(&span.file_name); + let file_line = format!("{file_name}:{}", span.line_start); LintJson { - file_name: span.file_name.clone(), - byte_pos: (span.byte_start, span.byte_end), - krate: warning.krate, - file_link: warning.url, - lint: warning.lint, - rendered: warning.diag.rendered.unwrap(), + name: warning.name, + file_line, + file_url: warning.url, + rendered: warning.diag.rendered.unwrap().trim().to_string(), } }) .collect(); @@ -63,7 +66,7 @@ pub(crate) fn diff(old_path: &Path, new_path: &Path, truncate: bool) { let mut lint_warnings = vec![]; for (name, changes) in &itertools::merge_join_by(old_warnings, new_warnings, |old, new| old.key().cmp(&new.key())) - .chunk_by(|change| change.as_ref().into_left().lint.to_string()) + .chunk_by(|change| change.as_ref().into_left().name.clone()) { let mut added = Vec::new(); let mut removed = Vec::new(); @@ -162,7 +165,7 @@ fn print_warnings(title: &str, warnings: &[LintJson], truncate_after: usize) { return; } - print_h3(&warnings[0].lint, title); + print_h3(&warnings[0].name, title); println!(); let warnings = truncate(warnings, truncate_after); @@ -171,7 +174,7 @@ fn print_warnings(title: &str, warnings: &[LintJson], truncate_after: usize) { println!("{}", warning.info_text(title)); println!(); println!("```"); - println!("{}", warning.rendered.trim_end()); + println!("{}", warning.rendered); println!("```"); println!(); } @@ -182,7 +185,7 @@ fn print_changed_diff(changed: &[(LintJson, LintJson)], truncate_after: usize) { return; } - print_h3(&changed[0].0.lint, "Changed"); + print_h3(&changed[0].0.name, "Changed"); println!(); let changed = truncate(changed, truncate_after); @@ -191,7 +194,7 @@ fn print_changed_diff(changed: &[(LintJson, LintJson)], truncate_after: usize) { println!("{}", new.info_text("Changed")); println!(); println!("```diff"); - for change in diff::lines(old.rendered.trim_end(), new.rendered.trim_end()) { + for change in diff::lines(&old.rendered, &new.rendered) { use diff::Result::{Both, Left, Right}; match change { diff --git a/src/tools/clippy/lintcheck/src/output.rs b/src/tools/clippy/lintcheck/src/output.rs index 15378630695..e38036315c2 100644 --- a/src/tools/clippy/lintcheck/src/output.rs +++ b/src/tools/clippy/lintcheck/src/output.rs @@ -51,7 +51,7 @@ impl RustcIce { /// A single warning that clippy issued while checking a `Crate` #[derive(Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct ClippyWarning { - pub lint: String, + pub name: String, pub diag: Diagnostic, pub krate: String, /// The URL that points to the file and line of the lint emission @@ -60,8 +60,8 @@ pub struct ClippyWarning { impl ClippyWarning { pub fn new(mut diag: Diagnostic, base_url: &str, krate: &str) -> Option { - let lint = diag.code.clone()?.code; - if !(lint.contains("clippy") || diag.message.contains("clippy")) + let name = diag.code.clone()?.code; + if !(name.contains("clippy") || diag.message.contains("clippy")) || diag.message.contains("could not read cargo metadata") { return None; @@ -92,7 +92,7 @@ impl ClippyWarning { }; Some(Self { - lint, + name, diag, url, krate: krate.to_string(), @@ -108,7 +108,7 @@ impl ClippyWarning { let mut file = span.file_name.clone(); let file_with_pos = format!("{file}:{}:{}", span.line_start, span.line_end); match format { - OutputFormat::Text => format!("{file_with_pos} {} \"{}\"\n", self.lint, self.diag.message), + OutputFormat::Text => format!("{file_with_pos} {} \"{}\"\n", self.name, self.diag.message), OutputFormat::Markdown => { if file.starts_with("target") { file.insert_str(0, "../"); @@ -116,7 +116,7 @@ impl ClippyWarning { let mut output = String::from("| "); write!(output, "[`{file_with_pos}`]({file}#L{})", span.line_start).unwrap(); - write!(output, r#" | `{:<50}` | "{}" |"#, self.lint, self.diag.message).unwrap(); + write!(output, r#" | `{:<50}` | "{}" |"#, self.name, self.diag.message).unwrap(); output.push('\n'); output }, @@ -164,7 +164,7 @@ fn gather_stats(warnings: &[ClippyWarning]) -> (String, HashMap<&String, usize>) let mut counter: HashMap<&String, usize> = HashMap::new(); warnings .iter() - .for_each(|wrn| *counter.entry(&wrn.lint).or_insert(0) += 1); + .for_each(|wrn| *counter.entry(&wrn.name).or_insert(0) += 1); // collect into a tupled list for sorting let mut stats: Vec<(&&String, &usize)> = counter.iter().collect(); diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain index 5fbe4e544a9..0be2e81810e 100644 --- a/src/tools/clippy/rust-toolchain +++ b/src/tools/clippy/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2024-08-08" +channel = "nightly-2024-08-23" components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] profile = "minimal" diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs index 64253514fbe..9754254cdd0 100644 --- a/src/tools/clippy/tests/compile-test.rs +++ b/src/tools/clippy/tests/compile-test.rs @@ -1,25 +1,31 @@ -// We need this feature as it changes `dylib` linking behavior and allows us to link to -// `rustc_driver`. -#![feature(rustc_private)] +#![feature(rustc_private, let_chains)] #![warn(rust_2018_idioms, unused_lifetimes)] #![allow(unused_extern_crates)] +use cargo_metadata::diagnostic::{Applicability, Diagnostic}; +use cargo_metadata::Message; +use clippy_config::ClippyConfiguration; +use clippy_lints::declared_lints::LINTS; +use clippy_lints::deprecated_lints::{DEPRECATED, DEPRECATED_VERSION, RENAMED}; +use clippy_lints::LintInfo; +use serde::{Deserialize, Serialize}; +use test_utils::IS_RUSTC_TEST_SUITE; use ui_test::custom_flags::rustfix::RustfixMode; +use ui_test::custom_flags::Flag; use ui_test::spanned::Spanned; +use ui_test::test_result::TestRun; use ui_test::{status_emitter, Args, CommandBuilder, Config, Match, OutputConflictHandling}; -use std::collections::BTreeMap; +use std::collections::{BTreeMap, HashMap}; use std::env::{self, set_var, var_os}; use std::ffi::{OsStr, OsString}; -use std::fs; +use std::fmt::Write; use std::path::{Path, PathBuf}; -use std::sync::LazyLock; -use test_utils::IS_RUSTC_TEST_SUITE; +use std::sync::mpsc::{channel, Sender}; +use std::{fs, iter, thread}; // Test dependencies may need an `extern crate` here to ensure that they show up // in the depinfo file (otherwise cargo thinks they are unused) -extern crate clippy_lints; -extern crate clippy_utils; extern crate futures; extern crate if_chain; extern crate itertools; @@ -55,7 +61,7 @@ static TEST_DEPENDENCIES: &[&str] = &[ /// dependencies must be added to Cargo.toml at the project root. Test /// dependencies that are not *directly* used by this test module require an /// `extern crate` declaration. -static EXTERN_FLAGS: LazyLock> = LazyLock::new(|| { +fn extern_flags() -> Vec { let current_exe_depinfo = { let mut path = env::current_exe().unwrap(); path.set_extension("d"); @@ -103,70 +109,93 @@ static EXTERN_FLAGS: LazyLock> = LazyLock::new(|| { .into_iter() .map(|(name, path)| format!("--extern={name}={path}")) .collect() -}); +} // whether to run internal tests or not const RUN_INTERNAL_TESTS: bool = cfg!(feature = "internal"); -fn base_config(test_dir: &str) -> (Config, Args) { - let mut args = Args::test().unwrap(); - args.bless |= var_os("RUSTC_BLESS").is_some_and(|v| v != "0"); - - let target_dir = PathBuf::from(var_os("CARGO_TARGET_DIR").unwrap_or_else(|| "target".into())); - let mut config = Config { - output_conflict_handling: OutputConflictHandling::Error, - filter_files: env::var("TESTNAME") - .map(|filters| filters.split(',').map(str::to_string).collect()) - .unwrap_or_default(), - target: None, - bless_command: Some("cargo uibless".into()), - out_dir: target_dir.join("ui_test"), - ..Config::rustc(Path::new("tests").join(test_dir)) - }; - config.comment_defaults.base().exit_status = None.into(); - config.comment_defaults.base().require_annotations = None.into(); - config - .comment_defaults - .base() - .set_custom("rustfix", RustfixMode::Everything); - config.comment_defaults.base().diagnostic_code_prefix = Some(Spanned::dummy("clippy::".into())).into(); - config.with_args(&args); - let current_exe_path = env::current_exe().unwrap(); - let deps_path = current_exe_path.parent().unwrap(); - let profile_path = deps_path.parent().unwrap(); - - config.program.args.extend( - [ - "--emit=metadata", - "-Aunused", - "-Ainternal_features", - "-Zui-testing", - "-Zdeduplicate-diagnostics=no", - "-Dwarnings", - &format!("-Ldependency={}", deps_path.display()), - ] - .map(OsString::from), - ); - - config.program.args.extend(EXTERN_FLAGS.iter().map(OsString::from)); - // Prevent rustc from creating `rustc-ice-*` files the console output is enough. - config.program.envs.push(("RUSTC_ICE".into(), Some("0".into()))); - - if let Some(host_libs) = option_env!("HOST_LIBS") { - let dep = format!("-Ldependency={}", Path::new(host_libs).join("deps").display()); - config.program.args.push(dep.into()); - } - - config.program.program = profile_path.join(if cfg!(windows) { - "clippy-driver.exe" - } else { - "clippy-driver" - }); - (config, args) +struct TestContext { + args: Args, + extern_flags: Vec, + diagnostic_collector: Option, + collector_thread: Option>, } -fn run_ui() { - let (mut config, args) = base_config("ui"); +impl TestContext { + fn new() -> Self { + let mut args = Args::test().unwrap(); + args.bless |= var_os("RUSTC_BLESS").is_some_and(|v| v != "0"); + let (diagnostic_collector, collector_thread) = var_os("COLLECT_METADATA") + .is_some() + .then(DiagnosticCollector::spawn) + .unzip(); + Self { + args, + extern_flags: extern_flags(), + diagnostic_collector, + collector_thread, + } + } + + fn base_config(&self, test_dir: &str) -> Config { + let target_dir = PathBuf::from(var_os("CARGO_TARGET_DIR").unwrap_or_else(|| "target".into())); + let mut config = Config { + output_conflict_handling: OutputConflictHandling::Error, + filter_files: env::var("TESTNAME") + .map(|filters| filters.split(',').map(str::to_string).collect()) + .unwrap_or_default(), + target: None, + bless_command: Some("cargo uibless".into()), + out_dir: target_dir.join("ui_test"), + ..Config::rustc(Path::new("tests").join(test_dir)) + }; + let defaults = config.comment_defaults.base(); + defaults.exit_status = None.into(); + defaults.require_annotations = None.into(); + defaults.diagnostic_code_prefix = Some(Spanned::dummy("clippy::".into())).into(); + defaults.set_custom("rustfix", RustfixMode::Everything); + if let Some(collector) = self.diagnostic_collector.clone() { + defaults.set_custom("diagnostic-collector", collector); + } + config.with_args(&self.args); + let current_exe_path = env::current_exe().unwrap(); + let deps_path = current_exe_path.parent().unwrap(); + let profile_path = deps_path.parent().unwrap(); + + config.program.args.extend( + [ + "--emit=metadata", + "-Aunused", + "-Ainternal_features", + "-Zui-testing", + "-Zdeduplicate-diagnostics=no", + "-Dwarnings", + &format!("-Ldependency={}", deps_path.display()), + ] + .map(OsString::from), + ); + + config.program.args.extend(self.extern_flags.iter().map(OsString::from)); + // Prevent rustc from creating `rustc-ice-*` files the console output is enough. + config.program.envs.push(("RUSTC_ICE".into(), Some("0".into()))); + + if let Some(host_libs) = option_env!("HOST_LIBS") { + let dep = format!("-Ldependency={}", Path::new(host_libs).join("deps").display()); + config.program.args.push(dep.into()); + } + + config.program.program = profile_path.join(if cfg!(windows) { + "clippy-driver.exe" + } else { + "clippy-driver" + }); + + config + } +} + +fn run_ui(cx: &TestContext) { + let mut config = cx.base_config("ui"); config .program .envs @@ -176,30 +205,29 @@ fn run_ui() { vec![config], ui_test::default_file_filter, ui_test::default_per_file_config, - status_emitter::Text::from(args.format), + status_emitter::Text::from(cx.args.format), ) .unwrap(); } -fn run_internal_tests() { - // only run internal tests with the internal-tests feature +fn run_internal_tests(cx: &TestContext) { if !RUN_INTERNAL_TESTS { return; } - let (mut config, args) = base_config("ui-internal"); + let mut config = cx.base_config("ui-internal"); config.bless_command = Some("cargo uitest --features internal -- -- --bless".into()); ui_test::run_tests_generic( vec![config], ui_test::default_file_filter, ui_test::default_per_file_config, - status_emitter::Text::from(args.format), + status_emitter::Text::from(cx.args.format), ) .unwrap(); } -fn run_ui_toml() { - let (mut config, args) = base_config("ui-toml"); +fn run_ui_toml(cx: &TestContext) { + let mut config = cx.base_config("ui-toml"); config .comment_defaults @@ -217,19 +245,19 @@ fn run_ui_toml() { .envs .push(("CLIPPY_CONF_DIR".into(), Some(path.parent().unwrap().into()))); }, - status_emitter::Text::from(args.format), + status_emitter::Text::from(cx.args.format), ) .unwrap(); } // Allow `Default::default` as `OptWithSpan` is not nameable #[allow(clippy::default_trait_access)] -fn run_ui_cargo() { +fn run_ui_cargo(cx: &TestContext) { if IS_RUSTC_TEST_SUITE { return; } - let (mut config, args) = base_config("ui-cargo"); + let mut config = cx.base_config("ui-cargo"); config.program.input_file_flag = CommandBuilder::cargo().input_file_flag; config.program.out_dir_flag = CommandBuilder::cargo().out_dir_flag; config.program.args = vec!["clippy".into(), "--color".into(), "never".into(), "--quiet".into()]; @@ -264,23 +292,25 @@ fn run_ui_cargo() { .then(|| ui_test::default_any_file_filter(path, config) && !ignored_32bit(path)) }, |_config, _file_contents| {}, - status_emitter::Text::from(args.format), + status_emitter::Text::from(cx.args.format), ) .unwrap(); } fn main() { set_var("CLIPPY_DISABLE_DOCS_LINKS", "true"); + + let cx = TestContext::new(); + // The SPEEDTEST_* env variables can be used to check Clippy's performance on your PR. It runs the // affected test 1000 times and gets the average. if let Ok(speedtest) = std::env::var("SPEEDTEST") { println!("----------- STARTING SPEEDTEST -----------"); let f = match speedtest.as_str() { - "ui" => run_ui as fn(), - "cargo" => run_ui_cargo as fn(), - "toml" => run_ui_toml as fn(), - "internal" => run_internal_tests as fn(), - "ui-cargo-toml-metadata" => ui_cargo_toml_metadata as fn(), + "ui" => run_ui, + "cargo" => run_ui_cargo, + "toml" => run_ui_toml, + "internal" => run_internal_tests, _ => panic!("unknown speedtest: {speedtest} || accepted speedtests are: [ui, cargo, toml, internal]"), }; @@ -297,7 +327,7 @@ fn main() { let mut sum = 0; for _ in 0..iterations { let start = std::time::Instant::now(); - f(); + f(&cx); sum += start.elapsed().as_millis(); } println!( @@ -306,11 +336,17 @@ fn main() { sum / u128::from(iterations) ); } else { - run_ui(); - run_ui_toml(); - run_ui_cargo(); - run_internal_tests(); + run_ui(&cx); + run_ui_toml(&cx); + run_ui_cargo(&cx); + run_internal_tests(&cx); + drop(cx.diagnostic_collector); + ui_cargo_toml_metadata(); + + if let Some(thread) = cx.collector_thread { + thread.join().unwrap(); + } } } @@ -349,3 +385,180 @@ fn ui_cargo_toml_metadata() { ); } } + +#[derive(Deserialize)] +#[serde(untagged)] +enum DiagnosticOrMessage { + Diagnostic(Diagnostic), + Message(Message), +} + +/// Collects applicabilities from the diagnostics produced for each UI test, producing the +/// `util/gh-pages/lints.json` file used by +#[derive(Debug, Clone)] +struct DiagnosticCollector { + sender: Sender>, +} + +impl DiagnosticCollector { + #[allow(clippy::assertions_on_constants)] + fn spawn() -> (Self, thread::JoinHandle<()>) { + assert!(!IS_RUSTC_TEST_SUITE && !RUN_INTERNAL_TESTS); + + let (sender, receiver) = channel::>(); + + let handle = thread::spawn(|| { + let mut applicabilities = HashMap::new(); + + for stderr in receiver { + for line in stderr.split(|&byte| byte == b'\n') { + let diag = match serde_json::from_slice(line) { + Ok(DiagnosticOrMessage::Diagnostic(diag)) => diag, + Ok(DiagnosticOrMessage::Message(Message::CompilerMessage(message))) => message.message, + _ => continue, + }; + + if let Some(lint) = diag.code.as_ref().and_then(|code| code.code.strip_prefix("clippy::")) { + let applicability = applicabilities + .entry(lint.to_string()) + .or_insert(Applicability::Unspecified); + let diag_applicability = diag + .children + .iter() + .flat_map(|child| &child.spans) + .filter_map(|span| span.suggestion_applicability.clone()) + .max_by_key(applicability_ord); + if let Some(diag_applicability) = diag_applicability + && applicability_ord(&diag_applicability) > applicability_ord(applicability) + { + *applicability = diag_applicability; + } + } + } + } + + let configs = clippy_config::get_configuration_metadata(); + let mut metadata: Vec = LINTS + .iter() + .map(|lint| LintMetadata::new(lint, &applicabilities, &configs)) + .chain( + iter::zip(DEPRECATED, DEPRECATED_VERSION) + .map(|((lint, reason), version)| LintMetadata::new_deprecated(lint, reason, version)), + ) + .collect(); + metadata.sort_unstable_by(|a, b| a.id.cmp(&b.id)); + + let json = serde_json::to_string_pretty(&metadata).unwrap(); + fs::write("util/gh-pages/lints.json", json).unwrap(); + }); + + (Self { sender }, handle) + } +} + +fn applicability_ord(applicability: &Applicability) -> u8 { + match applicability { + Applicability::MachineApplicable => 4, + Applicability::HasPlaceholders => 3, + Applicability::MaybeIncorrect => 2, + Applicability::Unspecified => 1, + _ => unimplemented!(), + } +} + +impl Flag for DiagnosticCollector { + fn post_test_action( + &self, + _config: &ui_test::per_test_config::TestConfig<'_>, + _cmd: &mut std::process::Command, + output: &std::process::Output, + _build_manager: &ui_test::build_manager::BuildManager<'_>, + ) -> Result, ui_test::Errored> { + if !output.stderr.is_empty() { + self.sender.send(output.stderr.clone()).unwrap(); + } + Ok(Vec::new()) + } + + fn clone_inner(&self) -> Box { + Box::new(self.clone()) + } + + fn must_be_unique(&self) -> bool { + true + } +} + +#[derive(Debug, Serialize)] +struct LintMetadata { + id: String, + id_location: Option<&'static str>, + group: &'static str, + level: &'static str, + docs: String, + version: &'static str, + applicability: Applicability, +} + +impl LintMetadata { + fn new(lint: &LintInfo, applicabilities: &HashMap, configs: &[ClippyConfiguration]) -> Self { + let name = lint.name_lower(); + let applicability = applicabilities + .get(&name) + .cloned() + .unwrap_or(Applicability::Unspecified); + let past_names = RENAMED + .iter() + .filter(|(_, new_name)| new_name.strip_prefix("clippy::") == Some(&name)) + .map(|(old_name, _)| old_name.strip_prefix("clippy::").unwrap()) + .collect::>(); + let mut docs = lint.explanation.to_string(); + if !past_names.is_empty() { + docs.push_str("\n### Past names\n\n"); + for past_name in past_names { + writeln!(&mut docs, " * {past_name}").unwrap(); + } + } + let configs: Vec<_> = configs + .iter() + .filter(|conf| conf.lints.contains(&name.as_str())) + .collect(); + if !configs.is_empty() { + docs.push_str("\n### Configuration\n\n"); + for config in configs { + writeln!(&mut docs, "{config}").unwrap(); + } + } + Self { + id: name, + id_location: Some(lint.location), + group: lint.category_str(), + level: lint.lint.default_level.as_str(), + docs, + version: lint.version.unwrap(), + applicability, + } + } + + fn new_deprecated(name: &str, reason: &str, version: &'static str) -> Self { + // The reason starts with a lowercase letter and ends without a period. + // This needs to be fixed for the website. + let mut reason = reason.to_owned(); + if let Some(reason) = reason.get_mut(0..1) { + reason.make_ascii_uppercase(); + } + Self { + id: name.strip_prefix("clippy::").unwrap().into(), + id_location: None, + group: "deprecated", + level: "none", + version, + docs: format!( + "### What it does\n\n\ + Nothing. This lint has been deprecated\n\n\ + ### Deprecation reason\n\n{reason}.\n", + ), + applicability: Applicability::Unspecified, + } + } +} diff --git a/src/tools/clippy/tests/config-metadata.rs b/src/tools/clippy/tests/config-metadata.rs new file mode 100644 index 00000000000..3e3711873ba --- /dev/null +++ b/src/tools/clippy/tests/config-metadata.rs @@ -0,0 +1,78 @@ +#![feature(rustc_private)] + +use clippy_config::{get_configuration_metadata, ClippyConfiguration}; +use itertools::Itertools; +use regex::Regex; +use std::borrow::Cow; +use std::{env, fs}; + +fn metadata() -> impl Iterator { + get_configuration_metadata() + .into_iter() + .filter(|config| config.deprecation_reason.is_none()) + .filter(|config| !config.lints.is_empty()) +} + +#[test] +fn book() { + let path = "book/src/lint_configuration.md"; + let current = fs::read_to_string(path).unwrap(); + + let configs = metadata().map(|conf| conf.to_markdown_paragraph()).join("\n"); + let expected = format!( + r#" + +# Lint Configuration Options + +The following list shows each configuration option, along with a description, its default value, an example +and lints affected. + +--- + +{} +"#, + configs.trim(), + ); + + if current != expected { + if env::var_os("RUSTC_BLESS").is_some_and(|v| v != "0") { + fs::write(path, expected).unwrap(); + } else { + panic!("`{path}` is out of date, run `cargo bless --test config-metadata` to update it"); + } + } +} + +#[test] +fn changelog() { + let path = "CHANGELOG.md"; + let current = fs::read_to_string(path).unwrap(); + + let configs = metadata().map(|conf| conf.to_markdown_link()).join("\n"); + + let re = Regex::new( + "(?s)\ + ()\ + .*\ + ()\ + ", + ) + .unwrap(); + let expected = re.replace(¤t, format!("$1\n{configs}\n$2")); + + assert!( + matches!(expected, Cow::Owned(_)), + "failed to find configuration section in `{path}`" + ); + + if current != expected { + if env::var_os("RUSTC_BLESS").is_some_and(|v| v != "0") { + fs::write(path, expected.as_bytes()).unwrap(); + } else { + panic!("`{path}` is out of date, run `cargo bless --test config-metadata` to update it"); + } + } +} diff --git a/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.allow_crates.stderr b/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.allow_crates.stderr index 1cc1034cd89..d24b0cd6162 100644 --- a/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.allow_crates.stderr +++ b/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.allow_crates.stderr @@ -1,29 +1,44 @@ error: consider bringing this path into scope with the `use` keyword - --> tests/ui-toml/absolute_paths/absolute_paths.rs:40:5 + --> tests/ui-toml/absolute_paths/absolute_paths.rs:14:13 | -LL | std::f32::MAX; - | ^^^^^^^^^^^^^ +LL | let _ = std::path::is_separator(' '); + | ^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D clippy::absolute-paths` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::absolute_paths)]` +note: the lint level is defined here + --> tests/ui-toml/absolute_paths/absolute_paths.rs:7:9 + | +LL | #![deny(clippy::absolute_paths)] + | ^^^^^^^^^^^^^^^^^^^^^^ error: consider bringing this path into scope with the `use` keyword - --> tests/ui-toml/absolute_paths/absolute_paths.rs:41:5 + --> tests/ui-toml/absolute_paths/absolute_paths.rs:20:13 | -LL | core::f32::MAX; - | ^^^^^^^^^^^^^^ +LL | let _ = ::std::path::MAIN_SEPARATOR; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: consider bringing this path into scope with the `use` keyword - --> tests/ui-toml/absolute_paths/absolute_paths.rs:42:5 + --> tests/ui-toml/absolute_paths/absolute_paths.rs:25:13 | -LL | ::core::f32::MAX; - | ^^^^^^^^^^^^^^^^ +LL | let _ = std::collections::hash_map::HashMap::::new(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: consider bringing this path into scope with the `use` keyword - --> tests/ui-toml/absolute_paths/absolute_paths.rs:58:5 + --> tests/ui-toml/absolute_paths/absolute_paths.rs:28:31 | -LL | ::std::f32::MAX; - | ^^^^^^^^^^^^^^^ +LL | let _: &std::path::Path = std::path::Path::new(""); + | ^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:28:13 + | +LL | let _: &std::path::Path = std::path::Path::new(""); + | ^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:43:13 + | +LL | let _ = std::option::Option::None::; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors diff --git a/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.allow_long.stderr b/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.allow_long.stderr new file mode 100644 index 00000000000..0cc6566af3a --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.allow_long.stderr @@ -0,0 +1,14 @@ +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:25:13 + | +LL | let _ = std::collections::hash_map::HashMap::::new(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> tests/ui-toml/absolute_paths/absolute_paths.rs:7:9 + | +LL | #![deny(clippy::absolute_paths)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.default.stderr b/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.default.stderr new file mode 100644 index 00000000000..53aa9030e0d --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.default.stderr @@ -0,0 +1,80 @@ +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:14:13 + | +LL | let _ = std::path::is_separator(' '); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> tests/ui-toml/absolute_paths/absolute_paths.rs:7:9 + | +LL | #![deny(clippy::absolute_paths)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:20:13 + | +LL | let _ = ::std::path::MAIN_SEPARATOR; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:25:13 + | +LL | let _ = std::collections::hash_map::HashMap::::new(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:28:31 + | +LL | let _: &std::path::Path = std::path::Path::new(""); + | ^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:28:13 + | +LL | let _: &std::path::Path = std::path::Path::new(""); + | ^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:37:13 + | +LL | let _ = ::core::clone::Clone::clone(&0i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:40:13 + | +LL | let _ = ::clone(&0i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:43:13 + | +LL | let _ = std::option::Option::None::; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:65:17 + | +LL | impl core::fmt::Display for X + | ^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:70:18 + | +LL | where T: core::clone::Clone + | ^^^^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:65:32 + | +LL | impl core::fmt::Display for X + | ^^^^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:116:5 + | +LL | crate::m1::S + | ^^^^^^^^^^^^ + +error: aborting due to 12 previous errors + diff --git a/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.disallow_crates.stderr b/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.disallow_crates.stderr deleted file mode 100644 index f342ebf6632..00000000000 --- a/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.disallow_crates.stderr +++ /dev/null @@ -1,71 +0,0 @@ -error: consider bringing this path into scope with the `use` keyword - --> tests/ui-toml/absolute_paths/absolute_paths.rs:40:5 - | -LL | std::f32::MAX; - | ^^^^^^^^^^^^^ - | - = note: `-D clippy::absolute-paths` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::absolute_paths)]` - -error: consider bringing this path into scope with the `use` keyword - --> tests/ui-toml/absolute_paths/absolute_paths.rs:41:5 - | -LL | core::f32::MAX; - | ^^^^^^^^^^^^^^ - -error: consider bringing this path into scope with the `use` keyword - --> tests/ui-toml/absolute_paths/absolute_paths.rs:42:5 - | -LL | ::core::f32::MAX; - | ^^^^^^^^^^^^^^^^ - -error: consider bringing this path into scope with the `use` keyword - --> tests/ui-toml/absolute_paths/absolute_paths.rs:43:5 - | -LL | crate::a::b::c::C; - | ^^^^^^^^^^^^^^^^^ - -error: consider bringing this path into scope with the `use` keyword - --> tests/ui-toml/absolute_paths/absolute_paths.rs:44:5 - | -LL | crate::a::b::c::d::e::f::F; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: consider bringing this path into scope with the `use` keyword - --> tests/ui-toml/absolute_paths/absolute_paths.rs:45:5 - | -LL | crate::a::A; - | ^^^^^^^^^^^ - -error: consider bringing this path into scope with the `use` keyword - --> tests/ui-toml/absolute_paths/absolute_paths.rs:46:5 - | -LL | crate::a::b::B; - | ^^^^^^^^^^^^^^ - -error: consider bringing this path into scope with the `use` keyword - --> tests/ui-toml/absolute_paths/absolute_paths.rs:47:5 - | -LL | crate::a::b::c::C::ZERO; - | ^^^^^^^^^^^^^^^^^ - -error: consider bringing this path into scope with the `use` keyword - --> tests/ui-toml/absolute_paths/absolute_paths.rs:48:5 - | -LL | helper::b::c::d::e::f(); - | ^^^^^^^^^^^^^^^^^^^^^ - -error: consider bringing this path into scope with the `use` keyword - --> tests/ui-toml/absolute_paths/absolute_paths.rs:49:5 - | -LL | ::helper::b::c::d::e::f(); - | ^^^^^^^^^^^^^^^^^^^^^^^ - -error: consider bringing this path into scope with the `use` keyword - --> tests/ui-toml/absolute_paths/absolute_paths.rs:58:5 - | -LL | ::std::f32::MAX; - | ^^^^^^^^^^^^^^^ - -error: aborting due to 11 previous errors - diff --git a/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.no_short.stderr b/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.no_short.stderr new file mode 100644 index 00000000000..70d71f6c4ea --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.no_short.stderr @@ -0,0 +1,98 @@ +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:14:13 + | +LL | let _ = std::path::is_separator(' '); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> tests/ui-toml/absolute_paths/absolute_paths.rs:7:9 + | +LL | #![deny(clippy::absolute_paths)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:20:13 + | +LL | let _ = ::std::path::MAIN_SEPARATOR; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:25:13 + | +LL | let _ = std::collections::hash_map::HashMap::::new(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:28:31 + | +LL | let _: &std::path::Path = std::path::Path::new(""); + | ^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:28:13 + | +LL | let _: &std::path::Path = std::path::Path::new(""); + | ^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:37:13 + | +LL | let _ = ::core::clone::Clone::clone(&0i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:40:13 + | +LL | let _ = ::clone(&0i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:43:13 + | +LL | let _ = std::option::Option::None::; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:65:17 + | +LL | impl core::fmt::Display for X + | ^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:70:18 + | +LL | where T: core::clone::Clone + | ^^^^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:65:32 + | +LL | impl core::fmt::Display for X + | ^^^^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:113:14 + | +LL | pub const _: crate::S = { + | ^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:114:9 + | +LL | let crate::S = m1::S; + | ^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:116:5 + | +LL | crate::m1::S + | ^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:122:14 + | +LL | let _ = ::clone(&m1::S); + | ^^^^^^^^ + +error: aborting due to 15 previous errors + diff --git a/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.rs b/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.rs index a828701bcee..c024f2f513c 100644 --- a/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.rs +++ b/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.rs @@ -1,97 +1,123 @@ //@aux-build:../../ui/auxiliary/proc_macros.rs -//@aux-build:helper.rs -//@revisions: allow_crates disallow_crates +//@revisions: default allow_crates allow_long no_short +//@[default] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/absolute_paths/default //@[allow_crates] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/absolute_paths/allow_crates -//@[disallow_crates] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/absolute_paths/disallow_crates -#![allow(clippy::no_effect, clippy::legacy_numeric_constants, unused)] -#![warn(clippy::absolute_paths)] -#![feature(decl_macro)] +//@[allow_long] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/absolute_paths/allow_long +//@[no_short] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/absolute_paths/no_short +#![deny(clippy::absolute_paths)] -extern crate helper; -#[macro_use] extern crate proc_macros; +use proc_macros::{external, inline_macros, with_span}; -pub mod a { - pub mod b { - pub mod c { - pub struct C; +#[inline_macros] +fn main() { + let _ = std::path::is_separator(' '); + //~[default]^ absolute_paths + //~[allow_crates]| absolute_paths + //~[no_short]| absolute_paths - impl C { - pub const ZERO: u32 = 0; - } + // Make sure this is treated as having three path segments, not four. + let _ = ::std::path::MAIN_SEPARATOR; + //~[default]^ absolute_paths + //~[allow_crates]| absolute_paths + //~[no_short]| absolute_paths - pub mod d { - pub mod e { - pub mod f { - pub struct F; - } - } + let _ = std::collections::hash_map::HashMap::::new(); //~ absolute_paths + + // Note `std::path::Path::new` is treated as having three parts + let _: &std::path::Path = std::path::Path::new(""); + //~[default]^ absolute_paths + //~[default]| absolute_paths + //~[allow_crates]| absolute_paths + //~[allow_crates]| absolute_paths + //~[no_short]| absolute_paths + //~[no_short]| absolute_paths + + // Treated as having three parts. + let _ = ::core::clone::Clone::clone(&0i32); + //~[default]^ absolute_paths + //~[no_short]| absolute_paths + let _ = ::clone(&0i32); + //~[default]^ absolute_paths + //~[no_short]| absolute_paths + let _ = std::option::Option::None::; + //~[default]^ absolute_paths + //~[allow_crates]| absolute_paths + //~[no_short]| absolute_paths + + { + // FIXME: macro calls should be checked. + let x = 1i32; + let _ = core::ptr::addr_of!(x); + } + + { + // FIXME: derive macro paths should be checked. + #[derive(core::clone::Clone)] + struct S; + } + + { + use core::fmt; + use core::marker::PhantomData; + + struct X(PhantomData); + impl core::fmt::Display for X + //~[default]^ absolute_paths + //~[default]| absolute_paths + //~[no_short]| absolute_paths + //~[no_short]| absolute_paths + where T: core::clone::Clone + //~[no_short]^ absolute_paths + //~[default]| absolute_paths + { + fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result { + Ok(()) } } - - pub struct B; } - pub struct A; -} + { + mod m1 { + pub(crate) mod m2 { + pub(crate) const FOO: i32 = 0; + } + } + let _ = m1::m2::FOO; + } -fn main() { - f32::max(1.0, 2.0); - std::f32::MAX; - core::f32::MAX; - ::core::f32::MAX; - crate::a::b::c::C; - crate::a::b::c::d::e::f::F; - crate::a::A; - crate::a::b::B; - crate::a::b::c::C::ZERO; - helper::b::c::d::e::f(); - ::helper::b::c::d::e::f(); - fn b() -> a::b::B { - todo!() - } - std::println!("a"); - let x = 1; - std::ptr::addr_of!(x); - // Test we handle max segments with `PathRoot` properly; this has 4 segments but we should say it - // has 3 - ::std::f32::MAX; - // Do not lint due to the above - ::helper::a(); - // Do not lint - helper::a(); - use crate::a::b::c::C; - use a::b; - use std::f32::MAX; - a::b::c::d::e::f::F; - b::c::C; - fn a() -> a::A { - todo!() - } - use a::b::c; - - fn c() -> c::C { - todo!() - } - fn d() -> Result<(), ()> { - todo!() - } - external! { - crate::a::b::c::C::ZERO; - } - // For some reason, `path.span.from_expansion()` takes care of this for us with_span! { span - crate::a::b::c::C::ZERO; + let _ = std::path::is_separator(' '); } - macro_rules! local_crate { - () => { - crate::a::b::c::C::ZERO; - }; + + external! { + let _ = std::path::is_separator(' '); } - macro local_crate_2_0() { - crate::a::b::c::C::ZERO; + + inline! { + let _ = std::path::is_separator(' '); } - local_crate!(); - local_crate_2_0!(); +} + +pub use core::cmp::Ordering; +pub use std::fs::File; + +#[derive(Clone)] +pub struct S; +mod m1 { + pub use crate::S; +} + +//~[no_short]v absolute_paths +pub const _: crate::S = { + let crate::S = m1::S; //~[no_short] absolute_paths + + crate::m1::S + //~[default]^ absolute_paths + //~[no_short]| absolute_paths +}; + +pub fn f() { + let _ = ::clone(&m1::S); //~[no_short] absolute_paths } diff --git a/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths_2015.default.stderr b/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths_2015.default.stderr new file mode 100644 index 00000000000..6fc495f0180 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths_2015.default.stderr @@ -0,0 +1,14 @@ +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths_2015.rs:15:13 + | +LL | let _ = ::m1::m2::X; + | ^^^^^^^^^^^ + | +note: the lint level is defined here + --> tests/ui-toml/absolute_paths/absolute_paths_2015.rs:6:9 + | +LL | #![deny(clippy::absolute_paths)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths_2015.rs b/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths_2015.rs new file mode 100644 index 00000000000..033c4780919 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths_2015.rs @@ -0,0 +1,16 @@ +//@revisions: default allow_crates +//@[default]rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/absolute_paths/default +//@[allow_crates]rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/absolute_paths/allow_crates +//@edition:2015 + +#![deny(clippy::absolute_paths)] + +mod m1 { + pub mod m2 { + pub struct X; + } +} + +fn main() { + let _ = ::m1::m2::X; //~[default] absolute_paths +} diff --git a/src/tools/clippy/tests/ui-toml/absolute_paths/allow_crates/clippy.toml b/src/tools/clippy/tests/ui-toml/absolute_paths/allow_crates/clippy.toml index 59a621e9d1d..9da49abcd31 100644 --- a/src/tools/clippy/tests/ui-toml/absolute_paths/allow_crates/clippy.toml +++ b/src/tools/clippy/tests/ui-toml/absolute_paths/allow_crates/clippy.toml @@ -1,2 +1 @@ -absolute-paths-max-segments = 2 -absolute-paths-allowed-crates = ["crate", "helper"] +absolute-paths-allowed-crates = ["core", "crate"] diff --git a/src/tools/clippy/tests/ui-toml/absolute_paths/allow_long/clippy.toml b/src/tools/clippy/tests/ui-toml/absolute_paths/allow_long/clippy.toml new file mode 100644 index 00000000000..5992fd1ed82 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/absolute_paths/allow_long/clippy.toml @@ -0,0 +1 @@ +absolute-paths-max-segments = 3 diff --git a/src/tools/clippy/tests/ui-toml/absolute_paths/auxiliary/helper.rs b/src/tools/clippy/tests/ui-toml/absolute_paths/auxiliary/helper.rs deleted file mode 100644 index 8e2678f5fe6..00000000000 --- a/src/tools/clippy/tests/ui-toml/absolute_paths/auxiliary/helper.rs +++ /dev/null @@ -1,11 +0,0 @@ -pub fn a() {} - -pub mod b { - pub mod c { - pub mod d { - pub mod e { - pub fn f() {} - } - } - } -} diff --git a/src/tools/clippy/tests/ui-toml/absolute_paths/default/clippy.toml b/src/tools/clippy/tests/ui-toml/absolute_paths/default/clippy.toml new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/tools/clippy/tests/ui-toml/absolute_paths/disallow_crates/clippy.toml b/src/tools/clippy/tests/ui-toml/absolute_paths/disallow_crates/clippy.toml deleted file mode 100644 index d44d648c641..00000000000 --- a/src/tools/clippy/tests/ui-toml/absolute_paths/disallow_crates/clippy.toml +++ /dev/null @@ -1 +0,0 @@ -absolute-paths-max-segments = 2 diff --git a/src/tools/clippy/tests/ui-toml/absolute_paths/no_short/clippy.toml b/src/tools/clippy/tests/ui-toml/absolute_paths/no_short/clippy.toml new file mode 100644 index 00000000000..357524420c5 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/absolute_paths/no_short/clippy.toml @@ -0,0 +1 @@ +absolute-paths-max-segments = 0 diff --git a/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs b/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs index a312df5a43a..3dafea56514 100644 --- a/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs +++ b/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs @@ -1,7 +1,7 @@ //! Tests macro_metavars_in_unsafe with default configuration #![feature(decl_macro)] #![warn(clippy::macro_metavars_in_unsafe)] -#![allow(clippy::no_effect)] +#![allow(clippy::no_effect, clippy::not_unsafe_ptr_arg_deref)] #[macro_export] macro_rules! allow_works { @@ -237,6 +237,19 @@ macro_rules! nested_macros { }}; } +pub mod issue13219 { + #[macro_export] + macro_rules! m { + ($e:expr) => { + // Metavariable in a block tail expression + unsafe { $e } + }; + } + pub fn f(p: *const i32) -> i32 { + m!(*p) + } +} + fn main() { allow_works!(1); simple!(1); diff --git a/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.stderr b/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.stderr index d6b97f6fde1..6f0ebcbba02 100644 --- a/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.stderr +++ b/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.stderr @@ -1,3 +1,15 @@ +error: this macro expands metavariables in an unsafe block + --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:245:13 + | +LL | unsafe { $e } + | ^^^^^^^^^^^^^ + | + = note: this allows the user of the macro to write unsafe code outside of an unsafe block + = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable + = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite + = note: `-D clippy::macro-metavars-in-unsafe` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::macro_metavars_in_unsafe)]` + error: this macro expands metavariables in an unsafe block --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:19:9 | @@ -10,8 +22,6 @@ LL | | } = note: this allows the user of the macro to write unsafe code outside of an unsafe block = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite - = note: `-D clippy::macro-metavars-in-unsafe` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::macro_metavars_in_unsafe)]` error: this macro expands metavariables in an unsafe block --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:30:9 @@ -183,5 +193,5 @@ LL | | } = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite -error: aborting due to 14 previous errors +error: aborting due to 15 previous errors diff --git a/src/tools/clippy/tests/ui/assigning_clones.fixed b/src/tools/clippy/tests/ui/assigning_clones.fixed index b376d55a402..09732d1a50c 100644 --- a/src/tools/clippy/tests/ui/assigning_clones.fixed +++ b/src/tools/clippy/tests/ui/assigning_clones.fixed @@ -396,3 +396,23 @@ impl Clone for DerefWrapperWithClone { *self = Self(source.0.clone()); } } + +#[cfg(test)] +mod test { + #[derive(Default)] + struct Data { + field: String, + } + + fn test_data() -> Data { + Data { + field: "default_value".to_string(), + } + } + + #[test] + fn test() { + let mut data = test_data(); + data.field = "override_value".to_owned(); + } +} diff --git a/src/tools/clippy/tests/ui/assigning_clones.rs b/src/tools/clippy/tests/ui/assigning_clones.rs index 11a5d4459c3..6be25ae17a5 100644 --- a/src/tools/clippy/tests/ui/assigning_clones.rs +++ b/src/tools/clippy/tests/ui/assigning_clones.rs @@ -396,3 +396,23 @@ impl Clone for DerefWrapperWithClone { *self = Self(source.0.clone()); } } + +#[cfg(test)] +mod test { + #[derive(Default)] + struct Data { + field: String, + } + + fn test_data() -> Data { + Data { + field: "default_value".to_string(), + } + } + + #[test] + fn test() { + let mut data = test_data(); + data.field = "override_value".to_owned(); + } +} diff --git a/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals_nested.stderr b/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals_nested.stderr index f7e659b10de..329be4d3662 100644 --- a/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals_nested.stderr +++ b/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals_nested.stderr @@ -2,7 +2,7 @@ error: called `unwrap` on `x` after checking its variant with `is_some` --> tests/ui/checked_unwrap/complex_conditionals_nested.rs:13:13 | LL | if x.is_some() { - | -------------- help: try: `if let Some(..) = x` + | -------------- help: try: `if let Some() = x` LL | // unnecessary LL | x.unwrap(); | ^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr index ddd600418af..f7e338935a7 100644 --- a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr +++ b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr @@ -2,7 +2,7 @@ error: called `unwrap` on `x` after checking its variant with `is_some` --> tests/ui/checked_unwrap/simple_conditionals.rs:46:9 | LL | if x.is_some() { - | -------------- help: try: `if let Some(..) = x` + | -------------- help: try: `if let Some() = x` LL | // unnecessary LL | x.unwrap(); | ^^^^^^^^^^ @@ -17,7 +17,7 @@ error: called `expect` on `x` after checking its variant with `is_some` --> tests/ui/checked_unwrap/simple_conditionals.rs:49:9 | LL | if x.is_some() { - | -------------- help: try: `if let Some(..) = x` + | -------------- help: try: `if let Some() = x` ... LL | x.expect("an error message"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -59,7 +59,7 @@ error: called `unwrap` on `x` after checking its variant with `is_none` --> tests/ui/checked_unwrap/simple_conditionals.rs:65:9 | LL | if x.is_none() { - | -------------- help: try: `if let Some(..) = x` + | -------------- help: try: `if let Some() = x` ... LL | x.unwrap(); | ^^^^^^^^^^ @@ -68,7 +68,7 @@ error: called `unwrap` on `x` after checking its variant with `is_some` --> tests/ui/checked_unwrap/simple_conditionals.rs:13:13 | LL | if $a.is_some() { - | --------------- help: try: `if let Some(..) = x` + | --------------- help: try: `if let Some() = x` LL | // unnecessary LL | $a.unwrap(); | ^^^^^^^^^^^ @@ -82,7 +82,7 @@ error: called `unwrap` on `x` after checking its variant with `is_ok` --> tests/ui/checked_unwrap/simple_conditionals.rs:78:9 | LL | if x.is_ok() { - | ------------ help: try: `if let Ok(..) = x` + | ------------ help: try: `if let Ok() = x` LL | // unnecessary LL | x.unwrap(); | ^^^^^^^^^^ @@ -91,7 +91,7 @@ error: called `expect` on `x` after checking its variant with `is_ok` --> tests/ui/checked_unwrap/simple_conditionals.rs:81:9 | LL | if x.is_ok() { - | ------------ help: try: `if let Ok(..) = x` + | ------------ help: try: `if let Ok() = x` ... LL | x.expect("an error message"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -127,7 +127,7 @@ error: called `unwrap_err` on `x` after checking its variant with `is_ok` --> tests/ui/checked_unwrap/simple_conditionals.rs:94:9 | LL | if x.is_ok() { - | ------------ help: try: `if let Err(..) = x` + | ------------ help: try: `if let Err() = x` ... LL | x.unwrap_err(); | ^^^^^^^^^^^^^^ @@ -145,7 +145,7 @@ error: called `unwrap_err` on `x` after checking its variant with `is_err` --> tests/ui/checked_unwrap/simple_conditionals.rs:102:9 | LL | if x.is_err() { - | ------------- help: try: `if let Err(..) = x` + | ------------- help: try: `if let Err() = x` ... LL | x.unwrap_err(); | ^^^^^^^^^^^^^^ @@ -154,7 +154,7 @@ error: called `unwrap` on `x` after checking its variant with `is_err` --> tests/ui/checked_unwrap/simple_conditionals.rs:106:9 | LL | if x.is_err() { - | ------------- help: try: `if let Ok(..) = x` + | ------------- help: try: `if let Ok() = x` ... LL | x.unwrap(); | ^^^^^^^^^^ @@ -172,7 +172,7 @@ error: called `unwrap` on `option` after checking its variant with `is_some` --> tests/ui/checked_unwrap/simple_conditionals.rs:134:9 | LL | if option.is_some() { - | ------------------- help: try: `if let Some(..) = &option` + | ------------------- help: try: `if let Some() = &option` LL | option.as_ref().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -189,7 +189,7 @@ error: called `unwrap` on `result` after checking its variant with `is_ok` --> tests/ui/checked_unwrap/simple_conditionals.rs:144:9 | LL | if result.is_ok() { - | ----------------- help: try: `if let Ok(..) = &result` + | ----------------- help: try: `if let Ok() = &result` LL | result.as_ref().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -206,7 +206,7 @@ error: called `unwrap` on `option` after checking its variant with `is_some` --> tests/ui/checked_unwrap/simple_conditionals.rs:153:9 | LL | if option.is_some() { - | ------------------- help: try: `if let Some(..) = &mut option` + | ------------------- help: try: `if let Some() = &mut option` LL | option.as_mut().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -223,7 +223,7 @@ error: called `unwrap` on `result` after checking its variant with `is_ok` --> tests/ui/checked_unwrap/simple_conditionals.rs:162:9 | LL | if result.is_ok() { - | ----------------- help: try: `if let Ok(..) = &mut result` + | ----------------- help: try: `if let Ok() = &mut result` LL | result.as_mut().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/collapsible_match.stderr b/src/tools/clippy/tests/ui/collapsible_match.stderr index 01944baee79..1da78b56239 100644 --- a/src/tools/clippy/tests/ui/collapsible_match.stderr +++ b/src/tools/clippy/tests/ui/collapsible_match.stderr @@ -223,7 +223,7 @@ help: the outer pattern can be modified to include the inner pattern LL | if let Issue9647::A { a, .. } = x { | ^ replace this binding LL | if let Some(u) = a { - | ^^^^^^^ with this pattern, prefixed by a: + | ^^^^^^^ with this pattern, prefixed by `a`: error: this `if let` can be collapsed into the outer `if let` --> tests/ui/collapsible_match.rs:292:9 diff --git a/src/tools/clippy/tests/ui/crashes/ice-3717.fixed b/src/tools/clippy/tests/ui/crashes/ice-3717.fixed new file mode 100644 index 00000000000..3f54b326979 --- /dev/null +++ b/src/tools/clippy/tests/ui/crashes/ice-3717.fixed @@ -0,0 +1,11 @@ +#![deny(clippy::implicit_hasher)] + +use std::collections::HashSet; + +fn main() {} + +pub fn ice_3717(_: &HashSet) { + //~^ ERROR: parameter of type `HashSet` should be generalized over different hashers + let _ = [0u8; 0]; + let _: HashSet = HashSet::default(); +} diff --git a/src/tools/clippy/tests/ui/crashes/ice-3717.rs b/src/tools/clippy/tests/ui/crashes/ice-3717.rs index 770f6cf448a..2890a9277c7 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-3717.rs +++ b/src/tools/clippy/tests/ui/crashes/ice-3717.rs @@ -1,7 +1,5 @@ #![deny(clippy::implicit_hasher)] -//@no-rustfix: need to change the suggestion to a multipart suggestion - use std::collections::HashSet; fn main() {} diff --git a/src/tools/clippy/tests/ui/crashes/ice-3717.stderr b/src/tools/clippy/tests/ui/crashes/ice-3717.stderr index 4b4618ee1bb..aac72c66965 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-3717.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-3717.stderr @@ -1,5 +1,5 @@ error: parameter of type `HashSet` should be generalized over different hashers - --> tests/ui/crashes/ice-3717.rs:9:21 + --> tests/ui/crashes/ice-3717.rs:7:21 | LL | pub fn ice_3717(_: &HashSet) { | ^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.rs b/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.rs index 56a8d22cb1c..9dafad8b784 100644 --- a/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.rs +++ b/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.rs @@ -3,6 +3,7 @@ use std::borrow::Cow; use std::cell::Cell; use std::fmt::Display; +use std::ptr; use std::sync::atomic::AtomicUsize; use std::sync::Once; @@ -53,4 +54,20 @@ mod issue_8493 { issue_8493!(); } +#[repr(C, align(8))] +struct NoAtomic(usize); +#[repr(C, align(8))] +struct WithAtomic(AtomicUsize); + +const fn with_non_null() -> *const WithAtomic { + const NO_ATOMIC: NoAtomic = NoAtomic(0); + (&NO_ATOMIC as *const NoAtomic).cast() +} +const WITH_ATOMIC: *const WithAtomic = with_non_null(); + +struct Generic(T); +impl Generic { + const RAW_POINTER: *const Cell = ptr::null(); +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.stderr b/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.stderr index 1f2b9561ce5..4a725147142 100644 --- a/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.stderr +++ b/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.stderr @@ -1,5 +1,5 @@ error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/others.rs:9:1 + --> tests/ui/declare_interior_mutable_const/others.rs:10:1 | LL | const ATOMIC: AtomicUsize = AtomicUsize::new(5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | const ATOMIC: AtomicUsize = AtomicUsize::new(5); = help: to override `-D warnings` add `#[allow(clippy::declare_interior_mutable_const)]` error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/others.rs:10:1 + --> tests/ui/declare_interior_mutable_const/others.rs:11:1 | LL | const CELL: Cell = Cell::new(6); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | const CELL: Cell = Cell::new(6); = help: consider making this `Sync` so that it can go in a static item or using a `thread_local` error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/others.rs:11:1 + --> tests/ui/declare_interior_mutable_const/others.rs:12:1 | LL | const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec, u8) = ([ATOMIC], Vec::new(), 7); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec, u8) = ([ATOMIC], V = help: consider making this a static item error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/others.rs:16:9 + --> tests/ui/declare_interior_mutable_const/others.rs:17:9 | LL | const $name: $ty = $e; | ^^^^^^^^^^^^^^^^^^^^^^ @@ -36,7 +36,7 @@ LL | declare_const!(_ONCE: Once = Once::new()); = note: this error originates in the macro `declare_const` (in Nightly builds, run with -Z macro-backtrace for more info) error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/others.rs:44:13 + --> tests/ui/declare_interior_mutable_const/others.rs:45:13 | LL | const _BAZ: Cell = Cell::new(0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.fixed b/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.fixed new file mode 100644 index 00000000000..fb0f40b34a4 --- /dev/null +++ b/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.fixed @@ -0,0 +1,13 @@ +// This test checks that words starting with capital letters and ending with "ified" don't +// trigger the lint. + +#![deny(clippy::doc_markdown)] + +pub enum OutputFormat { + /// `HumaNified` + //~^ ERROR: item in documentation is missing backticks + Plain, + // Should not warn! + /// JSONified console output + Json, +} diff --git a/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.rs b/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.rs new file mode 100644 index 00000000000..8c1e1a3cd6c --- /dev/null +++ b/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.rs @@ -0,0 +1,13 @@ +// This test checks that words starting with capital letters and ending with "ified" don't +// trigger the lint. + +#![deny(clippy::doc_markdown)] + +pub enum OutputFormat { + /// HumaNified + //~^ ERROR: item in documentation is missing backticks + Plain, + // Should not warn! + /// JSONified console output + Json, +} diff --git a/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.stderr b/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.stderr new file mode 100644 index 00000000000..ae68a767ec9 --- /dev/null +++ b/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.stderr @@ -0,0 +1,18 @@ +error: item in documentation is missing backticks + --> tests/ui/doc/doc_markdown-issue_13097.rs:7:9 + | +LL | /// HumaNified + | ^^^^^^^^^^ + | +note: the lint level is defined here + --> tests/ui/doc/doc_markdown-issue_13097.rs:4:9 + | +LL | #![deny(clippy::doc_markdown)] + | ^^^^^^^^^^^^^^^^^^^^ +help: try + | +LL | /// `HumaNified` + | ~~~~~~~~~~~~ + +error: aborting due to 1 previous error + diff --git a/src/tools/clippy/tests/ui/double_must_use.rs b/src/tools/clippy/tests/ui/double_must_use.rs index 615de3e2474..4460aeb075b 100644 --- a/src/tools/clippy/tests/ui/double_must_use.rs +++ b/src/tools/clippy/tests/ui/double_must_use.rs @@ -3,19 +3,19 @@ #[must_use] pub fn must_use_result() -> Result<(), ()> { - //~^ ERROR: this function has an empty `#[must_use]` attribute, but returns a type already + //~^ ERROR: this function has a `#[must_use]` attribute with no message, but returns a type already unimplemented!(); } #[must_use] pub fn must_use_tuple() -> (Result<(), ()>, u8) { - //~^ ERROR: this function has an empty `#[must_use]` attribute, but returns a type already + //~^ ERROR: this function has a `#[must_use]` attribute with no message, but returns a type already unimplemented!(); } #[must_use] pub fn must_use_array() -> [Result<(), ()>; 1] { - //~^ ERROR: this function has an empty `#[must_use]` attribute, but returns a type already + //~^ ERROR: this function has a `#[must_use]` attribute with no message, but returns a type already unimplemented!(); } @@ -32,7 +32,7 @@ async fn async_must_use() -> usize { #[must_use] async fn async_must_use_result() -> Result<(), ()> { - //~^ ERROR: this function has an empty `#[must_use]` attribute, but returns a type already + //~^ ERROR: this function has a `#[must_use]` attribute with no message, but returns a type already Ok(()) } diff --git a/src/tools/clippy/tests/ui/double_must_use.stderr b/src/tools/clippy/tests/ui/double_must_use.stderr index 0f2154ecbcf..b26d1e48a8b 100644 --- a/src/tools/clippy/tests/ui/double_must_use.stderr +++ b/src/tools/clippy/tests/ui/double_must_use.stderr @@ -1,36 +1,36 @@ -error: this function has an empty `#[must_use]` attribute, but returns a type already marked as `#[must_use]` +error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]` --> tests/ui/double_must_use.rs:5:1 | LL | pub fn must_use_result() -> Result<(), ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: either add some descriptive text or remove the attribute + = help: either add some descriptive message or remove the attribute = note: `-D clippy::double-must-use` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::double_must_use)]` -error: this function has an empty `#[must_use]` attribute, but returns a type already marked as `#[must_use]` +error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]` --> tests/ui/double_must_use.rs:11:1 | LL | pub fn must_use_tuple() -> (Result<(), ()>, u8) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: either add some descriptive text or remove the attribute + = help: either add some descriptive message or remove the attribute -error: this function has an empty `#[must_use]` attribute, but returns a type already marked as `#[must_use]` +error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]` --> tests/ui/double_must_use.rs:17:1 | LL | pub fn must_use_array() -> [Result<(), ()>; 1] { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: either add some descriptive text or remove the attribute + = help: either add some descriptive message or remove the attribute -error: this function has an empty `#[must_use]` attribute, but returns a type already marked as `#[must_use]` +error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]` --> tests/ui/double_must_use.rs:34:1 | LL | async fn async_must_use_result() -> Result<(), ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: either add some descriptive text or remove the attribute + = help: either add some descriptive message or remove the attribute error: aborting due to 4 previous errors diff --git a/src/tools/clippy/tests/ui/explicit_iter_loop.fixed b/src/tools/clippy/tests/ui/explicit_iter_loop.fixed index f38b34c5a7c..1148f0f6c6a 100644 --- a/src/tools/clippy/tests/ui/explicit_iter_loop.fixed +++ b/src/tools/clippy/tests/ui/explicit_iter_loop.fixed @@ -153,3 +153,15 @@ fn main() { let r = &x; for _ in r {} } + +#[clippy::msrv = "1.79"] +pub fn issue_13184() { + // https://github.com/rust-lang/rust-clippy/issues/13184 + // No need to fix, as IntoIterator for Box is valid starting from 1.80 + let mut values: Box<[u32]> = Box::new([1, 2]); + for _ in values.iter() {} + for _ in values.iter_mut() {} + + let rvalues = &values; + for _ in rvalues.iter() {} +} diff --git a/src/tools/clippy/tests/ui/explicit_iter_loop.rs b/src/tools/clippy/tests/ui/explicit_iter_loop.rs index 2e701ada5ac..4dda2f13e5b 100644 --- a/src/tools/clippy/tests/ui/explicit_iter_loop.rs +++ b/src/tools/clippy/tests/ui/explicit_iter_loop.rs @@ -153,3 +153,15 @@ fn main() { let r = &x; for _ in r.iter() {} } + +#[clippy::msrv = "1.79"] +pub fn issue_13184() { + // https://github.com/rust-lang/rust-clippy/issues/13184 + // No need to fix, as IntoIterator for Box is valid starting from 1.80 + let mut values: Box<[u32]> = Box::new([1, 2]); + for _ in values.iter() {} + for _ in values.iter_mut() {} + + let rvalues = &values; + for _ in rvalues.iter() {} +} diff --git a/src/tools/clippy/tests/ui/floating_point_abs.fixed b/src/tools/clippy/tests/ui/floating_point_abs.fixed index 5312a8b29c6..33183c76972 100644 --- a/src/tools/clippy/tests/ui/floating_point_abs.fixed +++ b/src/tools/clippy/tests/ui/floating_point_abs.fixed @@ -1,4 +1,3 @@ -#![feature(const_fn_floating_point_arithmetic)] #![warn(clippy::suboptimal_flops)] /// Allow suboptimal ops in constant context diff --git a/src/tools/clippy/tests/ui/floating_point_abs.rs b/src/tools/clippy/tests/ui/floating_point_abs.rs index 8619177130c..a08d5bbcef5 100644 --- a/src/tools/clippy/tests/ui/floating_point_abs.rs +++ b/src/tools/clippy/tests/ui/floating_point_abs.rs @@ -1,4 +1,3 @@ -#![feature(const_fn_floating_point_arithmetic)] #![warn(clippy::suboptimal_flops)] /// Allow suboptimal ops in constant context diff --git a/src/tools/clippy/tests/ui/floating_point_abs.stderr b/src/tools/clippy/tests/ui/floating_point_abs.stderr index f5a778c5b76..0c1f68f3b7f 100644 --- a/src/tools/clippy/tests/ui/floating_point_abs.stderr +++ b/src/tools/clippy/tests/ui/floating_point_abs.stderr @@ -1,5 +1,5 @@ error: manual implementation of `abs` method - --> tests/ui/floating_point_abs.rs:15:5 + --> tests/ui/floating_point_abs.rs:14:5 | LL | if num >= 0.0 { num } else { -num } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.abs()` @@ -8,43 +8,43 @@ LL | if num >= 0.0 { num } else { -num } = help: to override `-D warnings` add `#[allow(clippy::suboptimal_flops)]` error: manual implementation of `abs` method - --> tests/ui/floating_point_abs.rs:19:5 + --> tests/ui/floating_point_abs.rs:18:5 | LL | if 0.0 < num { num } else { -num } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.abs()` error: manual implementation of `abs` method - --> tests/ui/floating_point_abs.rs:23:5 + --> tests/ui/floating_point_abs.rs:22:5 | LL | if a.a > 0.0 { a.a } else { -a.a } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.a.abs()` error: manual implementation of `abs` method - --> tests/ui/floating_point_abs.rs:27:5 + --> tests/ui/floating_point_abs.rs:26:5 | LL | if 0.0 >= num { -num } else { num } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.abs()` error: manual implementation of `abs` method - --> tests/ui/floating_point_abs.rs:31:5 + --> tests/ui/floating_point_abs.rs:30:5 | LL | if a.a < 0.0 { -a.a } else { a.a } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.a.abs()` error: manual implementation of negation of `abs` method - --> tests/ui/floating_point_abs.rs:35:5 + --> tests/ui/floating_point_abs.rs:34:5 | LL | if num < 0.0 { num } else { -num } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-num.abs()` error: manual implementation of negation of `abs` method - --> tests/ui/floating_point_abs.rs:39:5 + --> tests/ui/floating_point_abs.rs:38:5 | LL | if 0.0 >= num { num } else { -num } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-num.abs()` error: manual implementation of negation of `abs` method - --> tests/ui/floating_point_abs.rs:44:12 + --> tests/ui/floating_point_abs.rs:43:12 | LL | a: if a.a >= 0.0 { -a.a } else { a.a }, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-a.a.abs()` diff --git a/src/tools/clippy/tests/ui/floating_point_mul_add.fixed b/src/tools/clippy/tests/ui/floating_point_mul_add.fixed index 3ce2edf2c71..164aac2601a 100644 --- a/src/tools/clippy/tests/ui/floating_point_mul_add.fixed +++ b/src/tools/clippy/tests/ui/floating_point_mul_add.fixed @@ -1,4 +1,3 @@ -#![feature(const_fn_floating_point_arithmetic)] #![warn(clippy::suboptimal_flops)] /// Allow suboptimal_ops in constant context diff --git a/src/tools/clippy/tests/ui/floating_point_mul_add.rs b/src/tools/clippy/tests/ui/floating_point_mul_add.rs index b5e4a8db4db..ae024b7f224 100644 --- a/src/tools/clippy/tests/ui/floating_point_mul_add.rs +++ b/src/tools/clippy/tests/ui/floating_point_mul_add.rs @@ -1,4 +1,3 @@ -#![feature(const_fn_floating_point_arithmetic)] #![warn(clippy::suboptimal_flops)] /// Allow suboptimal_ops in constant context diff --git a/src/tools/clippy/tests/ui/floating_point_mul_add.stderr b/src/tools/clippy/tests/ui/floating_point_mul_add.stderr index 3e1a071de73..9c75909f715 100644 --- a/src/tools/clippy/tests/ui/floating_point_mul_add.stderr +++ b/src/tools/clippy/tests/ui/floating_point_mul_add.stderr @@ -1,5 +1,5 @@ error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:20:13 + --> tests/ui/floating_point_mul_add.rs:19:13 | LL | let _ = a * b + c; | ^^^^^^^^^ help: consider using: `a.mul_add(b, c)` @@ -8,73 +8,73 @@ LL | let _ = a * b + c; = help: to override `-D warnings` add `#[allow(clippy::suboptimal_flops)]` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:21:13 + --> tests/ui/floating_point_mul_add.rs:20:13 | LL | let _ = a * b - c; | ^^^^^^^^^ help: consider using: `a.mul_add(b, -c)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:22:13 + --> tests/ui/floating_point_mul_add.rs:21:13 | LL | let _ = c + a * b; | ^^^^^^^^^ help: consider using: `a.mul_add(b, c)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:23:13 + --> tests/ui/floating_point_mul_add.rs:22:13 | LL | let _ = c - a * b; | ^^^^^^^^^ help: consider using: `a.mul_add(-b, c)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:24:13 + --> tests/ui/floating_point_mul_add.rs:23:13 | LL | let _ = a + 2.0 * 4.0; | ^^^^^^^^^^^^^ help: consider using: `2.0f64.mul_add(4.0, a)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:25:13 + --> tests/ui/floating_point_mul_add.rs:24:13 | LL | let _ = a + 2. * 4.; | ^^^^^^^^^^^ help: consider using: `2.0f64.mul_add(4., a)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:27:13 + --> tests/ui/floating_point_mul_add.rs:26:13 | LL | let _ = (a * b) + c; | ^^^^^^^^^^^ help: consider using: `a.mul_add(b, c)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:28:13 + --> tests/ui/floating_point_mul_add.rs:27:13 | LL | let _ = c + (a * b); | ^^^^^^^^^^^ help: consider using: `a.mul_add(b, c)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:29:13 + --> tests/ui/floating_point_mul_add.rs:28:13 | LL | let _ = a * b * c + d; | ^^^^^^^^^^^^^ help: consider using: `(a * b).mul_add(c, d)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:31:13 + --> tests/ui/floating_point_mul_add.rs:30:13 | LL | let _ = a.mul_add(b, c) * a.mul_add(b, c) + a.mul_add(b, c) + c; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `a.mul_add(b, c).mul_add(a.mul_add(b, c), a.mul_add(b, c))` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:32:13 + --> tests/ui/floating_point_mul_add.rs:31:13 | LL | let _ = 1234.567_f64 * 45.67834_f64 + 0.0004_f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1234.567_f64.mul_add(45.67834_f64, 0.0004_f64)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:34:13 + --> tests/ui/floating_point_mul_add.rs:33:13 | LL | let _ = (a * a + b).sqrt(); | ^^^^^^^^^^^ help: consider using: `a.mul_add(a, b)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:37:13 + --> tests/ui/floating_point_mul_add.rs:36:13 | LL | let _ = a - (b * u as f64); | ^^^^^^^^^^^^^^^^^^ help: consider using: `b.mul_add(-(u as f64), a)` diff --git a/src/tools/clippy/tests/ui/floating_point_rad.fixed b/src/tools/clippy/tests/ui/floating_point_rad.fixed index a710bd9bd60..2f93d233cb4 100644 --- a/src/tools/clippy/tests/ui/floating_point_rad.fixed +++ b/src/tools/clippy/tests/ui/floating_point_rad.fixed @@ -1,4 +1,3 @@ -#![feature(const_fn_floating_point_arithmetic)] #![warn(clippy::suboptimal_flops)] /// Allow suboptimal_flops in constant context diff --git a/src/tools/clippy/tests/ui/floating_point_rad.rs b/src/tools/clippy/tests/ui/floating_point_rad.rs index 14656f021df..9690effc4e1 100644 --- a/src/tools/clippy/tests/ui/floating_point_rad.rs +++ b/src/tools/clippy/tests/ui/floating_point_rad.rs @@ -1,4 +1,3 @@ -#![feature(const_fn_floating_point_arithmetic)] #![warn(clippy::suboptimal_flops)] /// Allow suboptimal_flops in constant context diff --git a/src/tools/clippy/tests/ui/floating_point_rad.stderr b/src/tools/clippy/tests/ui/floating_point_rad.stderr index 64674342c2b..b834f5374e0 100644 --- a/src/tools/clippy/tests/ui/floating_point_rad.stderr +++ b/src/tools/clippy/tests/ui/floating_point_rad.stderr @@ -1,5 +1,5 @@ error: conversion to radians can be done more accurately - --> tests/ui/floating_point_rad.rs:11:13 + --> tests/ui/floating_point_rad.rs:10:13 | LL | let _ = degrees as f64 * std::f64::consts::PI / 180.0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(degrees as f64).to_radians()` @@ -8,43 +8,43 @@ LL | let _ = degrees as f64 * std::f64::consts::PI / 180.0; = help: to override `-D warnings` add `#[allow(clippy::suboptimal_flops)]` error: conversion to degrees can be done more accurately - --> tests/ui/floating_point_rad.rs:12:13 + --> tests/ui/floating_point_rad.rs:11:13 | LL | let _ = degrees as f64 * 180.0 / std::f64::consts::PI; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(degrees as f64).to_degrees()` error: conversion to degrees can be done more accurately - --> tests/ui/floating_point_rad.rs:17:13 + --> tests/ui/floating_point_rad.rs:16:13 | LL | let _ = x * 180f32 / std::f32::consts::PI; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.to_degrees()` error: conversion to degrees can be done more accurately - --> tests/ui/floating_point_rad.rs:18:13 + --> tests/ui/floating_point_rad.rs:17:13 | LL | let _ = 90. * 180f64 / std::f64::consts::PI; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `90.0_f64.to_degrees()` error: conversion to degrees can be done more accurately - --> tests/ui/floating_point_rad.rs:19:13 + --> tests/ui/floating_point_rad.rs:18:13 | LL | let _ = 90.5 * 180f64 / std::f64::consts::PI; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `90.5_f64.to_degrees()` error: conversion to radians can be done more accurately - --> tests/ui/floating_point_rad.rs:20:13 + --> tests/ui/floating_point_rad.rs:19:13 | LL | let _ = x * std::f32::consts::PI / 180f32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.to_radians()` error: conversion to radians can be done more accurately - --> tests/ui/floating_point_rad.rs:21:13 + --> tests/ui/floating_point_rad.rs:20:13 | LL | let _ = 90. * std::f32::consts::PI / 180f32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `90.0_f64.to_radians()` error: conversion to radians can be done more accurately - --> tests/ui/floating_point_rad.rs:22:13 + --> tests/ui/floating_point_rad.rs:21:13 | LL | let _ = 90.5 * std::f32::consts::PI / 180f32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `90.5_f64.to_radians()` diff --git a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.fixed b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.fixed index 5778f8f526f..4c324587c96 100644 --- a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.fixed +++ b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.fixed @@ -15,6 +15,14 @@ struct Foo { z: i32, } +#[derive(Default)] +#[allow(clippy::inconsistent_struct_constructor)] +struct Bar { + x: i32, + y: i32, + z: i32, +} + mod without_base { use super::Foo; @@ -70,4 +78,17 @@ mod with_base { } } +mod with_allow_ty_def { + use super::Bar; + + fn test() { + let x = 1; + let y = 1; + let z = 1; + + // Should NOT lint because `Bar` is defined with `#[allow(clippy::inconsistent_struct_constructor)]` + Bar { y, x, z }; + } +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.rs b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.rs index 9efaf068934..d49f236b9b0 100644 --- a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.rs +++ b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.rs @@ -15,6 +15,14 @@ struct Foo { z: i32, } +#[derive(Default)] +#[allow(clippy::inconsistent_struct_constructor)] +struct Bar { + x: i32, + y: i32, + z: i32, +} + mod without_base { use super::Foo; @@ -74,4 +82,17 @@ mod with_base { } } +mod with_allow_ty_def { + use super::Bar; + + fn test() { + let x = 1; + let y = 1; + let z = 1; + + // Should NOT lint because `Bar` is defined with `#[allow(clippy::inconsistent_struct_constructor)]` + Bar { y, x, z }; + } +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.stderr b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.stderr index 1192271f911..97bb7c789a7 100644 --- a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.stderr +++ b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.stderr @@ -1,5 +1,5 @@ error: struct constructor field order is inconsistent with struct definition field order - --> tests/ui/inconsistent_struct_constructor.rs:28:9 + --> tests/ui/inconsistent_struct_constructor.rs:36:9 | LL | Foo { y, x, z }; | ^^^^^^^^^^^^^^^ help: try: `Foo { x, y, z }` @@ -8,7 +8,7 @@ LL | Foo { y, x, z }; = help: to override `-D warnings` add `#[allow(clippy::inconsistent_struct_constructor)]` error: struct constructor field order is inconsistent with struct definition field order - --> tests/ui/inconsistent_struct_constructor.rs:55:9 + --> tests/ui/inconsistent_struct_constructor.rs:63:9 | LL | / Foo { LL | | z, diff --git a/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.rs b/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.rs index 2dccadd9fce..c8409d78ed7 100644 --- a/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.rs +++ b/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.rs @@ -17,7 +17,7 @@ mod multiple { //~^ ERROR: `clippy::msrv` is defined multiple times mod foo { - #![clippy::msrv = "1"] + #![clippy::msrv = "1.0"] #![clippy::msrv = "1.0.0"] //~^ ERROR: `clippy::msrv` is defined multiple times } diff --git a/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.stderr b/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.stderr index b4cb1b5713f..dbc276ed89d 100644 --- a/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.stderr +++ b/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.stderr @@ -31,8 +31,8 @@ LL | #![clippy::msrv = "1.0.0"] note: first definition found here --> tests/ui/min_rust_version_invalid_attr.rs:20:9 | -LL | #![clippy::msrv = "1"] - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | #![clippy::msrv = "1.0"] + | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/src/tools/clippy/tests/ui/string_slice.rs b/src/tools/clippy/tests/ui/string_slice.rs index 440a86b104a..1d1911aaa1d 100644 --- a/src/tools/clippy/tests/ui/string_slice.rs +++ b/src/tools/clippy/tests/ui/string_slice.rs @@ -1,3 +1,5 @@ +use std::borrow::Cow; + #[warn(clippy::string_slice)] #[allow(clippy::no_effect)] @@ -11,4 +13,7 @@ fn main() { let s = String::from(m); &s[0..2]; //~^ ERROR: indexing into a string may panic if the index is within a UTF-8 character + let a = Cow::Borrowed("foo"); + &a[0..3]; + //~^ ERROR: indexing into a string may panic if the index is within a UTF-8 character } diff --git a/src/tools/clippy/tests/ui/string_slice.stderr b/src/tools/clippy/tests/ui/string_slice.stderr index 7a4596b5f2d..bc0fcde34b8 100644 --- a/src/tools/clippy/tests/ui/string_slice.stderr +++ b/src/tools/clippy/tests/ui/string_slice.stderr @@ -1,5 +1,5 @@ error: indexing into a string may panic if the index is within a UTF-8 character - --> tests/ui/string_slice.rs:5:6 + --> tests/ui/string_slice.rs:7:6 | LL | &"Ölkanne"[1..]; | ^^^^^^^^^^^^^^ @@ -8,16 +8,22 @@ LL | &"Ölkanne"[1..]; = help: to override `-D warnings` add `#[allow(clippy::string_slice)]` error: indexing into a string may panic if the index is within a UTF-8 character - --> tests/ui/string_slice.rs:9:6 + --> tests/ui/string_slice.rs:11:6 | LL | &m[2..5]; | ^^^^^^^ error: indexing into a string may panic if the index is within a UTF-8 character - --> tests/ui/string_slice.rs:12:6 + --> tests/ui/string_slice.rs:14:6 | LL | &s[0..2]; | ^^^^^^^ -error: aborting due to 3 previous errors +error: indexing into a string may panic if the index is within a UTF-8 character + --> tests/ui/string_slice.rs:17:6 + | +LL | &a[0..3]; + | ^^^^^^^ + +error: aborting due to 4 previous errors diff --git a/src/tools/clippy/tests/ui/too_long_first_doc_paragraph-fix.fixed b/src/tools/clippy/tests/ui/too_long_first_doc_paragraph-fix.fixed new file mode 100644 index 00000000000..d4a0cdf3447 --- /dev/null +++ b/src/tools/clippy/tests/ui/too_long_first_doc_paragraph-fix.fixed @@ -0,0 +1,9 @@ +#![warn(clippy::too_long_first_doc_paragraph)] + +/// A very short summary. +/// +/// A much longer explanation that goes into a lot more detail about +/// how the thing works, possibly with doclinks and so one, +/// and probably spanning a many rows. Blablabla, it needs to be over +/// 200 characters so I needed to write something longeeeeeeer. +pub struct Foo; diff --git a/src/tools/clippy/tests/ui/too_long_first_doc_paragraph-fix.rs b/src/tools/clippy/tests/ui/too_long_first_doc_paragraph-fix.rs new file mode 100644 index 00000000000..5a3b6c42a32 --- /dev/null +++ b/src/tools/clippy/tests/ui/too_long_first_doc_paragraph-fix.rs @@ -0,0 +1,8 @@ +#![warn(clippy::too_long_first_doc_paragraph)] + +/// A very short summary. +/// A much longer explanation that goes into a lot more detail about +/// how the thing works, possibly with doclinks and so one, +/// and probably spanning a many rows. Blablabla, it needs to be over +/// 200 characters so I needed to write something longeeeeeeer. +pub struct Foo; diff --git a/src/tools/clippy/tests/ui/too_long_first_doc_paragraph-fix.stderr b/src/tools/clippy/tests/ui/too_long_first_doc_paragraph-fix.stderr new file mode 100644 index 00000000000..6403265a39c --- /dev/null +++ b/src/tools/clippy/tests/ui/too_long_first_doc_paragraph-fix.stderr @@ -0,0 +1,20 @@ +error: first doc comment paragraph is too long + --> tests/ui/too_long_first_doc_paragraph-fix.rs:3:1 + | +LL | / /// A very short summary. +LL | | /// A much longer explanation that goes into a lot more detail about +LL | | /// how the thing works, possibly with doclinks and so one, +LL | | /// and probably spanning a many rows. Blablabla, it needs to be over +LL | | /// 200 characters so I needed to write something longeeeeeeer. + | |_ + | + = note: `-D clippy::too-long-first-doc-paragraph` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::too_long_first_doc_paragraph)]` +help: add an empty line + | +LL ~ /// A very short summary. +LL + /// + | + +error: aborting due to 1 previous error + diff --git a/src/tools/clippy/tests/ui/too_long_first_doc_paragraph.rs b/src/tools/clippy/tests/ui/too_long_first_doc_paragraph.rs new file mode 100644 index 00000000000..1042249c5b7 --- /dev/null +++ b/src/tools/clippy/tests/ui/too_long_first_doc_paragraph.rs @@ -0,0 +1,53 @@ +//@no-rustfix + +#![warn(clippy::too_long_first_doc_paragraph)] + +/// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc turpis nunc, lacinia +/// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris arcu libero, +/// gravida non lacinia at, rhoncus eu lacus. +pub struct Bar; + +// Should not warn! (not an item visible on mod page) +/// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc turpis nunc, lacinia +/// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris arcu libero, +/// gravida non lacinia at, rhoncus eu lacus. +impl Bar {} + +// Should not warn! (less than 80 characters) +/// Lorem ipsum dolor sit amet, consectetur adipiscing elit. +/// +/// Nunc turpis nunc, lacinia +/// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris arcu libero, +/// gravida non lacinia at, rhoncus eu lacus. +pub enum Enum { + A, +} + +/// Lorem +/// ipsum dolor sit amet, consectetur adipiscing elit. Nunc turpis nunc, lacinia +/// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris arcu libero, +/// gravida non lacinia at, rhoncus eu lacus. +pub union Union { + a: u8, + b: u8, +} + +// Should not warn! (title) +/// # bla +/// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc turpis nunc, lacinia +/// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris arcu libero, +/// gravida non lacinia at, rhoncus eu lacus. +pub union Union2 { + a: u8, + b: u8, +} + +// Should not warn! (not public) +/// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc turpis nunc, lacinia +/// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris arcu libero, +/// gravida non lacinia at, rhoncus eu lacus. +fn f() {} + +fn main() { + // test code goes here +} diff --git a/src/tools/clippy/tests/ui/too_long_first_doc_paragraph.stderr b/src/tools/clippy/tests/ui/too_long_first_doc_paragraph.stderr new file mode 100644 index 00000000000..7f48e5cf884 --- /dev/null +++ b/src/tools/clippy/tests/ui/too_long_first_doc_paragraph.stderr @@ -0,0 +1,22 @@ +error: first doc comment paragraph is too long + --> tests/ui/too_long_first_doc_paragraph.rs:5:1 + | +LL | / /// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc turpis nunc, lacinia +LL | | /// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris arcu libero, +LL | | /// gravida non lacinia at, rhoncus eu lacus. + | |_ + | + = note: `-D clippy::too-long-first-doc-paragraph` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::too_long_first_doc_paragraph)]` + +error: first doc comment paragraph is too long + --> tests/ui/too_long_first_doc_paragraph.rs:26:1 + | +LL | / /// Lorem +LL | | /// ipsum dolor sit amet, consectetur adipiscing elit. Nunc turpis nunc, lacinia +LL | | /// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris arcu libero, +LL | | /// gravida non lacinia at, rhoncus eu lacus. + | |_ + +error: aborting due to 2 previous errors + diff --git a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr index fcd60f48bcc..bcdf65b217e 100644 --- a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr @@ -2,316 +2,432 @@ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:83:13 | LL | let _ = opt.unwrap_or_else(|| 2); - | ^^^^-------------------- - | | - | help: use `unwrap_or(..)` instead: `unwrap_or(2)` + | ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::unnecessary-lazy-evaluations` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::unnecessary_lazy_evaluations)]` +help: use `unwrap_or` instead + | +LL | let _ = opt.unwrap_or(2); + | ~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:84:13 | LL | let _ = opt.unwrap_or_else(|| astronomers_pi); - | ^^^^--------------------------------- - | | - | help: use `unwrap_or(..)` instead: `unwrap_or(astronomers_pi)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `unwrap_or` instead + | +LL | let _ = opt.unwrap_or(astronomers_pi); + | ~~~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:85:13 | LL | let _ = opt.unwrap_or_else(|| ext_str.some_field); - | ^^^^------------------------------------- - | | - | help: use `unwrap_or(..)` instead: `unwrap_or(ext_str.some_field)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `unwrap_or` instead + | +LL | let _ = opt.unwrap_or(ext_str.some_field); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:87:13 | LL | let _ = opt.and_then(|_| ext_opt); - | ^^^^--------------------- - | | - | help: use `and(..)` instead: `and(ext_opt)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `and` instead + | +LL | let _ = opt.and(ext_opt); + | ~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:88:13 | LL | let _ = opt.or_else(|| ext_opt); - | ^^^^------------------- - | | - | help: use `or(..)` instead: `or(ext_opt)` + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `or` instead + | +LL | let _ = opt.or(ext_opt); + | ~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:89:13 | LL | let _ = opt.or_else(|| None); - | ^^^^---------------- - | | - | help: use `or(..)` instead: `or(None)` + | ^^^^^^^^^^^^^^^^^^^^ + | +help: use `or` instead + | +LL | let _ = opt.or(None); + | ~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:90:13 | LL | let _ = opt.get_or_insert_with(|| 2); - | ^^^^------------------------ - | | - | help: use `get_or_insert(..)` instead: `get_or_insert(2)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `get_or_insert` instead + | +LL | let _ = opt.get_or_insert(2); + | ~~~~~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:91:13 | LL | let _ = opt.ok_or_else(|| 2); - | ^^^^---------------- - | | - | help: use `ok_or(..)` instead: `ok_or(2)` + | ^^^^^^^^^^^^^^^^^^^^ + | +help: use `ok_or` instead + | +LL | let _ = opt.ok_or(2); + | ~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:92:13 | LL | let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2))); - | ^^^^^^^^^^^^^^^^^------------------------------- - | | - | help: use `unwrap_or(..)` instead: `unwrap_or(Some((1, 2)))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `unwrap_or` instead + | +LL | let _ = nested_tuple_opt.unwrap_or(Some((1, 2))); + | ~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:93:13 | LL | let _ = cond.then(|| astronomers_pi); - | ^^^^^----------------------- - | | - | help: use `then_some(..)` instead: `then_some(astronomers_pi)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _ = cond.then_some(astronomers_pi); + | ~~~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:94:13 | LL | let _ = true.then(|| -> _ {}); - | ^^^^^---------------- - | | - | help: use `then_some(..)` instead: `then_some({})` + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _ = true.then_some({}); + | ~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:95:13 | LL | let _ = true.then(|| {}); - | ^^^^^----------- - | | - | help: use `then_some(..)` instead: `then_some({})` + | ^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _ = true.then_some({}); + | ~~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:99:13 | LL | let _ = Some(1).unwrap_or_else(|| *r); - | ^^^^^^^^--------------------- - | | - | help: use `unwrap_or(..)` instead: `unwrap_or(*r)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `unwrap_or` instead + | +LL | let _ = Some(1).unwrap_or(*r); + | ~~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:101:13 | LL | let _ = Some(1).unwrap_or_else(|| *b); - | ^^^^^^^^--------------------- - | | - | help: use `unwrap_or(..)` instead: `unwrap_or(*b)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `unwrap_or` instead + | +LL | let _ = Some(1).unwrap_or(*b); + | ~~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:103:13 | LL | let _ = Some(1).as_ref().unwrap_or_else(|| &r); - | ^^^^^^^^^^^^^^^^^--------------------- - | | - | help: use `unwrap_or(..)` instead: `unwrap_or(&r)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `unwrap_or` instead + | +LL | let _ = Some(1).as_ref().unwrap_or(&r); + | ~~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:104:13 | LL | let _ = Some(1).as_ref().unwrap_or_else(|| &b); - | ^^^^^^^^^^^^^^^^^--------------------- - | | - | help: use `unwrap_or(..)` instead: `unwrap_or(&b)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `unwrap_or` instead + | +LL | let _ = Some(1).as_ref().unwrap_or(&b); + | ~~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:107:13 | LL | let _ = Some(10).unwrap_or_else(|| 2); - | ^^^^^^^^^-------------------- - | | - | help: use `unwrap_or(..)` instead: `unwrap_or(2)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `unwrap_or` instead + | +LL | let _ = Some(10).unwrap_or(2); + | ~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:108:13 | LL | let _ = Some(10).and_then(|_| ext_opt); - | ^^^^^^^^^--------------------- - | | - | help: use `and(..)` instead: `and(ext_opt)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `and` instead + | +LL | let _ = Some(10).and(ext_opt); + | ~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:109:28 | LL | let _: Option = None.or_else(|| ext_opt); - | ^^^^^------------------- - | | - | help: use `or(..)` instead: `or(ext_opt)` + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `or` instead + | +LL | let _: Option = None.or(ext_opt); + | ~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:110:13 | LL | let _ = None.get_or_insert_with(|| 2); - | ^^^^^------------------------ - | | - | help: use `get_or_insert(..)` instead: `get_or_insert(2)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `get_or_insert` instead + | +LL | let _ = None.get_or_insert(2); + | ~~~~~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:111:35 | LL | let _: Result = None.ok_or_else(|| 2); - | ^^^^^---------------- - | | - | help: use `ok_or(..)` instead: `ok_or(2)` + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: use `ok_or` instead + | +LL | let _: Result = None.ok_or(2); + | ~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:112:28 | LL | let _: Option = None.or_else(|| None); - | ^^^^^---------------- - | | - | help: use `or(..)` instead: `or(None)` + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: use `or` instead + | +LL | let _: Option = None.or(None); + | ~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:115:13 | LL | let _ = deep.0.unwrap_or_else(|| 2); - | ^^^^^^^-------------------- - | | - | help: use `unwrap_or(..)` instead: `unwrap_or(2)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `unwrap_or` instead + | +LL | let _ = deep.0.unwrap_or(2); + | ~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:116:13 | LL | let _ = deep.0.and_then(|_| ext_opt); - | ^^^^^^^--------------------- - | | - | help: use `and(..)` instead: `and(ext_opt)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `and` instead + | +LL | let _ = deep.0.and(ext_opt); + | ~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:117:13 | LL | let _ = deep.0.or_else(|| None); - | ^^^^^^^---------------- - | | - | help: use `or(..)` instead: `or(None)` + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `or` instead + | +LL | let _ = deep.0.or(None); + | ~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:118:13 | LL | let _ = deep.0.get_or_insert_with(|| 2); - | ^^^^^^^------------------------ - | | - | help: use `get_or_insert(..)` instead: `get_or_insert(2)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `get_or_insert` instead + | +LL | let _ = deep.0.get_or_insert(2); + | ~~~~~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:119:13 | LL | let _ = deep.0.ok_or_else(|| 2); - | ^^^^^^^---------------- - | | - | help: use `ok_or(..)` instead: `ok_or(2)` + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `ok_or` instead + | +LL | let _ = deep.0.ok_or(2); + | ~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:150:28 | LL | let _: Option = None.or_else(|| Some(3)); - | ^^^^^------------------- - | | - | help: use `or(..)` instead: `or(Some(3))` + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `or` instead + | +LL | let _: Option = None.or(Some(3)); + | ~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:151:13 | LL | let _ = deep.0.or_else(|| Some(3)); - | ^^^^^^^------------------- - | | - | help: use `or(..)` instead: `or(Some(3))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `or` instead + | +LL | let _ = deep.0.or(Some(3)); + | ~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:152:13 | LL | let _ = opt.or_else(|| Some(3)); - | ^^^^------------------- - | | - | help: use `or(..)` instead: `or(Some(3))` + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `or` instead + | +LL | let _ = opt.or(Some(3)); + | ~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Result::Err` --> tests/ui/unnecessary_lazy_eval.rs:158:13 | LL | let _ = res2.unwrap_or_else(|_| 2); - | ^^^^^--------------------- - | | - | help: use `unwrap_or(..)` instead: `unwrap_or(2)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `unwrap_or` instead + | +LL | let _ = res2.unwrap_or(2); + | ~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Result::Err` --> tests/ui/unnecessary_lazy_eval.rs:159:13 | LL | let _ = res2.unwrap_or_else(|_| astronomers_pi); - | ^^^^^---------------------------------- - | | - | help: use `unwrap_or(..)` instead: `unwrap_or(astronomers_pi)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `unwrap_or` instead + | +LL | let _ = res2.unwrap_or(astronomers_pi); + | ~~~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Result::Err` --> tests/ui/unnecessary_lazy_eval.rs:160:13 | LL | let _ = res2.unwrap_or_else(|_| ext_str.some_field); - | ^^^^^-------------------------------------- - | | - | help: use `unwrap_or(..)` instead: `unwrap_or(ext_str.some_field)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `unwrap_or` instead + | +LL | let _ = res2.unwrap_or(ext_str.some_field); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Result::Err` --> tests/ui/unnecessary_lazy_eval.rs:182:35 | LL | let _: Result = res.and_then(|_| Err(2)); - | ^^^^-------------------- - | | - | help: use `and(..)` instead: `and(Err(2))` + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `and` instead + | +LL | let _: Result = res.and(Err(2)); + | ~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Result::Err` --> tests/ui/unnecessary_lazy_eval.rs:183:35 | LL | let _: Result = res.and_then(|_| Err(astronomers_pi)); - | ^^^^--------------------------------- - | | - | help: use `and(..)` instead: `and(Err(astronomers_pi))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `and` instead + | +LL | let _: Result = res.and(Err(astronomers_pi)); + | ~~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Result::Err` --> tests/ui/unnecessary_lazy_eval.rs:184:35 | LL | let _: Result = res.and_then(|_| Err(ext_str.some_field)); - | ^^^^------------------------------------- - | | - | help: use `and(..)` instead: `and(Err(ext_str.some_field))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `and` instead + | +LL | let _: Result = res.and(Err(ext_str.some_field)); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Result::Err` --> tests/ui/unnecessary_lazy_eval.rs:186:35 | LL | let _: Result = res.or_else(|_| Ok(2)); - | ^^^^------------------ - | | - | help: use `or(..)` instead: `or(Ok(2))` + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `or` instead + | +LL | let _: Result = res.or(Ok(2)); + | ~~~~~~~~~ error: unnecessary closure used to substitute value for `Result::Err` --> tests/ui/unnecessary_lazy_eval.rs:187:35 | LL | let _: Result = res.or_else(|_| Ok(astronomers_pi)); - | ^^^^------------------------------- - | | - | help: use `or(..)` instead: `or(Ok(astronomers_pi))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `or` instead + | +LL | let _: Result = res.or(Ok(astronomers_pi)); + | ~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Result::Err` --> tests/ui/unnecessary_lazy_eval.rs:188:35 | LL | let _: Result = res.or_else(|_| Ok(ext_str.some_field)); - | ^^^^----------------------------------- - | | - | help: use `or(..)` instead: `or(Ok(ext_str.some_field))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `or` instead + | +LL | let _: Result = res.or(Ok(ext_str.some_field)); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Result::Err` --> tests/ui/unnecessary_lazy_eval.rs:189:35 @@ -324,193 +440,265 @@ LL | | // some lines ... | LL | | // some lines LL | | or_else(|_| Ok(ext_str.some_field)); - | |_____----------------------------------^ - | | - | help: use `or(..)` instead: `or(Ok(ext_str.some_field))` + | |_______________________________________^ + | +help: use `or` instead + | +LL | or(Ok(ext_str.some_field)); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:219:14 | LL | let _x = false.then(|| i32::MAX + 1); - | ^^^^^^--------------------- - | | - | help: use `then_some(..)` instead: `then_some(i32::MAX + 1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(i32::MAX + 1); + | ~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:221:14 | LL | let _x = false.then(|| i32::MAX * 2); - | ^^^^^^--------------------- - | | - | help: use `then_some(..)` instead: `then_some(i32::MAX * 2)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(i32::MAX * 2); + | ~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:223:14 | LL | let _x = false.then(|| i32::MAX - 1); - | ^^^^^^--------------------- - | | - | help: use `then_some(..)` instead: `then_some(i32::MAX - 1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(i32::MAX - 1); + | ~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:225:14 | LL | let _x = false.then(|| i32::MIN - 1); - | ^^^^^^--------------------- - | | - | help: use `then_some(..)` instead: `then_some(i32::MIN - 1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(i32::MIN - 1); + | ~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:227:14 | LL | let _x = false.then(|| (1 + 2 * 3 - 2 / 3 + 9) << 2); - | ^^^^^^------------------------------------- - | | - | help: use `then_some(..)` instead: `then_some((1 + 2 * 3 - 2 / 3 + 9) << 2)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some((1 + 2 * 3 - 2 / 3 + 9) << 2); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:229:14 | LL | let _x = false.then(|| 255u8 << 7); - | ^^^^^^------------------- - | | - | help: use `then_some(..)` instead: `then_some(255u8 << 7)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(255u8 << 7); + | ~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:231:14 | LL | let _x = false.then(|| 255u8 << 8); - | ^^^^^^------------------- - | | - | help: use `then_some(..)` instead: `then_some(255u8 << 8)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(255u8 << 8); + | ~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:233:14 | LL | let _x = false.then(|| 255u8 >> 8); - | ^^^^^^------------------- - | | - | help: use `then_some(..)` instead: `then_some(255u8 >> 8)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(255u8 >> 8); + | ~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:236:14 | LL | let _x = false.then(|| i32::MAX + -1); - | ^^^^^^---------------------- - | | - | help: use `then_some(..)` instead: `then_some(i32::MAX + -1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(i32::MAX + -1); + | ~~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:238:14 | LL | let _x = false.then(|| -i32::MAX); - | ^^^^^^------------------ - | | - | help: use `then_some(..)` instead: `then_some(-i32::MAX)` + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(-i32::MAX); + | ~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:240:14 | LL | let _x = false.then(|| -i32::MIN); - | ^^^^^^------------------ - | | - | help: use `then_some(..)` instead: `then_some(-i32::MIN)` + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(-i32::MIN); + | ~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:243:14 | LL | let _x = false.then(|| 255 >> -7); - | ^^^^^^------------------ - | | - | help: use `then_some(..)` instead: `then_some(255 >> -7)` + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(255 >> -7); + | ~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:245:14 | LL | let _x = false.then(|| 255 << -1); - | ^^^^^^------------------ - | | - | help: use `then_some(..)` instead: `then_some(255 << -1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(255 << -1); + | ~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:247:14 | LL | let _x = false.then(|| 1 / 0); - | ^^^^^^-------------- - | | - | help: use `then_some(..)` instead: `then_some(1 / 0)` + | ^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(1 / 0); + | ~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:249:14 | LL | let _x = false.then(|| x << -1); - | ^^^^^^---------------- - | | - | help: use `then_some(..)` instead: `then_some(x << -1)` + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(x << -1); + | ~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:251:14 | LL | let _x = false.then(|| x << 2); - | ^^^^^^--------------- - | | - | help: use `then_some(..)` instead: `then_some(x << 2)` + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(x << 2); + | ~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:261:14 | LL | let _x = false.then(|| x / 0); - | ^^^^^^-------------- - | | - | help: use `then_some(..)` instead: `then_some(x / 0)` + | ^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(x / 0); + | ~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:263:14 | LL | let _x = false.then(|| x % 0); - | ^^^^^^-------------- - | | - | help: use `then_some(..)` instead: `then_some(x % 0)` + | ^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(x % 0); + | ~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:266:14 | LL | let _x = false.then(|| 1 / -1); - | ^^^^^^--------------- - | | - | help: use `then_some(..)` instead: `then_some(1 / -1)` + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(1 / -1); + | ~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:268:14 | LL | let _x = false.then(|| i32::MIN / -1); - | ^^^^^^---------------------- - | | - | help: use `then_some(..)` instead: `then_some(i32::MIN / -1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(i32::MIN / -1); + | ~~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:271:14 | LL | let _x = false.then(|| i32::MIN / 0); - | ^^^^^^--------------------- - | | - | help: use `then_some(..)` instead: `then_some(i32::MIN / 0)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(i32::MIN / 0); + | ~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:273:14 | LL | let _x = false.then(|| 4 / 2); - | ^^^^^^-------------- - | | - | help: use `then_some(..)` instead: `then_some(4 / 2)` + | ^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(4 / 2); + | ~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:281:14 | LL | let _x = false.then(|| f1 + f2); - | ^^^^^^---------------- - | | - | help: use `then_some(..)` instead: `then_some(f1 + f2)` + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(f1 + f2); + | ~~~~~~~~~~~~~~~~~~ error: aborting due to 63 previous errors diff --git a/src/tools/clippy/tests/ui/unnecessary_lazy_eval_unfixable.stderr b/src/tools/clippy/tests/ui/unnecessary_lazy_eval_unfixable.stderr index b566b119571..390235b2124 100644 --- a/src/tools/clippy/tests/ui/unnecessary_lazy_eval_unfixable.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_lazy_eval_unfixable.stderr @@ -2,36 +2,47 @@ error: unnecessary closure used to substitute value for `Result::Err` --> tests/ui/unnecessary_lazy_eval_unfixable.rs:13:13 | LL | let _ = Ok(1).unwrap_or_else(|()| 2); - | ^^^^^^---------------------- - | | - | help: use `unwrap_or(..)` instead: `unwrap_or(2)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::unnecessary-lazy-evaluations` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::unnecessary_lazy_evaluations)]` +help: use `unwrap_or` instead + | +LL | let _ = Ok(1).unwrap_or(2); + | ~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Result::Err` --> tests/ui/unnecessary_lazy_eval_unfixable.rs:19:13 | LL | let _ = Ok(1).unwrap_or_else(|e::E| 2); - | ^^^^^^------------------------ - | | - | help: use `unwrap_or(..)` instead: `unwrap_or(2)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `unwrap_or` instead + | +LL | let _ = Ok(1).unwrap_or(2); + | ~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Result::Err` --> tests/ui/unnecessary_lazy_eval_unfixable.rs:21:13 | LL | let _ = Ok(1).unwrap_or_else(|SomeStruct { .. }| 2); - | ^^^^^^------------------------------------- - | | - | help: use `unwrap_or(..)` instead: `unwrap_or(2)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `unwrap_or` instead + | +LL | let _ = Ok(1).unwrap_or(2); + | ~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval_unfixable.rs:31:13 | LL | let _ = true.then(|| -> &[u8] { &[] }); - | ^^^^^------------------------- - | | - | help: use `then_some(..)` instead: `then_some({ &[] })` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _ = true.then_some({ &[] }); + | ~~~~~~~~~~~~~~~~~~ error: aborting due to 4 previous errors diff --git a/src/tools/clippy/triagebot.toml b/src/tools/clippy/triagebot.toml index dcf00e4e384..99b3560a064 100644 --- a/src/tools/clippy/triagebot.toml +++ b/src/tools/clippy/triagebot.toml @@ -20,6 +20,7 @@ new_pr = true [assign] contributing_url = "https://github.com/rust-lang/rust-clippy/blob/master/CONTRIBUTING.md" users_on_vacation = [ + "flip1995", "matthiaskrgr", "giraffate", ] diff --git a/src/tools/clippy/util/gh-pages/index.html b/src/tools/clippy/util/gh-pages/index.html index 300c9de178f..f3d7e504fdf 100644 --- a/src/tools/clippy/util/gh-pages/index.html +++ b/src/tools/clippy/util/gh-pages/index.html @@ -23,378 +23,25 @@ Otherwise, have a great day =^.^= - - + -
    -
    🖌
    -
      -
    • {{name}}
    • -
    +
    +
    +
    +
    Theme
    + + +
    @@ -592,7 +239,7 @@ Otherwise, have a great day =^.^=
    Applicability: - {{lint.applicability.applicability}} + {{lint.applicability}} (?)
    @@ -605,8 +252,8 @@ Otherwise, have a great day =^.^= Related Issues
    -
    diff --git a/src/tools/clippy/util/gh-pages/script.js b/src/tools/clippy/util/gh-pages/script.js index ed1e090e1b5..1a5330bc0e5 100644 --- a/src/tools/clippy/util/gh-pages/script.js +++ b/src/tools/clippy/util/gh-pages/script.js @@ -50,24 +50,6 @@ ); }; }) - .directive('themeDropdown', function ($document) { - return { - restrict: 'A', - link: function ($scope, $element, $attr) { - $element.bind('click', function () { - $element.toggleClass('open'); - $element.addClass('open-recent'); - }); - - $document.bind('click', function () { - if (!$element.hasClass('open-recent')) { - $element.removeClass('open'); - } - $element.removeClass('open-recent'); - }) - } - } - }) .directive('filterDropdown', function ($document) { return { restrict: 'A', @@ -114,28 +96,19 @@ cargo: true, complexity: true, correctness: true, - deprecated: false, nursery: true, pedantic: true, perf: true, restriction: true, style: true, suspicious: true, + deprecated: false, } $scope.groups = { ...GROUPS_FILTER_DEFAULT }; - const THEMES_DEFAULT = { - light: "Light", - rust: "Rust", - coal: "Coal", - navy: "Navy", - ayu: "Ayu" - }; - $scope.themes = THEMES_DEFAULT; - $scope.versionFilters = { "≥": {enabled: false, minorVersion: null }, "≤": {enabled: false, minorVersion: null }, @@ -153,11 +126,10 @@ ); const APPLICABILITIES_FILTER_DEFAULT = { - Unspecified: true, - Unresolved: true, MachineApplicable: true, MaybeIncorrect: true, - HasPlaceholders: true + HasPlaceholders: true, + Unspecified: true, }; $scope.applicabilities = { @@ -321,10 +293,6 @@ $location.path($scope.search); } - $scope.selectTheme = function (theme) { - setTheme(theme, true); - } - $scope.toggleLevels = function (value) { const levels = $scope.levels; for (const key in levels) { @@ -456,7 +424,7 @@ } $scope.byApplicabilities = function (lint) { - return $scope.applicabilities[lint.applicability.applicability]; + return $scope.applicabilities[lint.applicability]; }; // Show details for one lint @@ -537,6 +505,16 @@ function getQueryVariable(variable) { } } +function storeValue(settingName, value) { + try { + localStorage.setItem(`clippy-lint-list-${settingName}`, value); + } catch (e) { } +} + +function loadValue(settingName) { + return localStorage.getItem(`clippy-lint-list-${settingName}`); +} + function setTheme(theme, store) { let enableHighlight = false; let enableNight = false; @@ -569,14 +547,14 @@ function setTheme(theme, store) { document.getElementById("styleAyu").disabled = !enableAyu; if (store) { - try { - localStorage.setItem('clippy-lint-list-theme', theme); - } catch (e) { } + storeValue("theme", theme); + } else { + document.getElementById(`theme-choice`).value = theme; } } function handleShortcut(ev) { - if (ev.ctrlKey || ev.altKey || ev.metaKey) { + if (ev.ctrlKey || ev.altKey || ev.metaKey || disableShortcuts) { return; } @@ -601,11 +579,51 @@ function handleShortcut(ev) { document.addEventListener("keypress", handleShortcut); document.addEventListener("keydown", handleShortcut); +function changeSetting(elem) { + if (elem.id === "disable-shortcuts") { + disableShortcuts = elem.checked; + storeValue(elem.id, elem.checked); + } +} + +function onEachLazy(lazyArray, func) { + const arr = Array.prototype.slice.call(lazyArray); + for (const el of arr) { + func(el); + } +} + +function handleBlur(event) { + const parent = document.getElementById("settings-dropdown"); + if (!parent.contains(document.activeElement) && + !parent.contains(event.relatedTarget) + ) { + parent.classList.remove("open"); + } +} + +function generateSettings() { + const settings = document.getElementById("settings-dropdown"); + const settingsButton = settings.querySelector(".settings-icon") + settingsButton.onclick = () => settings.classList.toggle("open"); + settingsButton.onblur = handleBlur; + const settingsMenu = settings.querySelector(".settings-menu"); + settingsMenu.onblur = handleBlur; + onEachLazy( + settingsMenu.querySelectorAll("input"), + el => el.onblur = handleBlur, + ); +} + +generateSettings(); + // loading the theme after the initial load const prefersDark = window.matchMedia("(prefers-color-scheme: dark)"); -const theme = localStorage.getItem('clippy-lint-list-theme'); +const theme = loadValue('theme'); if (prefersDark.matches && !theme) { setTheme("coal", false); } else { setTheme(theme, false); } +let disableShortcuts = loadValue('disable-shortcuts') === "true"; +document.getElementById("disable-shortcuts").checked = disableShortcuts; diff --git a/src/tools/clippy/util/gh-pages/style.css b/src/tools/clippy/util/gh-pages/style.css new file mode 100644 index 00000000000..a9485d51104 --- /dev/null +++ b/src/tools/clippy/util/gh-pages/style.css @@ -0,0 +1,398 @@ +blockquote { font-size: 1em; } + +[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak { + display: none !important; +} + +.dropdown-menu { + color: var(--fg); + background: var(--theme-popup-bg); + border: 1px solid var(--theme-popup-border); +} + +.dropdown-menu .divider { + background-color: var(--theme-popup-border); +} + +.dropdown-menu .checkbox { + display: block; + white-space: nowrap; + margin: 0; +} +.dropdown-menu .checkbox label { + padding: 3px 20px; + width: 100%; +} + +.dropdown-menu .checkbox input { + position: relative; + margin: 0 0.5rem 0; + padding: 0; +} + +.dropdown-menu .checkbox:hover { + background-color: var(--theme-hover); +} + +div.panel div.panel-body button { + background: var(--searchbar-bg); + color: var(--searchbar-fg); + border-color: var(--theme-popup-border); +} + +div.panel div.panel-body button:hover { + box-shadow: 0 0 3px var(--searchbar-shadow-color); +} + +div.panel div.panel-body button.open { + filter: brightness(90%); +} + +.dropdown-toggle .badge { + background-color: #777; +} + +.panel-heading { cursor: pointer; } + +.panel-title { display: flex; flex-wrap: wrap;} +.panel-title .label { display: inline-block; } + +.panel-title-name { flex: 1; min-width: 400px;} +.panel-title-name span { vertical-align: bottom; } + +.panel .panel-title-name .anchor { display: none; } +.panel:hover .panel-title-name .anchor { display: inline;} + +.search-control { + margin-top: 15px; +} + +@media (min-width: 992px) { + .search-control { + margin-top: 0; + } +} + +@media (min-width: 405px) { + #upper-filters { + display: flex; + flex-wrap: wrap; + } +} + +@media (max-width: 430px) { + /* Turn the version filter list to the left */ + #version-filter-selector { + right: 0; + left: auto; + } +} + +@media (max-width: 412px) { + #upper-filters, + .panel-body .search-control { + padding-right: 8px; + padding-left: 8px; + } +} + +.label { + padding-top: 0.3em; + padding-bottom: 0.3em; +} + +.label-lint-group { + min-width: 8em; +} +.label-lint-level { + min-width: 4em; +} + +.label-lint-level-allow { + background-color: #5cb85c; +} +.label-lint-level-warn { + background-color: #f0ad4e; +} +.label-lint-level-deny { + background-color: #d9534f; +} +.label-lint-level-none { + background-color: #777777; + opacity: 0.5; +} + +.label-group-deprecated { + opacity: 0.5; +} + +.label-doc-folding { + color: #000; + background-color: #fff; + border: 1px solid var(--theme-popup-border); +} +.label-doc-folding:hover { + background-color: #e6e6e6; +} + +.lint-doc-md > h3 { + border-top: 1px solid var(--theme-popup-border); + padding: 10px 15px; + margin: 0 -15px; + font-size: 18px; +} +.lint-doc-md > h3:first-child { + border-top: none; + padding-top: 0px; +} + +@media (max-width:749px) { + .lint-additional-info-container { + display: flex; + flex-flow: column; + } + .lint-additional-info-item + .lint-additional-info-item { + border-top: 1px solid var(--theme-popup-border); + } +} +@media (min-width:750px) { + .lint-additional-info-container { + display: flex; + flex-flow: row; + } + .lint-additional-info-item + .lint-additional-info-item { + border-left: 1px solid var(--theme-popup-border); + } +} + +.lint-additional-info-item { + display: inline-flex; + min-width: 200px; + flex-grow: 1; + padding: 9px 5px 5px 15px; +} + +.label-applicability { + background-color: #777777; + margin: auto 5px; +} + +.label-version { + background-color: #777777; + margin: auto 5px; + font-family: monospace; +} + +details { + border-radius: 4px; + padding: .5em .5em 0; +} + +code { + white-space: pre !important; +} + +summary { + font-weight: bold; + margin: -.5em -.5em 0; + padding: .5em; + display: revert; +} + +details[open] { + padding: .5em; +} + +/* Expanding the mdBook theme*/ +.light { + --inline-code-bg: #f6f7f6; +} +.rust { + --inline-code-bg: #f6f7f6; +} +.coal { + --inline-code-bg: #1d1f21; +} +.navy { + --inline-code-bg: #1d1f21; +} +.ayu { + --inline-code-bg: #191f26; +} + +#settings-dropdown { + position: absolute; + margin: 0.7em; + z-index: 10; + display: flex; +} + +/* Applying the mdBook theme */ +.settings-icon { + text-align: center; + width: 2em; + height: 2em; + line-height: 2em; + border: solid 1px var(--icons); + border-radius: 5px; + user-select: none; + cursor: pointer; + background: var(--theme-hover); +} +.settings-menu { + display: none; + list-style: none; + border: 1px solid var(--theme-popup-border); + border-radius: 5px; + color: var(--fg); + background: var(--theme-popup-bg); + overflow: hidden; + padding: 9px; + width: 207px; + position: absolute; + top: 28px; +} + +.settings-icon::before { + /* Wheel */ + content: url('data:image/svg+xml,\ +'); + width: 18px; + height: 18px; + display: block; + filter: invert(0.7); + padding-left: 4px; + padding-top: 3px; +} + +.settings-menu * { + font-weight: normal; +} + +.settings-menu label { + cursor: pointer; +} + +#settings-dropdown.open .settings-menu { + display: block; +} + +#theme-choice { + margin-bottom: 10px; + background: var(--searchbar-bg); + color: var(--searchbar-fg); + border-color: var(--theme-popup-border); + border-radius: 5px; + cursor: pointer; + width: 100%; + border-width: 1px; + padding: 5px; +} + +.alert { + color: var(--fg); + background: var(--theme-hover); + border: 1px solid var(--theme-popup-border); +} +.page-header { + border-color: var(--theme-popup-border); +} +.panel-default > .panel-heading { + background: var(--theme-hover); + color: var(--fg); + border: 1px solid var(--theme-popup-border); +} +.panel-default > .panel-heading:hover { + filter: brightness(90%); +} +.list-group-item { + background: 0%; + border: 1px solid var(--theme-popup-border); +} +.panel, pre, hr { + background: var(--bg); + border: 1px solid var(--theme-popup-border); +} + +#version-filter-selector .checkbox { + display: flex; +} + +#version-filter { + min-width: available; +} + +#version-filter li label { + padding-right: 0; + width: 35%; +} + +.version-filter-input { + height: 60%; + width: 30%; + text-align: center; + border: none; + border-bottom: 1px solid #000000; +} + +#filter-label, .filter-clear { + background: var(--searchbar-bg); + color: var(--searchbar-fg); + border-color: var(--theme-popup-border); + filter: brightness(95%); +} +#filter-label:hover, .filter-clear:hover { + filter: brightness(90%); +} +.filter-input { + background: var(--searchbar-bg); + color: var(--searchbar-fg); + border-color: var(--theme-popup-border); +} + +.filter-input::-webkit-input-placeholder, +.filter-input::-moz-placeholder { + color: var(--searchbar-fg); + opacity: 30%; +} + +.expansion-group { + margin-top: 15px; + padding: 0px 8px; + display: flex; + flex-wrap: nowrap; +} + +@media (min-width: 992px) { + .expansion-group { + margin-top: 0; + padding: 0px 15px; + } +} + +.expansion-control { + width: 50%; +} + +:not(pre) > code { + color: var(--inline-code-color); + background-color: var(--inline-code-bg); +} +html { + scrollbar-color: var(--scrollbar) var(--bg); +} +body { + background: var(--bg); + color: var(--fg); +} diff --git a/src/tools/compiletest/src/command-list.rs b/src/tools/compiletest/src/command-list.rs index 50c909793f5..a559d6f81a2 100644 --- a/src/tools/compiletest/src/command-list.rs +++ b/src/tools/compiletest/src/command-list.rs @@ -92,10 +92,12 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "ignore-nvptx64-nvidia-cuda", "ignore-openbsd", "ignore-pass", + "ignore-powerpc", "ignore-remote", "ignore-riscv64", "ignore-s390x", "ignore-sgx", + "ignore-sparc64", "ignore-spirv", "ignore-stable", "ignore-stage1", @@ -123,6 +125,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "ignore-x86", "ignore-x86_64", "ignore-x86_64-apple-darwin", + "ignore-x86_64-pc-windows-gnu", "ignore-x86_64-unknown-linux-gnu", "incremental", "known-bug", @@ -138,11 +141,11 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "needs-force-clang-based-tests", "needs-git-hash", "needs-llvm-components", + "needs-llvm-zstd", "needs-profiler-support", "needs-relocation-model-pic", "needs-run-enabled", "needs-rust-lld", - "needs-rust-lldb", "needs-sanitizer-address", "needs-sanitizer-cfi", "needs-sanitizer-dataflow", @@ -191,7 +194,9 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "only-msvc", "only-nightly", "only-nvptx64", + "only-powerpc", "only-riscv64", + "only-s390x", "only-sparc", "only-sparc64", "only-stable", diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 70ebefe3f41..5831f7c3cf2 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -296,15 +296,9 @@ pub struct Config { /// Version of GDB, encoded as ((major * 1000) + minor) * 1000 + patch pub gdb_version: Option, - /// Whether GDB has native rust support - pub gdb_native_rust: bool, - /// Version of LLDB pub lldb_version: Option, - /// Whether LLDB has native rust support - pub lldb_native_rust: bool, - /// Version of LLVM pub llvm_version: Option, diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 1fc24301c85..933913eb47c 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -1203,6 +1203,107 @@ pub fn extract_llvm_version_from_binary(binary_path: &str) -> Option { None } +/// For tests using the `needs-llvm-zstd` directive: +/// - for local LLVM builds, try to find the static zstd library in the llvm-config system libs. +/// - for `download-ci-llvm`, see if `lld` was built with zstd support. +pub fn llvm_has_libzstd(config: &Config) -> bool { + // Strategy 1: works for local builds but not with `download-ci-llvm`. + // + // We check whether `llvm-config` returns the zstd library. Bootstrap's `llvm.libzstd` will only + // ask to statically link it when building LLVM, so we only check if the list of system libs + // contains a path to that static lib, and that it exists. + // + // See compiler/rustc_llvm/build.rs for more details and similar expectations. + fn is_zstd_in_config(llvm_bin_dir: &Path) -> Option<()> { + let llvm_config_path = llvm_bin_dir.join("llvm-config"); + let output = Command::new(llvm_config_path).arg("--system-libs").output().ok()?; + assert!(output.status.success(), "running llvm-config --system-libs failed"); + + let libs = String::from_utf8(output.stdout).ok()?; + for lib in libs.split_whitespace() { + if lib.ends_with("libzstd.a") && Path::new(lib).exists() { + return Some(()); + } + } + + None + } + + // Strategy 2: `download-ci-llvm`'s `llvm-config --system-libs` will not return any libs to + // use. + // + // The CI artifacts also don't contain the bootstrap config used to build them: otherwise we + // could have looked at the `llvm.libzstd` config. + // + // We infer whether `LLVM_ENABLE_ZSTD` was used to build LLVM as a byproduct of testing whether + // `lld` supports it. If not, an error will be emitted: "LLVM was not built with + // LLVM_ENABLE_ZSTD or did not find zstd at build time". + #[cfg(unix)] + fn is_lld_built_with_zstd(llvm_bin_dir: &Path) -> Option<()> { + let lld_path = llvm_bin_dir.join("lld"); + if lld_path.exists() { + // We can't call `lld` as-is, it expects to be invoked by a compiler driver using a + // different name. Prepare a temporary symlink to do that. + let lld_symlink_path = llvm_bin_dir.join("ld.lld"); + if !lld_symlink_path.exists() { + std::os::unix::fs::symlink(lld_path, &lld_symlink_path).ok()?; + } + + // Run `lld` with a zstd flag. We expect this command to always error here, we don't + // want to link actual files and don't pass any. + let output = Command::new(&lld_symlink_path) + .arg("--compress-debug-sections=zstd") + .output() + .ok()?; + assert!(!output.status.success()); + + // Look for a specific error caused by LLVM not being built with zstd support. We could + // also look for the "no input files" message, indicating the zstd flag was accepted. + let stderr = String::from_utf8(output.stderr).ok()?; + let zstd_available = !stderr.contains("LLVM was not built with LLVM_ENABLE_ZSTD"); + + // We don't particularly need to clean the link up (so the previous commands could fail + // in theory but won't in practice), but we can try. + std::fs::remove_file(lld_symlink_path).ok()?; + + if zstd_available { + return Some(()); + } + } + + None + } + + #[cfg(not(unix))] + fn is_lld_built_with_zstd(_llvm_bin_dir: &Path) -> Option<()> { + None + } + + if let Some(llvm_bin_dir) = &config.llvm_bin_dir { + // Strategy 1: for local LLVM builds. + if is_zstd_in_config(llvm_bin_dir).is_some() { + return true; + } + + // Strategy 2: for LLVM artifacts built on CI via `download-ci-llvm`. + // + // It doesn't work for cases where the artifacts don't contain the linker, but it's + // best-effort: CI has `llvm.libzstd` and `lld` enabled on the x64 linux artifacts, so it + // will at least work there. + // + // If this can be improved and expanded to less common cases in the future, it should. + if config.target == "x86_64-unknown-linux-gnu" + && config.host == config.target + && is_lld_built_with_zstd(llvm_bin_dir).is_some() + { + return true; + } + } + + // Otherwise, all hope is lost. + false +} + /// Takes a directive of the form " [- ]", /// returns the numeric representation of and as /// tuple: ( as u32, as u32) diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs index 5b2665f7d0b..72b1b9c6d48 100644 --- a/src/tools/compiletest/src/header/needs.rs +++ b/src/tools/compiletest/src/header/needs.rs @@ -1,5 +1,5 @@ -use crate::common::{Config, Debugger, Sanitizer}; -use crate::header::IgnoreDecision; +use crate::common::{Config, Sanitizer}; +use crate::header::{llvm_has_libzstd, IgnoreDecision}; pub(super) fn handle_needs( cache: &CachedNeedsConditions, @@ -114,11 +114,6 @@ pub(super) fn handle_needs( condition: cache.rust_lld, ignore_reason: "ignored on targets without Rust's LLD", }, - Need { - name: "needs-rust-lldb", - condition: config.debugger != Some(Debugger::Lldb) || config.lldb_native_rust, - ignore_reason: "ignored on targets without Rust's LLDB", - }, Need { name: "needs-dlltool", condition: cache.dlltool, @@ -149,6 +144,11 @@ pub(super) fn handle_needs( condition: cache.symlinks, ignore_reason: "ignored if symlinks are unavailable", }, + Need { + name: "needs-llvm-zstd", + condition: cache.llvm_zstd, + ignore_reason: "ignored if LLVM wasn't build with zstd for ELF section compression", + }, ]; let (name, comment) = match ln.split_once([':', ' ']) { @@ -174,7 +174,7 @@ pub(super) fn handle_needs( } else { return IgnoreDecision::Ignore { reason: if let Some(comment) = comment { - format!("{} ({comment})", need.ignore_reason) + format!("{} ({})", need.ignore_reason, comment.trim()) } else { need.ignore_reason.into() }, @@ -215,6 +215,8 @@ pub(super) struct CachedNeedsConditions { rust_lld: bool, dlltool: bool, symlinks: bool, + /// Whether LLVM built with zstd, for the `needs-llvm-zstd` directive. + llvm_zstd: bool, } impl CachedNeedsConditions { @@ -258,6 +260,7 @@ impl CachedNeedsConditions { .join(if config.host.contains("windows") { "rust-lld.exe" } else { "rust-lld" }) .exists(), + llvm_zstd: llvm_has_libzstd(&config), dlltool: find_dlltool(&config), symlinks: has_symlinks(), } diff --git a/src/tools/compiletest/src/json.rs b/src/tools/compiletest/src/json.rs index 76b83f02b14..0da93dcafa2 100644 --- a/src/tools/compiletest/src/json.rs +++ b/src/tools/compiletest/src/json.rs @@ -1,5 +1,4 @@ //! These structs are a subset of the ones found in `rustc_errors::json`. -//! They are only used for deserialization of JSON output provided by libtest. use std::path::{Path, PathBuf}; use std::str::FromStr; @@ -127,11 +126,10 @@ pub fn extract_rendered(output: &str) -> String { // Ignore the notification. None } else { - print!( - "failed to decode compiler output as json: line: {}\noutput: {}", - line, output - ); - panic!() + // This function is called for both compiler and non-compiler output, + // so if the line isn't recognized as JSON from the compiler then + // just print it as-is. + Some(format!("{line}\n")) } } else { // preserve non-JSON lines, such as ICEs diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 6acf46f9196..7018362af54 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -194,14 +194,8 @@ pub fn parse_config(args: Vec) -> Config { let target = opt_str2(matches.opt_str("target")); let android_cross_path = opt_path(matches, "android-cross-path"); let (cdb, cdb_version) = analyze_cdb(matches.opt_str("cdb"), &target); - let (gdb, gdb_version, gdb_native_rust) = - analyze_gdb(matches.opt_str("gdb"), &target, &android_cross_path); - let (lldb_version, lldb_native_rust) = matches - .opt_str("lldb-version") - .as_deref() - .and_then(extract_lldb_version) - .map(|(v, b)| (Some(v), b)) - .unwrap_or((None, false)); + let (gdb, gdb_version) = analyze_gdb(matches.opt_str("gdb"), &target, &android_cross_path); + let lldb_version = matches.opt_str("lldb-version").as_deref().and_then(extract_lldb_version); let color = match matches.opt_str("color").as_deref() { Some("auto") | None => ColorConfig::AutoColor, Some("always") => ColorConfig::AlwaysColor, @@ -298,9 +292,7 @@ pub fn parse_config(args: Vec) -> Config { cdb_version, gdb, gdb_version, - gdb_native_rust, lldb_version, - lldb_native_rust, llvm_version, system_llvm: matches.opt_present("system-llvm"), android_cross_path, @@ -1035,19 +1027,17 @@ fn extract_cdb_version(full_version_line: &str) -> Option<[u16; 4]> { Some([major, minor, patch, build]) } -/// Returns (Path to GDB, GDB Version, GDB has Rust Support) +/// Returns (Path to GDB, GDB Version) fn analyze_gdb( gdb: Option, target: &str, android_cross_path: &PathBuf, -) -> (Option, Option, bool) { +) -> (Option, Option) { #[cfg(not(windows))] const GDB_FALLBACK: &str = "gdb"; #[cfg(windows)] const GDB_FALLBACK: &str = "gdb.exe"; - const MIN_GDB_WITH_RUST: u32 = 7011010; - let fallback_gdb = || { if is_android_gdb_target(target) { let mut gdb_path = match android_cross_path.to_str() { @@ -1076,12 +1066,10 @@ fn analyze_gdb( let version = match version_line { Some(line) => extract_gdb_version(&line), - None => return (None, None, false), + None => return (None, None), }; - let gdb_native_rust = version.map_or(false, |v| v >= MIN_GDB_WITH_RUST); - - (Some(gdb), version, gdb_native_rust) + (Some(gdb), version) } fn extract_gdb_version(full_version_line: &str) -> Option { @@ -1131,8 +1119,8 @@ fn extract_gdb_version(full_version_line: &str) -> Option { Some(((major * 1000) + minor) * 1000 + patch) } -/// Returns (LLDB version, LLDB is rust-enabled) -fn extract_lldb_version(full_version_line: &str) -> Option<(u32, bool)> { +/// Returns LLDB version +fn extract_lldb_version(full_version_line: &str) -> Option { // Extract the major LLDB version from the given version string. // LLDB version strings are different for Apple and non-Apple platforms. // The Apple variant looks like this: @@ -1149,9 +1137,7 @@ fn extract_lldb_version(full_version_line: &str) -> Option<(u32, bool)> { // There doesn't seem to be a way to correlate the Apple version // with the upstream version, and since the tests were originally // written against Apple versions, we make a fake Apple version by - // multiplying the first number by 100. This is a hack, but - // normally fine because the only non-Apple version we test is - // rust-enabled. + // multiplying the first number by 100. This is a hack. let full_version_line = full_version_line.trim(); @@ -1160,12 +1146,12 @@ fn extract_lldb_version(full_version_line: &str) -> Option<(u32, bool)> { { if let Some(idx) = apple_ver.find(not_a_digit) { let version: u32 = apple_ver[..idx].parse().unwrap(); - return Some((version, full_version_line.contains("rust-enabled"))); + return Some(version); } } else if let Some(lldb_ver) = full_version_line.strip_prefix("lldb version ") { if let Some(idx) = lldb_ver.find(not_a_digit) { let version: u32 = lldb_ver[..idx].parse().ok()?; - return Some((version * 100, full_version_line.contains("rust-enabled"))); + return Some(version * 100); } } None diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 59fce44d1c7..eca21e55989 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -856,22 +856,10 @@ impl<'test> TestCx<'test> { } fn run_debuginfo_gdb_test_no_opt(&self) { - let prefixes = if self.config.gdb_native_rust { - // GDB with Rust - static PREFIXES: &[&str] = &["gdb", "gdbr"]; - println!("NOTE: compiletest thinks it is using GDB with native rust support"); - PREFIXES - } else { - // Generic GDB - static PREFIXES: &[&str] = &["gdb", "gdbg"]; - println!("NOTE: compiletest thinks it is using GDB without native rust support"); - PREFIXES - }; - let dbg_cmds = DebuggerCommands::parse_from( &self.testpaths.file, self.config, - prefixes, + &["gdb"], self.revision, ) .unwrap_or_else(|e| self.fatal(&e)); @@ -1053,9 +1041,7 @@ impl<'test> TestCx<'test> { .push_str(&format!("file {}\n", exe_file.to_str().unwrap().replace(r"\", r"\\"))); // Force GDB to print values in the Rust format. - if self.config.gdb_native_rust { - script_str.push_str("set language rust\n"); - } + script_str.push_str("set language rust\n"); // Add line breakpoints for line in &dbg_cmds.breakpoint_lines { @@ -1140,21 +1126,11 @@ impl<'test> TestCx<'test> { } } - let prefixes = if self.config.lldb_native_rust { - static PREFIXES: &[&str] = &["lldb", "lldbr"]; - println!("NOTE: compiletest thinks it is using LLDB with native rust support"); - PREFIXES - } else { - static PREFIXES: &[&str] = &["lldb", "lldbg"]; - println!("NOTE: compiletest thinks it is using LLDB without native rust support"); - PREFIXES - }; - // Parse debugger commands etc from test files let dbg_cmds = DebuggerCommands::parse_from( &self.testpaths.file, self.config, - prefixes, + &["lldb"], self.revision, ) .unwrap_or_else(|e| self.fatal(&e)); diff --git a/src/tools/compiletest/src/tests.rs b/src/tools/compiletest/src/tests.rs index 4292f234adc..7c2e7b0f023 100644 --- a/src/tools/compiletest/src/tests.rs +++ b/src/tools/compiletest/src/tests.rs @@ -48,12 +48,12 @@ fn test_extract_gdb_version() { #[test] fn test_extract_lldb_version() { // Apple variants - assert_eq!(extract_lldb_version("LLDB-179.5"), Some((179, false))); - assert_eq!(extract_lldb_version("lldb-300.2.51"), Some((300, false))); + assert_eq!(extract_lldb_version("LLDB-179.5"), Some(179)); + assert_eq!(extract_lldb_version("lldb-300.2.51"), Some(300)); // Upstream versions - assert_eq!(extract_lldb_version("lldb version 6.0.1"), Some((600, false))); - assert_eq!(extract_lldb_version("lldb version 9.0.0"), Some((900, false))); + assert_eq!(extract_lldb_version("lldb version 6.0.1"), Some(600)); + assert_eq!(extract_lldb_version("lldb version 9.0.0"), Some(900)); } #[test] diff --git a/src/tools/generate-windows-sys/src/main.rs b/src/tools/generate-windows-sys/src/main.rs index fe1b1bd5ceb..6dbf29d957f 100644 --- a/src/tools/generate-windows-sys/src/main.rs +++ b/src/tools/generate-windows-sys/src/main.rs @@ -35,7 +35,6 @@ fn main() -> Result<(), Box> { let mut f = std::fs::File::options().append(true).open("windows_sys.rs")?; f.write_all(ARM32_SHIM.as_bytes())?; writeln!(&mut f, "// ignore-tidy-filelength")?; - writeln!(&mut f, "use super::windows_targets;")?; Ok(()) } diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs index 72448c1180a..fa77ab1e011 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs @@ -6,8 +6,10 @@ //! script is to check all relative links in our documentation to make sure they //! actually point to a valid place. //! -//! Currently this doesn't actually do any HTML parsing or anything fancy like -//! that, it just has a simple "regex" to search for `href` and `id` tags. +//! Currently uses a combination of HTML parsing to +//! extract the `href` and `id` attributes, +//! and regex search on the orignal markdown to handle intra-doc links. +//! //! These values are then translated to file URLs if possible and then the //! destination is asserted to exist. //! diff --git a/src/tools/lint-docs/src/lib.rs b/src/tools/lint-docs/src/lib.rs index e0aef13ca79..72bb9db7e74 100644 --- a/src/tools/lint-docs/src/lib.rs +++ b/src/tools/lint-docs/src/lib.rs @@ -444,6 +444,7 @@ impl<'a> LintExtractor<'a> { let mut cmd = Command::new(self.rustc_path); if options.contains(&"edition2024") { cmd.arg("--edition=2024"); + cmd.arg("-Zunstable-options"); } else if options.contains(&"edition2021") { cmd.arg("--edition=2021"); } else if options.contains(&"edition2018") { diff --git a/src/tools/miri/.cargo/config.toml b/src/tools/miri/.cargo/config.toml new file mode 100644 index 00000000000..42e7c2c4818 --- /dev/null +++ b/src/tools/miri/.cargo/config.toml @@ -0,0 +1,9 @@ +[unstable] +profile-rustflags = true + +# Add back the containing directory of the packages we have to refer to using --manifest-path. +# Per-package profiles avoid adding this to build dependencies. +[profile.dev.package."cargo-miri"] +rustflags = ["--remap-path-prefix", "=cargo-miri"] +[profile.dev.package."miri-script"] +rustflags = ["--remap-path-prefix", "=miri-script"] diff --git a/src/tools/miri/.github/workflows/ci.yml b/src/tools/miri/.github/workflows/ci.yml index fc4e484fa38..22c833a5488 100644 --- a/src/tools/miri/.github/workflows/ci.yml +++ b/src/tools/miri/.github/workflows/ci.yml @@ -60,7 +60,7 @@ jobs: - name: clippy (all features) run: ./miri clippy --all-features -- -D warnings - name: rustdoc - run: RUSTDOCFLAGS="-Dwarnings" ./miri cargo doc --document-private-items + run: RUSTDOCFLAGS="-Dwarnings" ./miri doc --document-private-items # These jobs doesn't actually test anything, but they're only used to tell # bors the build completed, as there is no practical way to detect when a @@ -123,6 +123,8 @@ jobs: run: | git config --global user.name 'The Miri Cronjob Bot' git config --global user.email 'miri@cron.bot' + - name: Install nightly toolchain + run: rustup toolchain install nightly --profile minimal - name: get changes from rustc run: ./miri rustc-pull - name: Install rustup-toolchain-install-master diff --git a/src/tools/miri/.github/workflows/setup/action.yml b/src/tools/miri/.github/workflows/setup/action.yml index 8f54b5b8d81..bf5749a7b17 100644 --- a/src/tools/miri/.github/workflows/setup/action.yml +++ b/src/tools/miri/.github/workflows/setup/action.yml @@ -35,6 +35,10 @@ runs: run: cargo install -f rustup-toolchain-install-master hyperfine shell: bash + - name: Install nightly toolchain + run: rustup toolchain install nightly --profile minimal + shell: bash + - name: Install "master" toolchain run: | if [[ ${{ github.event_name }} == 'schedule' ]]; then diff --git a/src/tools/miri/CONTRIBUTING.md b/src/tools/miri/CONTRIBUTING.md index 9067cbc6032..ca03a9b16e3 100644 --- a/src/tools/miri/CONTRIBUTING.md +++ b/src/tools/miri/CONTRIBUTING.md @@ -8,10 +8,43 @@ find useful. Check out the issues on this GitHub repository for some ideas. In particular, look for the green `E-*` labels which mark issues that should be rather well-suited for onboarding. For more ideas or help with hacking on Miri, you can -contact us (`oli-obk` and `RalfJ`) on the [Rust Zulip]. +contact us on the [Rust Zulip]. See the [Rust website](https://www.rust-lang.org/governance/teams/compiler#team-miri) +for a list of Miri maintainers. [Rust Zulip]: https://rust-lang.zulipchat.com +### Larger-scale contributions + +If you are thinking about making a larger-scale contribution -- in particular anything that needs +more than can reasonably fit in a single PR to be feature-complete -- then please talk to us before +writing significant amounts of code. Generally, we will ask that you follow a three-step "project" +process for such contributions: + +1. Clearly define the **goal** of the project. This defines the scope of the project, i.e. which + part of which APIs should be supported. If this involves functions that expose a big API surface + with lots of flags, the project may want to support only a tiny subset of flags; that should be + documented. A good way to express the goal is with one or more test cases that Miri should be + able to successfully execute when the project is completed. It is a good idea to get feedback + from team members already at this stage to ensure that the project is reasonably scoped and + aligns with our interests. +2. Make a **design** for how to realize the goal. A larger project will likely have to do global + changes to Miri, like adding new global state to the `Machine` type or new methods to the + `FileDescription` trait. Often we have to iterate on those changes, which can quite substantially + change how the final implementation looks like. + + The design should be reasonably concrete, i.e. for new global state or methods the corresponding + Rust types and method signatures should be spelled out. We realize that it can be hard to make a + design without doing implementation work, in particular if you are not yet familiar with the + codebase. Doing draft implementations in phase 2 of this process is perfectly fine, just please + be aware that we might request fundamental changes that can require significantly reworking what + you already did. If you open a PR in this stage, please clearly indicate that this project is + still in the design stage. + +3. Finish the **implementation** and have it reviewed. + +This process is largely informal, and its primary goal is to more clearly communicate expectations. +Please get in touch with us if you have any questions! + ## Preparing the build environment Miri heavily relies on internal and unstable rustc interfaces to execute MIR, @@ -173,24 +206,24 @@ to `.vscode/settings.json` in your local Miri clone: "cargo-miri/Cargo.toml", "miri-script/Cargo.toml", ], + "rust-analyzer.check.invocationLocation": "root", + "rust-analyzer.check.invocationStrategy": "once", "rust-analyzer.check.overrideCommand": [ "env", "MIRI_AUTO_OPS=no", "./miri", - "cargo", "clippy", // make this `check` when working with a locally built rustc "--message-format=json", - "--all-targets", ], // Contrary to what the name suggests, this also affects proc macros. + "rust-analyzer.cargo.buildScripts.invocationLocation": "root", + "rust-analyzer.cargo.buildScripts.invocationStrategy": "once", "rust-analyzer.cargo.buildScripts.overrideCommand": [ "env", "MIRI_AUTO_OPS=no", "./miri", - "cargo", "check", "--message-format=json", - "--all-targets", ], } ``` @@ -309,6 +342,7 @@ anyone but Miri itself. They are used to communicate between different Miri binaries, and as such worth documenting: * `CARGO_EXTRA_FLAGS` is understood by `./miri` and passed to all host cargo invocations. + It is reserved for CI usage; setting the wrong flags this way can easily confuse the script. * `MIRI_BE_RUSTC` can be set to `host` or `target`. It tells the Miri driver to actually not interpret the code but compile it like rustc would. With `target`, Miri sets some compiler flags to prepare the code for interpretation; with `host`, this is not done. diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml index e12f3f9012f..4b7f3483ff7 100644 --- a/src/tools/miri/Cargo.toml +++ b/src/tools/miri/Cargo.toml @@ -20,7 +20,7 @@ doctest = false # and no doc tests [dependencies] getrandom = { version = "0.2", features = ["std"] } rand = "0.8" -smallvec = "1.7" +smallvec = { version = "1.7", features = ["drain_filter"] } aes = { version = "0.8.3", features = ["hazmat"] } measureme = "11" ctrlc = "3.2.5" diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md index a0bff386a71..5821adb96ce 100644 --- a/src/tools/miri/README.md +++ b/src/tools/miri/README.md @@ -414,10 +414,6 @@ to Miri failing to detect cases of undefined behavior in a program. being allocated or freed. This helps in debugging memory leaks and use after free bugs. Specifying this argument multiple times does not overwrite the previous values, instead it appends its values to the list. Listing an id multiple times has no effect. -* `-Zmiri-track-call-id=,,...` shows a backtrace when the given call ids are - assigned to a stack frame. This helps in debugging UB related to Stacked - Borrows "protectors". Specifying this argument multiple times does not overwrite the previous - values, instead it appends its values to the list. Listing an id multiple times has no effect. * `-Zmiri-track-pointer-tag=,,...` shows a backtrace when a given pointer tag is created and when (if ever) it is popped from a borrow stack (which is where the tag becomes invalid and any future use of it will error). This helps you in finding out why UB is diff --git a/src/tools/miri/cargo-miri/miri b/src/tools/miri/cargo-miri/miri deleted file mode 100755 index cf3ad06788a..00000000000 --- a/src/tools/miri/cargo-miri/miri +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -# RA invokes `./miri cargo ...` for each workspace, so we need to forward that to the main `miri` -# script. See . -exec "$(dirname "$0")"/../miri "$@" diff --git a/src/tools/miri/cargo-miri/src/util.rs b/src/tools/miri/cargo-miri/src/util.rs index 5f2794e2244..56f38de8de6 100644 --- a/src/tools/miri/cargo-miri/src/util.rs +++ b/src/tools/miri/cargo-miri/src/util.rs @@ -93,12 +93,9 @@ pub fn find_miri() -> PathBuf { if let Some(path) = env::var_os("MIRI") { return path.into(); } + // Assume it is in the same directory as ourselves. let mut path = std::env::current_exe().expect("current executable path invalid"); - if cfg!(windows) { - path.set_file_name("miri.exe"); - } else { - path.set_file_name("miri"); - } + path.set_file_name(format!("miri{}", env::consts::EXE_SUFFIX)); path } diff --git a/src/tools/miri/ci/ci.sh b/src/tools/miri/ci/ci.sh index 3e90ecc5c03..1f66b6fa776 100755 --- a/src/tools/miri/ci/ci.sh +++ b/src/tools/miri/ci/ci.sh @@ -150,8 +150,8 @@ case $HOST_TARGET in UNIX="panic/panic panic/unwind concurrency/simple atomic libc-mem libc-misc libc-random env num_cpus" # the things that are very similar across all Unixes, and hence easily supported there TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC $UNIX threadname libc-time fs TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC $UNIX threadname libc-time fs - TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC $UNIX threadname pthread-sync available-parallelism libc-time - TEST_TARGET=x86_64-pc-solaris run_tests_minimal $BASIC $UNIX threadname pthread-sync available-parallelism libc-time + TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC $UNIX threadname pthread-sync available-parallelism libc-time tls + TEST_TARGET=x86_64-pc-solaris run_tests_minimal $BASIC $UNIX threadname pthread-sync available-parallelism libc-time tls TEST_TARGET=aarch64-linux-android run_tests_minimal $BASIC $UNIX TEST_TARGET=wasm32-wasip2 run_tests_minimal empty_main wasm heap_alloc libc-mem TEST_TARGET=wasm32-unknown-unknown run_tests_minimal empty_main wasm diff --git a/src/tools/miri/miri b/src/tools/miri/miri index 07383bb59eb..5d07ad9e249 100755 --- a/src/tools/miri/miri +++ b/src/tools/miri/miri @@ -1,8 +1,15 @@ #!/usr/bin/env bash set -e +# We want to call the binary directly, so we need to know where it ends up. +MIRI_SCRIPT_TARGET_DIR="$(dirname "$0")"/miri-script/target +# If stdout is not a terminal and we are not on CI, assume that we are being invoked by RA, and use JSON output. +if ! [ -t 1 ] && [ -z "$CI" ]; then + MESSAGE_FORMAT="--message-format=json" +fi +# We need a nightly toolchain, for the `profile-rustflags` cargo feature. +cargo +nightly build $CARGO_EXTRA_FLAGS --manifest-path "$(dirname "$0")"/miri-script/Cargo.toml \ + -q --target-dir "$MIRI_SCRIPT_TARGET_DIR" $MESSAGE_FORMAT || \ + ( echo "Failed to build miri-script. Is the 'nightly' toolchain installed?"; exit 1 ) # Instead of doing just `cargo run --manifest-path .. $@`, we invoke miri-script binary directly. Invoking `cargo run` goes through # rustup (that sets it's own environmental variables), which is undesirable. -MIRI_SCRIPT_TARGET_DIR="$(dirname "$0")"/miri-script/target -cargo +stable build $CARGO_EXTRA_FLAGS -q --target-dir "$MIRI_SCRIPT_TARGET_DIR" --manifest-path "$(dirname "$0")"/miri-script/Cargo.toml || \ - ( echo "Failed to build miri-script. Is the 'stable' toolchain installed?"; exit 1 ) "$MIRI_SCRIPT_TARGET_DIR"/debug/miri-script "$@" diff --git a/src/tools/miri/miri-script/miri b/src/tools/miri/miri-script/miri deleted file mode 100755 index cf3ad06788a..00000000000 --- a/src/tools/miri/miri-script/miri +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -# RA invokes `./miri cargo ...` for each workspace, so we need to forward that to the main `miri` -# script. See . -exec "$(dirname "$0")"/../miri "$@" diff --git a/src/tools/miri/miri-script/src/commands.rs b/src/tools/miri/miri-script/src/commands.rs index fc205040baf..a9a80175901 100644 --- a/src/tools/miri/miri-script/src/commands.rs +++ b/src/tools/miri/miri-script/src/commands.rs @@ -1,12 +1,12 @@ use std::env; use std::ffi::{OsStr, OsString}; use std::io::Write; +use std::net; use std::ops::Not; use std::ops::Range; use std::path::PathBuf; use std::process; -use std::thread; -use std::time; +use std::time::Duration; use anyhow::{anyhow, bail, Context, Result}; use path_macro::path; @@ -19,9 +19,10 @@ use crate::Command; /// Used for rustc syncs. const JOSH_FILTER: &str = ":rev(75dd959a3a40eb5b4574f8d2e23aa6efbeb33573:prefix=src/tools/miri):/src/tools/miri"; -const JOSH_PORT: &str = "42042"; +const JOSH_PORT: u16 = 42042; impl MiriEnv { + /// Prepares the environment: builds miri and cargo-miri and a sysroot. /// Returns the location of the sysroot. /// /// If the target is None the sysroot will be built for the host machine. @@ -34,12 +35,10 @@ impl MiriEnv { // Sysroot already set, use that. return Ok(miri_sysroot.into()); } - let manifest_path = path!(self.miri_dir / "cargo-miri" / "Cargo.toml"); - let Self { toolchain, cargo_extra_flags, .. } = &self; // Make sure everything is built. Also Miri itself. - self.build(path!(self.miri_dir / "Cargo.toml"), &[], quiet)?; - self.build(&manifest_path, &[], quiet)?; + self.build(".", &[], quiet)?; + self.build("cargo-miri", &[], quiet)?; let target_flag = if let Some(target) = &target { vec![OsStr::new("--target"), target.as_ref()] @@ -56,10 +55,12 @@ impl MiriEnv { eprintln!(); } - let mut cmd = cmd!(self.sh, - "cargo +{toolchain} --quiet run {cargo_extra_flags...} --manifest-path {manifest_path} -- - miri setup --print-sysroot {target_flag...}" - ); + let mut cmd = self + .cargo_cmd("cargo-miri", "run") + .arg("--quiet") + .arg("--") + .args(&["miri", "setup", "--print-sysroot"]) + .args(target_flag); cmd.set_quiet(quiet); let output = cmd.read()?; self.sh.set_var("MIRI_SYSROOT", &output); @@ -105,13 +106,11 @@ impl Command { let mut cmd = process::Command::new("josh-proxy"); cmd.arg("--local").arg(local_dir); cmd.arg("--remote").arg("https://github.com"); - cmd.arg("--port").arg(JOSH_PORT); + cmd.arg("--port").arg(JOSH_PORT.to_string()); cmd.arg("--no-background"); cmd.stdout(process::Stdio::null()); cmd.stderr(process::Stdio::null()); let josh = cmd.spawn().context("failed to start josh-proxy, make sure it is installed")?; - // Give it some time so hopefully the port is open. (100ms was not enough.) - thread::sleep(time::Duration::from_millis(200)); // Create a wrapper that stops it on drop. struct Josh(process::Child); @@ -125,7 +124,7 @@ impl Command { .output() .expect("failed to SIGINT josh-proxy"); // Sadly there is no "wait with timeout"... so we just give it some time to finish. - thread::sleep(time::Duration::from_millis(100)); + std::thread::sleep(Duration::from_millis(100)); // Now hopefully it is gone. if self.0.try_wait().expect("failed to wait for josh-proxy").is_some() { return; @@ -139,7 +138,20 @@ impl Command { } } - Ok(Josh(josh)) + // Wait until the port is open. We try every 10ms until 1s passed. + for _ in 0..100 { + // This will generally fail immediately when the port is still closed. + let josh_ready = net::TcpStream::connect_timeout( + &net::SocketAddr::from(([127, 0, 0, 1], JOSH_PORT)), + Duration::from_millis(1), + ); + if josh_ready.is_ok() { + return Ok(Josh(josh)); + } + // Not ready yet. + std::thread::sleep(Duration::from_millis(10)); + } + bail!("Even after waiting for 1s, josh-proxy is still not available.") } pub fn exec(self) -> Result<()> { @@ -151,8 +163,8 @@ impl Command { | Command::Test { .. } | Command::Run { .. } | Command::Fmt { .. } - | Command::Clippy { .. } - | Command::Cargo { .. } => Self::auto_actions()?, + | Command::Doc { .. } + | Command::Clippy { .. } => Self::auto_actions()?, | Command::Toolchain { .. } | Command::Bench { .. } | Command::RustcPull { .. } @@ -166,9 +178,9 @@ impl Command { Command::Test { bless, flags, target } => Self::test(bless, flags, target), Command::Run { dep, verbose, many_seeds, target, edition, flags } => Self::run(dep, verbose, many_seeds, target, edition, flags), + Command::Doc { flags } => Self::doc(flags), Command::Fmt { flags } => Self::fmt(flags), Command::Clippy { flags } => Self::clippy(flags), - Command::Cargo { flags } => Self::cargo(flags), Command::Bench { target, benches } => Self::bench(target, benches), Command::Toolchain { flags } => Self::toolchain(flags), Command::RustcPull { commit } => Self::rustc_pull(commit.clone()), @@ -236,6 +248,8 @@ impl Command { } // Make sure josh is running. let josh = Self::start_josh()?; + let josh_url = + format!("http://localhost:{JOSH_PORT}/rust-lang/rust.git@{commit}{JOSH_FILTER}.git"); // Update rust-version file. As a separate commit, since making it part of // the merge has confused the heck out of josh in the past. @@ -250,7 +264,7 @@ impl Command { .context("FAILED to commit rust-version file, something went wrong")?; // Fetch given rustc commit. - cmd!(sh, "git fetch http://localhost:{JOSH_PORT}/rust-lang/rust.git@{commit}{JOSH_FILTER}.git") + cmd!(sh, "git fetch {josh_url}") .run() .inspect_err(|_| { // Try to un-do the previous `git commit`, to leave the repo in the state we found it. @@ -294,6 +308,8 @@ impl Command { } // Make sure josh is running. let josh = Self::start_josh()?; + let josh_url = + format!("http://localhost:{JOSH_PORT}/{github_user}/rust.git{JOSH_FILTER}.git"); // Find a repo we can do our preparation in. if let Ok(rustc_git) = env::var("RUSTC_GIT") { @@ -338,20 +354,11 @@ impl Command { // Do the actual push. sh.change_dir(miri_dir()?); println!("Pushing miri changes..."); - cmd!( - sh, - "git push http://localhost:{JOSH_PORT}/{github_user}/rust.git{JOSH_FILTER}.git HEAD:{branch}" - ) - .run()?; + cmd!(sh, "git push {josh_url} HEAD:{branch}").run()?; println!(); // Do a round-trip check to make sure the push worked as expected. - cmd!( - sh, - "git fetch http://localhost:{JOSH_PORT}/{github_user}/rust.git{JOSH_FILTER}.git {branch}" - ) - .ignore_stderr() - .read()?; + cmd!(sh, "git fetch {josh_url} {branch}").ignore_stderr().read()?; let head = cmd!(sh, "git rev-parse HEAD").read()?; let fetch_head = cmd!(sh, "git rev-parse FETCH_HEAD").read()?; if head != fetch_head { @@ -427,39 +434,37 @@ impl Command { fn build(flags: Vec) -> Result<()> { let e = MiriEnv::new()?; - e.build(path!(e.miri_dir / "Cargo.toml"), &flags, /* quiet */ false)?; - e.build(path!(e.miri_dir / "cargo-miri" / "Cargo.toml"), &flags, /* quiet */ false)?; + e.build(".", &flags, /* quiet */ false)?; + e.build("cargo-miri", &flags, /* quiet */ false)?; Ok(()) } fn check(flags: Vec) -> Result<()> { let e = MiriEnv::new()?; - e.check(path!(e.miri_dir / "Cargo.toml"), &flags)?; - e.check(path!(e.miri_dir / "cargo-miri" / "Cargo.toml"), &flags)?; + e.check(".", &flags)?; + e.check("cargo-miri", &flags)?; + Ok(()) + } + + fn doc(flags: Vec) -> Result<()> { + let e = MiriEnv::new()?; + e.doc(".", &flags)?; + e.doc("cargo-miri", &flags)?; Ok(()) } fn clippy(flags: Vec) -> Result<()> { let e = MiriEnv::new()?; - e.clippy(path!(e.miri_dir / "Cargo.toml"), &flags)?; - e.clippy(path!(e.miri_dir / "cargo-miri" / "Cargo.toml"), &flags)?; - e.clippy(path!(e.miri_dir / "miri-script" / "Cargo.toml"), &flags)?; - Ok(()) - } - - fn cargo(flags: Vec) -> Result<()> { - let e = MiriEnv::new()?; - let toolchain = &e.toolchain; - // We carefully kept the working dir intact, so this will run cargo *on the workspace in the - // current working dir*, not on the main Miri workspace. That is exactly what RA needs. - cmd!(e.sh, "cargo +{toolchain} {flags...}").run()?; + e.clippy(".", &flags)?; + e.clippy("cargo-miri", &flags)?; + e.clippy("miri-script", &flags)?; Ok(()) } fn test(bless: bool, mut flags: Vec, target: Option) -> Result<()> { let mut e = MiriEnv::new()?; - // Prepare a sysroot. + // Prepare a sysroot. (Also builds cargo-miri, which we need.) e.build_miri_sysroot(/* quiet */ false, target.as_deref())?; // Forward information to test harness. @@ -476,7 +481,7 @@ impl Command { // Then test, and let caller control flags. // Only in root project as `cargo-miri` has no tests. - e.test(path!(e.miri_dir / "Cargo.toml"), &flags)?; + e.test(".", &flags)?; Ok(()) } @@ -504,32 +509,27 @@ impl Command { early_flags.push("--edition".into()); early_flags.push(edition.as_deref().unwrap_or("2021").into()); - // Prepare a sysroot, add it to the flags. + // Prepare a sysroot, add it to the flags. (Also builds cargo-miri, which we need.) let miri_sysroot = e.build_miri_sysroot(/* quiet */ !verbose, target.as_deref())?; early_flags.push("--sysroot".into()); early_flags.push(miri_sysroot.into()); // Compute everything needed to run the actual command. Also add MIRIFLAGS. - let miri_manifest = path!(e.miri_dir / "Cargo.toml"); let miri_flags = e.sh.var("MIRIFLAGS").unwrap_or_default(); let miri_flags = flagsplit(&miri_flags); - let toolchain = &e.toolchain; - let extra_flags = &e.cargo_extra_flags; let quiet_flag = if verbose { None } else { Some("--quiet") }; // This closure runs the command with the given `seed_flag` added between the MIRIFLAGS and // the `flags` given on the command-line. - let run_miri = |sh: &Shell, seed_flag: Option| -> Result<()> { + let run_miri = |e: &MiriEnv, seed_flag: Option| -> Result<()> { // The basic command that executes the Miri driver. let mut cmd = if dep { - cmd!( - sh, - "cargo +{toolchain} {quiet_flag...} test {extra_flags...} --manifest-path {miri_manifest} --test ui -- --miri-run-dep-mode" - ) + e.cargo_cmd(".", "test") + .args(&["--test", "ui"]) + .args(quiet_flag) + .arg("--") + .args(&["--miri-run-dep-mode"]) } else { - cmd!( - sh, - "cargo +{toolchain} {quiet_flag...} run {extra_flags...} --manifest-path {miri_manifest} --" - ) + e.cargo_cmd(".", "run").args(quiet_flag).arg("--") }; cmd.set_quiet(!verbose); // Add Miri flags @@ -545,14 +545,14 @@ impl Command { }; // Run the closure once or many times. if let Some(seed_range) = many_seeds { - e.run_many_times(seed_range, |sh, seed| { + e.run_many_times(seed_range, |e, seed| { eprintln!("Trying seed: {seed}"); - run_miri(sh, Some(format!("-Zmiri-seed={seed}"))).inspect_err(|_| { + run_miri(e, Some(format!("-Zmiri-seed={seed}"))).inspect_err(|_| { eprintln!("FAILING SEED: {seed}"); }) })?; } else { - run_miri(&e.sh, None)?; + run_miri(&e, None)?; } Ok(()) } @@ -579,6 +579,6 @@ impl Command { .filter_ok(|item| item.file_type().is_file()) .map_ok(|item| item.into_path()); - e.format_files(files, &e.toolchain[..], &config_path, &flags) + e.format_files(files, &config_path, &flags) } } diff --git a/src/tools/miri/miri-script/src/main.rs b/src/tools/miri/miri-script/src/main.rs index c4f0d808d93..92148237107 100644 --- a/src/tools/miri/miri-script/src/main.rs +++ b/src/tools/miri/miri-script/src/main.rs @@ -48,6 +48,11 @@ pub enum Command { /// Flags that are passed through to `miri`. flags: Vec, }, + /// Build documentation + Doc { + /// Flags that are passed through to `cargo doc`. + flags: Vec, + }, /// Format all sources and tests. Fmt { /// Flags that are passed through to `rustfmt`. @@ -58,9 +63,6 @@ pub enum Command { /// Flags that are passed through to `cargo clippy`. flags: Vec, }, - /// Runs just `cargo ` with the Miri-specific environment variables. - /// Mainly meant to be invoked by rust-analyzer. - Cargo { flags: Vec }, /// Runs the benchmarks from bench-cargo-miri in hyperfine. hyperfine needs to be installed. Bench { target: Option, @@ -151,6 +153,7 @@ fn main() -> Result<()> { let command = match args.next_raw().as_deref() { Some("build") => Command::Build { flags: args.remainder() }, Some("check") => Command::Check { flags: args.remainder() }, + Some("doc") => Command::Doc { flags: args.remainder() }, Some("test") => { let mut target = None; let mut bless = false; @@ -205,7 +208,6 @@ fn main() -> Result<()> { } Some("fmt") => Command::Fmt { flags: args.remainder() }, Some("clippy") => Command::Clippy { flags: args.remainder() }, - Some("cargo") => Command::Cargo { flags: args.remainder() }, Some("install") => Command::Install { flags: args.remainder() }, Some("bench") => { let mut target = None; diff --git a/src/tools/miri/miri-script/src/util.rs b/src/tools/miri/miri-script/src/util.rs index e1b77be192e..35c604b407e 100644 --- a/src/tools/miri/miri-script/src/util.rs +++ b/src/tools/miri/miri-script/src/util.rs @@ -7,7 +7,7 @@ use std::thread; use anyhow::{anyhow, Context, Result}; use dunce::canonicalize; use path_macro::path; -use xshell::{cmd, Shell}; +use xshell::{cmd, Cmd, Shell}; pub fn miri_dir() -> std::io::Result { const MIRI_SCRIPT_ROOT_DIR: &str = env!("CARGO_MANIFEST_DIR"); @@ -28,13 +28,14 @@ pub fn flagsplit(flags: &str) -> Vec { } /// Some extra state we track for building Miri, such as the right RUSTFLAGS. +#[derive(Clone)] pub struct MiriEnv { /// miri_dir is the root of the miri repository checkout we are working in. pub miri_dir: PathBuf, /// active_toolchain is passed as `+toolchain` argument to cargo/rustc invocations. - pub toolchain: String, + toolchain: String, /// Extra flags to pass to cargo. - pub cargo_extra_flags: Vec, + cargo_extra_flags: Vec, /// The rustc sysroot pub sysroot: PathBuf, /// The shell we use. @@ -54,15 +55,14 @@ impl MiriEnv { // Determine some toolchain properties if !libdir.exists() { - println!("Something went wrong determining the library dir."); - println!("I got {} but that does not exist.", libdir.display()); - println!("Please report a bug at https://github.com/rust-lang/miri/issues."); + eprintln!("Something went wrong determining the library dir."); + eprintln!("I got {} but that does not exist.", libdir.display()); + eprintln!("Please report a bug at https://github.com/rust-lang/miri/issues."); std::process::exit(2); } - // Share target dir between `miri` and `cargo-miri`. - let target_dir = std::env::var_os("CARGO_TARGET_DIR") - .unwrap_or_else(|| path!(miri_dir / "target").into()); - sh.set_var("CARGO_TARGET_DIR", target_dir); + + // Hard-code the target dir, since we rely on all binaries ending up in the same spot. + sh.set_var("CARGO_TARGET_DIR", path!(miri_dir / "target")); // We configure dev builds to not be unusably slow. let devel_opt_level = @@ -91,61 +91,73 @@ impl MiriEnv { // Get extra flags for cargo. let cargo_extra_flags = std::env::var("CARGO_EXTRA_FLAGS").unwrap_or_default(); let cargo_extra_flags = flagsplit(&cargo_extra_flags); + if cargo_extra_flags.iter().any(|a| a == "--release" || a.starts_with("--profile")) { + // This makes binaries end up in different paths, let's not do that. + eprintln!( + "Passing `--release` or `--profile` in `CARGO_EXTRA_FLAGS` will totally confuse miri-script, please don't do that." + ); + std::process::exit(1); + } Ok(MiriEnv { miri_dir, toolchain, sh, sysroot, cargo_extra_flags }) } + pub fn cargo_cmd(&self, crate_dir: impl AsRef, cmd: &str) -> Cmd<'_> { + let MiriEnv { toolchain, cargo_extra_flags, .. } = self; + let manifest_path = path!(self.miri_dir / crate_dir.as_ref() / "Cargo.toml"); + cmd!( + self.sh, + "cargo +{toolchain} {cmd} {cargo_extra_flags...} --manifest-path {manifest_path}" + ) + } + pub fn install_to_sysroot( &self, path: impl AsRef, args: impl IntoIterator>, ) -> Result<()> { let MiriEnv { sysroot, toolchain, cargo_extra_flags, .. } = self; + let path = path!(self.miri_dir / path.as_ref()); // Install binaries to the miri toolchain's `sysroot` so they do not interact with other toolchains. + // (Not using `cargo_cmd` as `install` is special and doesn't use `--manifest-path`.) cmd!(self.sh, "cargo +{toolchain} install {cargo_extra_flags...} --path {path} --force --root {sysroot} {args...}").run()?; Ok(()) } - pub fn build( - &self, - manifest_path: impl AsRef, - args: &[String], - quiet: bool, - ) -> Result<()> { - let MiriEnv { toolchain, cargo_extra_flags, .. } = self; + pub fn build(&self, crate_dir: impl AsRef, args: &[String], quiet: bool) -> Result<()> { let quiet_flag = if quiet { Some("--quiet") } else { None }; // We build the tests as well, (a) to avoid having rebuilds when building the tests later // and (b) to have more parallelism during the build of Miri and its tests. - let mut cmd = cmd!( - self.sh, - "cargo +{toolchain} build --bins --tests {cargo_extra_flags...} --manifest-path {manifest_path} {quiet_flag...} {args...}" - ); + // This means `./miri run` without `--dep` will build Miri twice (for the sysroot with + // dev-dependencies, and then for running without dev-dependencies), but the way more common + // `./miri test` will avoid building Miri twice. + let mut cmd = self + .cargo_cmd(crate_dir, "build") + .args(&["--bins", "--tests"]) + .args(quiet_flag) + .args(args); cmd.set_quiet(quiet); cmd.run()?; Ok(()) } - pub fn check(&self, manifest_path: impl AsRef, args: &[String]) -> Result<()> { - let MiriEnv { toolchain, cargo_extra_flags, .. } = self; - cmd!(self.sh, "cargo +{toolchain} check {cargo_extra_flags...} --manifest-path {manifest_path} --all-targets {args...}") - .run()?; + pub fn check(&self, crate_dir: impl AsRef, args: &[String]) -> Result<()> { + self.cargo_cmd(crate_dir, "check").arg("--all-targets").args(args).run()?; Ok(()) } - pub fn clippy(&self, manifest_path: impl AsRef, args: &[String]) -> Result<()> { - let MiriEnv { toolchain, cargo_extra_flags, .. } = self; - cmd!(self.sh, "cargo +{toolchain} clippy {cargo_extra_flags...} --manifest-path {manifest_path} --all-targets {args...}") - .run()?; + pub fn doc(&self, crate_dir: impl AsRef, args: &[String]) -> Result<()> { + self.cargo_cmd(crate_dir, "doc").args(args).run()?; Ok(()) } - pub fn test(&self, manifest_path: impl AsRef, args: &[String]) -> Result<()> { - let MiriEnv { toolchain, cargo_extra_flags, .. } = self; - cmd!( - self.sh, - "cargo +{toolchain} test {cargo_extra_flags...} --manifest-path {manifest_path} {args...}" - ) - .run()?; + pub fn clippy(&self, crate_dir: impl AsRef, args: &[String]) -> Result<()> { + self.cargo_cmd(crate_dir, "clippy").arg("--all-targets").args(args).run()?; + Ok(()) + } + + pub fn test(&self, crate_dir: impl AsRef, args: &[String]) -> Result<()> { + self.cargo_cmd(crate_dir, "test").args(args).run()?; Ok(()) } @@ -155,7 +167,6 @@ impl MiriEnv { pub fn format_files( &self, files: impl Iterator>, - toolchain: &str, config_path: &Path, flags: &[String], ) -> anyhow::Result<()> { @@ -166,6 +177,7 @@ impl MiriEnv { // Format in batches as not all our files fit into Windows' command argument limit. for batch in &files.chunks(256) { // Build base command. + let toolchain = &self.toolchain; let mut cmd = cmd!( self.sh, "rustfmt +{toolchain} --edition=2021 --config-path {config_path} --unstable-features --skip-children {flags...}" @@ -197,7 +209,7 @@ impl MiriEnv { pub fn run_many_times( &self, range: Range, - run: impl Fn(&Shell, u32) -> Result<()> + Sync, + run: impl Fn(&Self, u32) -> Result<()> + Sync, ) -> Result<()> { // `next` is atomic so threads can concurrently fetch their next value to run. let next = AtomicU32::new(range.start); @@ -207,10 +219,10 @@ impl MiriEnv { let mut handles = Vec::new(); // Spawn one worker per core. for _ in 0..thread::available_parallelism()?.get() { - // Create a copy of the shell for this thread. - let local_shell = self.sh.clone(); + // Create a copy of the environment for this thread. + let local_miri = self.clone(); let handle = s.spawn(|| -> Result<()> { - let local_shell = local_shell; // move the copy into this thread. + let local_miri = local_miri; // move the copy into this thread. // Each worker thread keeps asking for numbers until we're all done. loop { let cur = next.fetch_add(1, Ordering::Relaxed); @@ -219,7 +231,7 @@ impl MiriEnv { break; } // Run the command with this seed. - run(&local_shell, cur).inspect_err(|_| { + run(&local_miri, cur).inspect_err(|_| { // If we failed, tell everyone about this. failed.store(true, Ordering::Relaxed); })?; diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index b74f9759ebe..1eca86baeaa 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -29e924841f06bb181d87494eba2783761bc1ddec +fdf61d499c8a8421ecf98e7924bb87caf43a9938 diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index e13e54c3309..14f43f576d3 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -581,17 +581,6 @@ fn main() { show_error!("-Zmiri-track-pointer-tag requires nonzero arguments"); } } - } else if let Some(param) = arg.strip_prefix("-Zmiri-track-call-id=") { - let ids: Vec = parse_comma_list(param).unwrap_or_else(|err| { - show_error!("-Zmiri-track-call-id requires a comma separated list of valid `u64` arguments: {err}") - }); - for id in ids.into_iter().map(miri::CallId::new) { - if let Some(id) = id { - miri_config.tracked_call_ids.insert(id); - } else { - show_error!("-Zmiri-track-call-id requires a nonzero argument"); - } - } } else if let Some(param) = arg.strip_prefix("-Zmiri-track-alloc-id=") { let ids = parse_comma_list::>(param).unwrap_or_else(|err| { show_error!("-Zmiri-track-alloc-id requires a comma separated list of valid non-zero `u64` arguments: {err}") diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs index d537a7fbc17..7a3d76a9beb 100644 --- a/src/tools/miri/src/borrow_tracker/mod.rs +++ b/src/tools/miri/src/borrow_tracker/mod.rs @@ -12,8 +12,6 @@ use crate::*; pub mod stacked_borrows; pub mod tree_borrows; -pub type CallId = NonZero; - /// Tracking pointer provenance #[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct BorTag(NonZero); @@ -57,9 +55,6 @@ impl fmt::Debug for BorTag { /// Per-call-stack-frame data for borrow tracking #[derive(Debug)] pub struct FrameState { - /// The ID of the call this frame corresponds to. - call_id: CallId, - /// If this frame is protecting any tags, they are listed here. We use this list to do /// incremental updates of the global list of protected tags stored in the /// `stacked_borrows::GlobalState` upon function return, and if we attempt to pop a protected @@ -93,18 +88,13 @@ pub struct GlobalStateInner { /// The root tag is the one used for the initial pointer. /// We need this in a separate table to handle cyclic statics. root_ptr_tags: FxHashMap, - /// Next unused call ID (for protectors). - next_call_id: CallId, /// All currently protected tags. - /// An item is protected if its tag is in this set, *and* it has the "protected" bit set. /// We add tags to this when they are created with a protector in `reborrow`, and /// we remove tags from this when the call which is protecting them returns, in /// `GlobalStateInner::end_call`. See `Stack::item_invalidated` for more details. protected_tags: FxHashMap, /// The pointer ids to trace tracked_pointer_tags: FxHashSet, - /// The call ids to trace - tracked_call_ids: FxHashSet, /// Whether to recurse into datatypes when searching for pointers to retag. retag_fields: RetagFields, /// Whether `core::ptr::Unique` gets special (`Box`-like) handling. @@ -168,7 +158,6 @@ impl GlobalStateInner { pub fn new( borrow_tracker_method: BorrowTrackerMethod, tracked_pointer_tags: FxHashSet, - tracked_call_ids: FxHashSet, retag_fields: RetagFields, unique_is_unique: bool, ) -> Self { @@ -176,10 +165,8 @@ impl GlobalStateInner { borrow_tracker_method, next_ptr_tag: BorTag::one(), root_ptr_tags: FxHashMap::default(), - next_call_id: NonZero::new(1).unwrap(), protected_tags: FxHashMap::default(), tracked_pointer_tags, - tracked_call_ids, retag_fields, unique_is_unique, } @@ -192,14 +179,8 @@ impl GlobalStateInner { id } - pub fn new_frame(&mut self, machine: &MiriMachine<'_>) -> FrameState { - let call_id = self.next_call_id; - trace!("new_frame: Assigning call ID {}", call_id); - if self.tracked_call_ids.contains(&call_id) { - machine.emit_diagnostic(NonHaltingDiagnostic::CreatedCallId(call_id)); - } - self.next_call_id = NonZero::new(call_id.get() + 1).unwrap(); - FrameState { call_id, protected_tags: SmallVec::new() } + pub fn new_frame(&mut self) -> FrameState { + FrameState { protected_tags: SmallVec::new() } } fn end_call(&mut self, frame: &machine::FrameExtra<'_>) { @@ -252,7 +233,6 @@ impl BorrowTrackerMethod { RefCell::new(GlobalStateInner::new( self, config.tracked_pointer_tags.clone(), - config.tracked_call_ids.clone(), config.retag_fields, config.unique_is_unique, )) @@ -346,7 +326,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn print_borrow_state(&mut self, alloc_id: AllocId, show_unnamed: bool) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method; + let Some(borrow_tracker) = &this.machine.borrow_tracker else { + eprintln!("attempted to print borrow state, but no borrow state is being tracked"); + return Ok(()); + }; + let method = borrow_tracker.borrow().borrow_tracker_method; match method { BorrowTrackerMethod::StackedBorrows => this.print_stacks(alloc_id), BorrowTrackerMethod::TreeBorrows => this.print_tree(alloc_id, show_unnamed), diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs index 87d9057cb89..12eeaae0eff 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs @@ -429,30 +429,14 @@ impl<'history, 'ecx, 'tcx> DiagnosticCx<'history, 'ecx, 'tcx> { ProtectorKind::WeakProtector => "weakly protected", ProtectorKind::StrongProtector => "strongly protected", }; - let item_tag = item.tag(); - let call_id = self - .machine - .threads - .all_stacks() - .flat_map(|(_id, stack)| stack) - .map(|frame| { - frame.extra.borrow_tracker.as_ref().expect("we should have borrow tracking data") - }) - .find(|frame| frame.protected_tags.iter().any(|(_, tag)| tag == &item_tag)) - .map(|frame| frame.call_id) - .unwrap(); // FIXME: Surely we should find something, but a panic seems wrong here? match self.operation { Operation::Dealloc(_) => - err_sb_ub( - format!("deallocating while item {item:?} is {protected} by call {call_id:?}",), - vec![], - None, - ), + err_sb_ub(format!("deallocating while item {item:?} is {protected}",), vec![], None), Operation::Retag(RetagOp { orig_tag: tag, .. }) | Operation::Access(AccessOp { tag, .. }) => err_sb_ub( format!( - "not granting access to tag {tag:?} because that would remove {item:?} which is {protected} because it is an argument of call {call_id:?}", + "not granting access to tag {tag:?} because that would remove {item:?} which is {protected}", ), vec![], tag.and_then(|tag| self.get_logs_relevant_to(tag, Some(item.tag()))), diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/item.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/item.rs index b9a52e4966c..13846710615 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/item.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/item.rs @@ -7,9 +7,12 @@ use crate::borrow_tracker::BorTag; pub struct Item(u64); // An Item contains 3 bitfields: -// * Bits 0-61 store a BorTag -// * Bits 61-63 store a Permission -// * Bit 64 stores a flag which indicates if we have a protector +// * Bits 0-61 store a BorTag. +// * Bits 61-63 store a Permission. +// * Bit 64 stores a flag which indicates if we might have a protector. +// This is purely an optimization: if the bit is set, the tag *might* be +// in `protected_tags`, but if the bit is not set then the tag is definitely +// not in `protected_tags`. const TAG_MASK: u64 = u64::MAX >> 3; const PERM_MASK: u64 = 0x3 << 61; const PROTECTED_MASK: u64 = 0x1 << 63; diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index 44f42d5fb9c..722cb79c66b 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -1,10 +1,6 @@ use rustc_middle::{ mir::{Mutability, RetagKind}, - ty::{ - self, - layout::{HasParamEnv, HasTyCtxt}, - Ty, - }, + ty::{self, layout::HasParamEnv, Ty}, }; use rustc_span::def_id::DefId; use rustc_target::abi::{Abi, Size}; @@ -146,10 +142,9 @@ impl<'tcx> NewPermission { // interior mutability and protectors interact poorly. // To eliminate the case of Protected Reserved IM we override interior mutability // in the case of a protected reference: protected references are always considered - // "freeze". + // "freeze" in their reservation phase. let initial_state = match mutability { - Mutability::Mut if ty_is_unpin => - Permission::new_reserved(ty_is_freeze || is_protected), + Mutability::Mut if ty_is_unpin => Permission::new_reserved(ty_is_freeze, is_protected), Mutability::Not if ty_is_freeze => Permission::new_frozen(), // Raw pointers never enter this function so they are not handled. // However raw pointers are not the only pointers that take the parent @@ -176,10 +171,12 @@ impl<'tcx> NewPermission { // Regular `Unpin` box, give it `noalias` but only a weak protector // because it is valid to deallocate it within the function. let ty_is_freeze = ty.is_freeze(*cx.tcx, cx.param_env()); + let protected = kind == RetagKind::FnEntry; + let initial_state = Permission::new_reserved(ty_is_freeze, protected); Self { zero_size, - initial_state: Permission::new_reserved(ty_is_freeze), - protector: (kind == RetagKind::FnEntry).then_some(ProtectorKind::WeakProtector), + initial_state, + protector: protected.then_some(ProtectorKind::WeakProtector), } }) } @@ -521,11 +518,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn tb_protect_place(&mut self, place: &MPlaceTy<'tcx>) -> InterpResult<'tcx, MPlaceTy<'tcx>> { let this = self.eval_context_mut(); + // Note: if we were to inline `new_reserved` below we would find out that + // `ty_is_freeze` is eventually unused because it appears in a `ty_is_freeze || true`. + // We are nevertheless including it here for clarity. + let ty_is_freeze = place.layout.ty.is_freeze(*this.tcx, this.param_env()); // Retag it. With protection! That is the entire point. let new_perm = NewPermission { - initial_state: Permission::new_reserved( - place.layout.ty.is_freeze(this.tcx(), this.param_env()), - ), + initial_state: Permission::new_reserved(ty_is_freeze, /* protected */ true), zero_size: false, protector: Some(ProtectorKind::StrongProtector), }; diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs index 8e23257b6c0..5461edb51d3 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs @@ -8,10 +8,16 @@ use crate::AccessKind; /// The activation states of a pointer. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] enum PermissionPriv { - /// represents: a local reference that has not yet been written to; - /// allows: child reads, foreign reads, foreign writes if type is freeze; + /// represents: a local mutable reference that has not yet been written to; + /// allows: child reads, foreign reads; /// affected by: child writes (becomes Active), - /// rejects: foreign writes (Disabled, except if type is not freeze). + /// rejects: foreign writes (Disabled). + /// + /// `ReservedFrz` is mostly for types that are `Freeze` (no interior mutability). + /// If the type has interior mutability, see `ReservedIM` instead. + /// (Note: since the discovery of `tests/fail/tree_borrows/reservedim_spurious_write.rs`, + /// we also use `ReservedFreeze` for mutable references that were retagged with a protector + /// independently of interior mutability) /// /// special case: behaves differently when protected, which is where `conflicted` /// is relevant @@ -22,12 +28,12 @@ enum PermissionPriv { /// - foreign-read then child-write is UB due to `conflicted`, /// - child-write then foreign-read is UB since child-write will activate and then /// foreign-read disables a protected `Active`, which is UB. - /// - /// Note: since the discovery of `tests/fail/tree_borrows/reservedim_spurious_write.rs`, - /// `ty_is_freeze` does not strictly mean that the type has no interior mutability, - /// it could be an interior mutable type that lost its interior mutability privileges - /// when retagged with a protector. - Reserved { ty_is_freeze: bool, conflicted: bool }, + ReservedFrz { conflicted: bool }, + /// Alternative version of `ReservedFrz` made for types with interior mutability. + /// allows: child reads, foreign reads, foreign writes (extra); + /// affected by: child writes (becomes Active); + /// rejects: nothing. + ReservedIM, /// represents: a unique pointer; /// allows: child reads, child writes; /// rejects: foreign reads (Frozen), foreign writes (Disabled). @@ -59,17 +65,14 @@ impl PartialOrd for PermissionPriv { (_, Frozen) => Less, (Active, _) => Greater, (_, Active) => Less, - ( - Reserved { ty_is_freeze: f1, conflicted: c1 }, - Reserved { ty_is_freeze: f2, conflicted: c2 }, - ) => { - // No transition ever changes `ty_is_freeze`. - if f1 != f2 { - return None; - } + (ReservedIM, ReservedIM) => Equal, + (ReservedFrz { conflicted: c1 }, ReservedFrz { conflicted: c2 }) => { // `bool` is ordered such that `false <= true`, so this works as intended. c1.cmp(c2) } + // Versions of `Reserved` with different interior mutability are incomparable with each + // other. + (ReservedIM, ReservedFrz { .. }) | (ReservedFrz { .. }, ReservedIM) => return None, }) } } @@ -77,7 +80,12 @@ impl PartialOrd for PermissionPriv { impl PermissionPriv { /// Check if `self` can be the initial state of a pointer. fn is_initial(&self) -> bool { - matches!(self, Reserved { conflicted: false, .. } | Frozen) + matches!(self, ReservedFrz { conflicted: false } | Frozen | ReservedIM) + } + + /// Reject `ReservedIM` that cannot exist in the presence of a protector. + fn compatible_with_protector(&self) -> bool { + !matches!(self, ReservedIM) } } @@ -93,7 +101,7 @@ mod transition { Disabled => return None, // The inner data `ty_is_freeze` of `Reserved` is always irrelevant for Read // accesses, since the data is not being mutated. Hence the `{ .. }`. - readable @ (Reserved { .. } | Active | Frozen) => readable, + readable @ (ReservedFrz { .. } | ReservedIM | Active | Frozen) => readable, }) } @@ -109,11 +117,16 @@ mod transition { // Someone else read. To make sure we won't write before function exit, // we set the "conflicted" flag, which will disallow writes while we are protected. - Reserved { ty_is_freeze, .. } if protected => - Reserved { ty_is_freeze, conflicted: true }, + ReservedFrz { .. } if protected => ReservedFrz { conflicted: true }, // Before activation and without protectors, foreign reads are fine. // That's the entire point of 2-phase borrows. - res @ Reserved { .. } => res, + res @ (ReservedFrz { .. } | ReservedIM) => { + // Even though we haven't checked `ReservedIM if protected` separately, + // it is a state that cannot occur because under a protector we only + // create `ReservedFrz` never `ReservedIM`. + assert!(!protected); + res + } Active => if protected { // We wrote, someone else reads -- that's bad. @@ -134,10 +147,10 @@ mod transition { // If the `conflicted` flag is set, then there was a foreign read during // the function call that is still ongoing (still `protected`), // this is UB (`noalias` violation). - Reserved { conflicted: true, .. } if protected => return None, + ReservedFrz { conflicted: true } if protected => return None, // A write always activates the 2-phase borrow, even with interior // mutability - Reserved { .. } | Active => Active, + ReservedFrz { .. } | ReservedIM | Active => Active, Frozen | Disabled => return None, }) } @@ -145,15 +158,15 @@ mod transition { /// A non-child node was write-accessed: this makes everything `Disabled` except for /// non-protected interior mutable `Reserved` which stay the same. fn foreign_write(state: PermissionPriv, protected: bool) -> Option { + // There is no explicit dependency on `protected`, but recall that interior mutable + // types receive a `ReservedFrz` instead of `ReservedIM` when retagged under a protector, + // so the result of this function does indirectly depend on (past) protector status. Some(match state { - // FIXME: since the fix related to reservedim_spurious_write, it is now possible - // to express these transitions of the state machine without an explicit dependency - // on `protected`: because `ty_is_freeze: false` implies `!protected` then - // the line handling `Reserved { .. } if protected` could be deleted. - // This will however require optimizations to the exhaustive tests because - // fewer initial conditions are valid. - Reserved { .. } if protected => Disabled, - res @ Reserved { ty_is_freeze: false, .. } => res, + res @ ReservedIM => { + // We can never create a `ReservedIM` under a protector, only `ReservedFrz`. + assert!(!protected); + res + } _ => Disabled, }) } @@ -208,9 +221,23 @@ impl Permission { Self { inner: Active } } - /// Default initial permission of a reborrowed mutable reference. - pub fn new_reserved(ty_is_freeze: bool) -> Self { - Self { inner: Reserved { ty_is_freeze, conflicted: false } } + /// Default initial permission of a reborrowed mutable reference that is either + /// protected or not interior mutable. + fn new_reserved_frz() -> Self { + Self { inner: ReservedFrz { conflicted: false } } + } + + /// Default initial permission of an unprotected interior mutable reference. + fn new_reserved_im() -> Self { + Self { inner: ReservedIM } + } + + /// Wrapper around `new_reserved_frz` and `new_reserved_im` that decides + /// which to call based on the interior mutability and the retag kind (whether there + /// is a protector is relevant because being protected takes priority over being + /// interior mutable) + pub fn new_reserved(ty_is_freeze: bool, protected: bool) -> Self { + if ty_is_freeze || protected { Self::new_reserved_frz() } else { Self::new_reserved_im() } } /// Default initial permission of a reborrowed shared reference. @@ -224,6 +251,11 @@ impl Permission { Self { inner: Disabled } } + /// Reject `ReservedIM` that cannot exist in the presence of a protector. + pub fn compatible_with_protector(&self) -> bool { + self.inner.compatible_with_protector() + } + /// Apply the transition to the inner PermissionPriv. pub fn perform_access( kind: AccessKind, @@ -279,12 +311,9 @@ pub mod diagnostics { f, "{}", match self { - Reserved { ty_is_freeze: true, conflicted: false } => "Reserved", - Reserved { ty_is_freeze: true, conflicted: true } => "Reserved (conflicted)", - Reserved { ty_is_freeze: false, conflicted: false } => - "Reserved (interior mutable)", - Reserved { ty_is_freeze: false, conflicted: true } => - "Reserved (interior mutable, conflicted)", + ReservedFrz { conflicted: false } => "Reserved", + ReservedFrz { conflicted: true } => "Reserved (conflicted)", + ReservedIM => "Reserved (interior mutable)", Active => "Active", Frozen => "Frozen", Disabled => "Disabled", @@ -312,10 +341,9 @@ pub mod diagnostics { // and also as `diagnostics::DisplayFmtPermission.uninit` otherwise // alignment will be incorrect. match self.inner { - Reserved { ty_is_freeze: true, conflicted: false } => "Rs ", - Reserved { ty_is_freeze: true, conflicted: true } => "RsC ", - Reserved { ty_is_freeze: false, conflicted: false } => "RsM ", - Reserved { ty_is_freeze: false, conflicted: true } => "RsCM", + ReservedFrz { conflicted: false } => "Res ", + ReservedFrz { conflicted: true } => "ResC", + ReservedIM => "ReIM", Active => "Act ", Frozen => "Frz ", Disabled => "Dis ", @@ -325,13 +353,14 @@ pub mod diagnostics { impl PermTransition { /// Readable explanation of the consequences of an event. - /// Fits in the sentence "This accessed caused {trans.summary()}". + /// Fits in the sentence "This transition corresponds to {trans.summary()}". pub fn summary(&self) -> &'static str { assert!(self.is_possible()); + assert!(!self.is_noop()); match (self.from, self.to) { (_, Active) => "the first write to a 2-phase borrowed mutable reference", (_, Frozen) => "a loss of write permissions", - (Reserved { conflicted: false, .. }, Reserved { conflicted: true, .. }) => + (ReservedFrz { conflicted: false }, ReservedFrz { conflicted: true }) => "a temporary loss of write permissions until function exit", (Frozen, Disabled) => "a loss of read permissions", (_, Disabled) => "a loss of read and write permissions", @@ -380,28 +409,33 @@ pub mod diagnostics { (Frozen, Frozen) => true, (Active, Frozen) => true, (Disabled, Disabled) => true, - (Reserved { conflicted: true, .. }, Reserved { conflicted: true, .. }) => - true, + ( + ReservedFrz { conflicted: true, .. }, + ReservedFrz { conflicted: true, .. }, + ) => true, // A pointer being `Disabled` is a strictly stronger source of // errors than it being `Frozen`. If we try to access a `Disabled`, // then where it became `Frozen` (or `Active` or `Reserved`) is the least // of our concerns for now. - (Reserved { conflicted: true, .. } | Active | Frozen, Disabled) => false, - (Reserved { conflicted: true, .. }, Frozen) => false, + (ReservedFrz { conflicted: true } | Active | Frozen, Disabled) => false, + (ReservedFrz { conflicted: true }, Frozen) => false, // `Active` and `Reserved` have all permissions, so a // `ChildAccessForbidden(Reserved | Active)` can never exist. - (_, Active) | (_, Reserved { conflicted: false, .. }) => + (_, Active) | (_, ReservedFrz { conflicted: false }) => unreachable!("this permission cannot cause an error"), - // No transition has `Reserved(conflicted=false)` as its `.to` unless it's a noop. - (Reserved { conflicted: false, .. }, _) => + // No transition has `Reserved { conflicted: false }` or `ReservedIM` + // as its `.to` unless it's a noop. + (ReservedFrz { conflicted: false } | ReservedIM, _) => unreachable!("self is a noop transition"), // All transitions produced in normal executions (using `apply_access`) // change permissions in the order `Reserved -> Active -> Frozen -> Disabled`. // We assume that the error was triggered on the same location that // the transition `self` applies to, so permissions found must be increasing // in the order `self.from < self.to <= insufficient.inner` - (Active | Frozen | Disabled, Reserved { .. }) | (Disabled, Frozen) => + (Active | Frozen | Disabled, ReservedFrz { .. } | ReservedIM) + | (Disabled, Frozen) + | (ReservedFrz { .. }, ReservedIM) => unreachable!("permissions between self and err must be increasing"), } } @@ -415,8 +449,10 @@ pub mod diagnostics { // conflicted. (Active, Active) => true, (Frozen, Frozen) => true, - (Reserved { conflicted: true, .. }, Reserved { conflicted: true, .. }) => - true, + ( + ReservedFrz { conflicted: true, .. }, + ReservedFrz { conflicted: true, .. }, + ) => true, // If the error is a transition `Frozen -> Disabled`, then we don't really // care whether before that was `Reserved -> Active -> Frozen` or // `Frozen` directly. @@ -429,23 +465,23 @@ pub mod diagnostics { // -> Reserved { conflicted: true }` is inexistant or irrelevant, // and so is the `Reserved { conflicted: false } -> Active` (Active, Frozen) => false, - (Reserved { conflicted: true, .. }, _) => false, + (ReservedFrz { conflicted: true }, _) => false, (_, Disabled) => unreachable!( "permission that results in Disabled should not itself be Disabled in the first place" ), - // No transition has `Reserved { conflicted: false }` as its `.to` + // No transition has `Reserved { conflicted: false }` or `ReservedIM` as its `.to` // unless it's a noop. - (Reserved { conflicted: false, .. }, _) => + (ReservedFrz { conflicted: false } | ReservedIM, _) => unreachable!("self is a noop transition"), // Permissions only evolve in the order `Reserved -> Active -> Frozen -> Disabled`, // so permissions found must be increasing in the order // `self.from < self.to <= forbidden.from < forbidden.to`. - (Disabled, Reserved { .. } | Active | Frozen) - | (Frozen, Reserved { .. } | Active) - | (Active, Reserved { .. }) => + (Disabled, ReservedFrz { .. } | ReservedIM | Active | Frozen) + | (Frozen, ReservedFrz { .. } | ReservedIM | Active) + | (Active, ReservedFrz { .. } | ReservedIM) => unreachable!("permissions between self and err must be increasing"), } } @@ -466,9 +502,9 @@ pub mod diagnostics { #[cfg(test)] impl Permission { - pub fn is_reserved_with_conflicted(&self, expected_conflicted: bool) -> bool { + pub fn is_reserved_frz_with_conflicted(&self, expected_conflicted: bool) -> bool { match self.inner { - Reserved { conflicted, .. } => conflicted == expected_conflicted, + ReservedFrz { conflicted } => conflicted == expected_conflicted, _ => false, } } @@ -482,10 +518,9 @@ mod propagation_optimization_checks { impl Exhaustive for PermissionPriv { fn exhaustive() -> Box> { Box::new( - vec![Active, Frozen, Disabled].into_iter().chain( - <[bool; 2]>::exhaustive() - .map(|[ty_is_freeze, conflicted]| Reserved { ty_is_freeze, conflicted }), - ), + vec![Active, Frozen, Disabled, ReservedIM] + .into_iter() + .chain(::exhaustive().map(|conflicted| ReservedFrz { conflicted })), ) } } @@ -525,6 +560,9 @@ mod propagation_optimization_checks { // We thus eliminate from this test and all other tests // the case where the tag is initially unprotected and later becomes protected. precondition!(old_protected || !new_protected); + if old_protected { + precondition!(old.compatible_with_protector()); + } for (access, rel_pos) in <(AccessKind, AccessRelatedness)>::exhaustive() { if let Some(new) = perform_access(access, rel_pos, old, old_protected) { assert_eq!( @@ -546,6 +584,9 @@ mod propagation_optimization_checks { for old in PermissionPriv::exhaustive() { for [old_protected, new_protected] in <[bool; 2]>::exhaustive() { precondition!(old_protected || !new_protected); + if old_protected { + precondition!(old.compatible_with_protector()); + } for rel_pos in AccessRelatedness::exhaustive() { precondition!(rel_pos.is_foreign()); if let Some(new) = perform_access(old_access, rel_pos, old, old_protected) { @@ -570,6 +611,9 @@ mod propagation_optimization_checks { reach.insert((start, start)); for (access, rel) in <(AccessKind, AccessRelatedness)>::exhaustive() { for prot in bool::exhaustive() { + if prot { + precondition!(start.compatible_with_protector()); + } if let Some(end) = transition::perform_access(access, rel, start, prot) { reach.insert((start, end)); } diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs index 90bd1103218..56643c6cbe8 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs @@ -10,7 +10,7 @@ //! and the relative position of the access; //! - idempotency properties asserted in `perms.rs` (for optimizations) -use std::fmt; +use std::{fmt, mem}; use smallvec::SmallVec; @@ -699,8 +699,7 @@ impl<'tcx> Tree { /// Integration with the BorTag garbage collector impl Tree { pub fn remove_unreachable_tags(&mut self, live_tags: &FxHashSet) { - let root_is_needed = self.keep_only_needed(self.root, live_tags); // root can't be removed - assert!(root_is_needed); + self.remove_useless_children(self.root, live_tags); // Right after the GC runs is a good moment to check if we can // merge some adjacent ranges that were made equal by the removal of some // tags (this does not necessarily mean that they have identical internal representations, @@ -708,9 +707,16 @@ impl Tree { self.rperms.merge_adjacent_thorough(); } + /// Checks if a node is useless and should be GC'ed. + /// A node is useless if it has no children and also the tag is no longer live. + fn is_useless(&self, idx: UniIndex, live: &FxHashSet) -> bool { + let node = self.nodes.get(idx).unwrap(); + node.children.is_empty() && !live.contains(&node.tag) + } + /// Traverses the entire tree looking for useless tags. - /// Returns true iff the tag it was called on is still live or has live children, - /// and removes from the tree all tags that have no live children. + /// Removes from the tree all useless child nodes of root. + /// It will not delete the root itself. /// /// NOTE: This leaves in the middle of the tree tags that are unreachable but have /// reachable children. There is a potential for compacting the tree by reassigning @@ -721,42 +727,60 @@ impl Tree { /// `child: Reserved`. This tree can exist. If we blindly delete `parent` and reassign /// `child` to be a direct child of `root` then Writes to `child` are now permitted /// whereas they were not when `parent` was still there. - fn keep_only_needed(&mut self, idx: UniIndex, live: &FxHashSet) -> bool { - let node = self.nodes.get(idx).unwrap(); - // FIXME: this function does a lot of cloning, a 2-pass approach is possibly - // more efficient. It could consist of - // 1. traverse the Tree, collect all useless tags in a Vec - // 2. traverse the Vec, remove all tags previously selected - // Bench it. - let children: SmallVec<_> = node - .children - .clone() - .into_iter() - .filter(|child| self.keep_only_needed(*child, live)) - .collect(); - let no_children = children.is_empty(); - let node = self.nodes.get_mut(idx).unwrap(); - node.children = children; - if !live.contains(&node.tag) && no_children { - // All of the children and this node are unreachable, delete this tag - // from the tree (the children have already been deleted by recursive - // calls). - // Due to the API of UniMap we must absolutely call - // `UniValMap::remove` for the key of this tag on *all* maps that used it - // (which are `self.nodes` and every range of `self.rperms`) - // before we can safely apply `UniValMap::forget` to truly remove - // the tag from the mapping. - let tag = node.tag; - self.nodes.remove(idx); - for (_perms_range, perms) in self.rperms.iter_mut_all() { - perms.remove(idx); + fn remove_useless_children(&mut self, root: UniIndex, live: &FxHashSet) { + // To avoid stack overflows, we roll our own stack. + // Each element in the stack consists of the current tag, and the number of the + // next child to be processed. + + // The other functions are written using the `TreeVisitorStack`, but that does not work here + // since we need to 1) do a post-traversal and 2) remove nodes from the tree. + // Since we do a post-traversal (by deleting nodes only after handling all children), + // we also need to be a bit smarter than "pop node, push all children." + let mut stack = vec![(root, 0)]; + while let Some((tag, nth_child)) = stack.last_mut() { + let node = self.nodes.get(*tag).unwrap(); + if *nth_child < node.children.len() { + // Visit the child by pushing it to the stack. + // Also increase `nth_child` so that when we come back to the `tag` node, we + // look at the next child. + let next_child = node.children[*nth_child]; + *nth_child += 1; + stack.push((next_child, 0)); + continue; + } else { + // We have processed all children of `node`, so now it is time to process `node` itself. + // First, get the current children of `node`. To appease the borrow checker, + // we have to temporarily move the list out of the node, and then put the + // list of remaining children back in. + let mut children_of_node = + mem::take(&mut self.nodes.get_mut(*tag).unwrap().children); + // Remove all useless children, and save them for later. + // The closure needs `&self` and the loop below needs `&mut self`, so we need to `collect` + // in to a temporary list. + let to_remove: Vec<_> = + children_of_node.drain_filter(|x| self.is_useless(*x, live)).collect(); + // Put back the now-filtered vector. + self.nodes.get_mut(*tag).unwrap().children = children_of_node; + // Now, all that is left is unregistering the children saved in `to_remove`. + for idx in to_remove { + // Note: In the rest of this comment, "this node" refers to `idx`. + // This node has no more children (if there were any, they have already been removed). + // It is also unreachable as determined by the GC, so we can remove it everywhere. + // Due to the API of UniMap we must make sure to call + // `UniValMap::remove` for the key of this node on *all* maps that used it + // (which are `self.nodes` and every range of `self.rperms`) + // before we can safely apply `UniKeyMap::remove` to truly remove + // this tag from the `tag_mapping`. + let node = self.nodes.remove(idx).unwrap(); + for (_perms_range, perms) in self.rperms.iter_mut_all() { + perms.remove(idx); + } + self.tag_mapping.remove(&node.tag); + } + // We are done, the parent can continue. + stack.pop(); + continue; } - self.tag_mapping.remove(&tag); - // The tag has been deleted, inform the caller - false - } else { - // The tag is still live or has live children, it must be kept - true } } } diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs index 73717014e89..654419c099d 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs @@ -14,6 +14,15 @@ impl Exhaustive for LocationState { } } +impl LocationState { + /// Ensure that the current internal state can exist at the same time as a protector. + /// In practice this only eliminates `ReservedIM` that is never used in the presence + /// of a protector (we instead emit `ReservedFrz` on retag). + pub fn compatible_with_protector(&self) -> bool { + self.permission.compatible_with_protector() + } +} + #[test] #[rustfmt::skip] // Exhaustive check that for any starting configuration loc, @@ -30,6 +39,9 @@ fn all_read_accesses_commute() { // so the two read accesses occur under the same protector. for protected in bool::exhaustive() { for loc in LocationState::exhaustive() { + if protected { + precondition!(loc.compatible_with_protector()); + } // Apply 1 then 2. Failure here means that there is UB in the source // and we skip the check in the target. let mut loc12 = loc; @@ -61,8 +73,8 @@ fn protected_enforces_noalias() { // We want to check pairs of accesses where one is foreign and one is not. precondition!(rel1.is_foreign() != rel2.is_foreign()); for [kind1, kind2] in <[AccessKind; 2]>::exhaustive() { - for mut state in LocationState::exhaustive() { - let protected = true; + let protected = true; + for mut state in LocationState::exhaustive().filter(|s| s.compatible_with_protector()) { precondition!(state.perform_access(kind1, rel1, protected).is_ok()); precondition!(state.perform_access(kind2, rel2, protected).is_ok()); // If these were both allowed, it must have been two reads. @@ -387,6 +399,9 @@ mod spurious_read { fn retag_y(self, new_y: LocStateProt) -> Result { assert!(new_y.is_initial()); + if new_y.prot && !new_y.state.compatible_with_protector() { + return Err(()); + } // `xy_rel` changes to "mutually foreign" now: `y` can no longer be a parent of `x`. Self { y: new_y, xy_rel: RelPosXY::MutuallyForeign, ..self } .read_if_initialized(PtrSelector::Y) @@ -511,7 +526,7 @@ mod spurious_read { } #[test] - // `Reserved(aliased=false)` and `Reserved(aliased=true)` are properly indistinguishable + // `Reserved { conflicted: false }` and `Reserved { conflicted: true }` are properly indistinguishable // under the conditions where we want to insert a spurious read. fn reserved_aliased_protected_indistinguishable() { let source = LocStateProtPair { @@ -521,14 +536,16 @@ mod spurious_read { prot: true, }, y: LocStateProt { - state: LocationState::new_uninit(Permission::new_reserved(false)), + state: LocationState::new_uninit(Permission::new_reserved( + /* freeze */ true, /* protected */ true, + )), prot: true, }, }; let acc = TestAccess { ptr: PtrSelector::X, kind: AccessKind::Read }; let target = source.clone().perform_test_access(&acc).unwrap(); - assert!(source.y.state.permission.is_reserved_with_conflicted(false)); - assert!(target.y.state.permission.is_reserved_with_conflicted(true)); + assert!(source.y.state.permission.is_reserved_frz_with_conflicted(false)); + assert!(target.y.state.permission.is_reserved_frz_with_conflicted(true)); assert!(!source.distinguishable::<(), ()>(&target)) } @@ -563,7 +580,13 @@ mod spurious_read { precondition!(x_retag_perm.initialized); // And `x` just got retagged, so it must be initial. precondition!(x_retag_perm.permission.is_initial()); + // As stated earlier, `x` is always protected in the patterns we consider here. + precondition!(x_retag_perm.compatible_with_protector()); for y_protected in bool::exhaustive() { + // Finally `y` that is optionally protected must have a compatible permission. + if y_protected { + precondition!(y_current_perm.compatible_with_protector()); + } v.push(Pattern { xy_rel, x_retag_perm, y_current_perm, y_protected }); } } diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/unimap.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/unimap.rs index f45b2d9e00a..92bae6203b3 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/unimap.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/unimap.rs @@ -12,7 +12,7 @@ #![allow(dead_code)] -use std::hash::Hash; +use std::{hash::Hash, mem}; use rustc_data_structures::fx::FxHashMap; @@ -187,13 +187,16 @@ impl UniValMap { self.data.get_mut(idx.idx as usize).and_then(Option::as_mut) } - /// Delete any value associated with this index. Ok even if the index - /// has no associated value. - pub fn remove(&mut self, idx: UniIndex) { + /// Delete any value associated with this index. + /// Returns None if the value was not present, otherwise + /// returns the previously stored value. + pub fn remove(&mut self, idx: UniIndex) -> Option { if idx.idx as usize >= self.data.len() { - return; + return None; } - self.data[idx.idx as usize] = None; + let mut res = None; + mem::swap(&mut res, &mut self.data[idx.idx as usize]); + res } } diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs index 9df0d95f1f2..6fd207c92b9 100644 --- a/src/tools/miri/src/concurrency/data_race.rs +++ b/src/tools/miri/src/concurrency/data_race.rs @@ -617,9 +617,10 @@ pub trait EvalContextExt<'tcx>: MiriInterpCxExt<'tcx> { // the *value* (including the associated provenance if this is an AtomicPtr) at this location. // Only metadata on the location itself is used. let scalar = this.allow_data_races_ref(move |this| this.read_scalar(place))?; - this.buffered_atomic_read(place, atomic, scalar, || { + let buffered_scalar = this.buffered_atomic_read(place, atomic, scalar, || { this.validate_atomic_load(place, atomic) - }) + })?; + Ok(buffered_scalar.ok_or_else(|| err_ub!(InvalidUninitBytes(None)))?) } /// Perform an atomic write operation at the memory location. @@ -632,14 +633,14 @@ pub trait EvalContextExt<'tcx>: MiriInterpCxExt<'tcx> { let this = self.eval_context_mut(); this.atomic_access_check(dest, AtomicAccessType::Store)?; + // Read the previous value so we can put it in the store buffer later. + // The program didn't actually do a read, so suppress the memory access hooks. + // This is also a very special exception where we just ignore an error -- if this read + // was UB e.g. because the memory is uninitialized, we don't want to know! + let old_val = this.run_for_validation(|| this.read_scalar(dest)).ok(); this.allow_data_races_mut(move |this| this.write_scalar(val, dest))?; this.validate_atomic_store(dest, atomic)?; - // FIXME: it's not possible to get the value before write_scalar. A read_scalar will cause - // side effects from a read the program did not perform. So we have to initialise - // the store buffer with the value currently being written - // ONCE this is fixed please remove the hack in buffered_atomic_write() in weak_memory.rs - // https://github.com/rust-lang/miri/issues/2164 - this.buffered_atomic_write(val, dest, atomic, val) + this.buffered_atomic_write(val, dest, atomic, old_val) } /// Perform an atomic RMW operation on a memory location. @@ -768,7 +769,7 @@ pub trait EvalContextExt<'tcx>: MiriInterpCxExt<'tcx> { // in the modification order. // Since `old` is only a value and not the store element, we need to separately // find it in our store buffer and perform load_impl on it. - this.perform_read_on_buffered_latest(place, fail, old.to_scalar())?; + this.perform_read_on_buffered_latest(place, fail)?; } // Return the old value. diff --git a/src/tools/miri/src/concurrency/init_once.rs b/src/tools/miri/src/concurrency/init_once.rs index 9145ef32c52..c23e5737280 100644 --- a/src/tools/miri/src/concurrency/init_once.rs +++ b/src/tools/miri/src/concurrency/init_once.rs @@ -26,27 +26,6 @@ pub(super) struct InitOnce { clock: VClock, } -impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {} -trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { - /// Provides the closure with the next InitOnceId. Creates that InitOnce if the closure returns None, - /// otherwise returns the value from the closure. - #[inline] - fn init_once_get_or_create(&mut self, existing: F) -> InterpResult<'tcx, InitOnceId> - where - F: FnOnce(&mut MiriInterpCx<'tcx>, InitOnceId) -> InterpResult<'tcx, Option>, - { - let this = self.eval_context_mut(); - let next_index = this.machine.sync.init_onces.next_index(); - if let Some(old) = existing(this, next_index)? { - Ok(old) - } else { - let new_index = this.machine.sync.init_onces.push(Default::default()); - assert_eq!(next_index, new_index); - Ok(new_index) - } - } -} - impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn init_once_get_or_create_id( @@ -56,9 +35,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { offset: u64, ) -> InterpResult<'tcx, InitOnceId> { let this = self.eval_context_mut(); - this.init_once_get_or_create(|ecx, next_id| { - ecx.get_or_create_id(next_id, lock_op, lock_layout, offset) - }) + this.get_or_create_id(lock_op, lock_layout, offset, |ecx| &mut ecx.machine.sync.init_onces)? + .ok_or_else(|| err_ub_format!("init_once has invalid ID").into()) } #[inline] diff --git a/src/tools/miri/src/concurrency/sync.rs b/src/tools/miri/src/concurrency/sync.rs index d0c9a4600e8..d972831c768 100644 --- a/src/tools/miri/src/concurrency/sync.rs +++ b/src/tools/miri/src/concurrency/sync.rs @@ -164,25 +164,29 @@ pub struct SynchronizationObjects { impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {} pub(super) trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { /// Lazily initialize the ID of this Miri sync structure. - /// ('0' indicates uninit.) + /// If memory stores '0', that indicates uninit and we generate a new instance. + /// Returns `None` if memory stores a non-zero invalid ID. + /// + /// `get_objs` must return the `IndexVec` that stores all the objects of this type. #[inline] - fn get_or_create_id( + fn get_or_create_id( &mut self, - next_id: Id, lock_op: &OpTy<'tcx>, lock_layout: TyAndLayout<'tcx>, offset: u64, + get_objs: impl for<'a> Fn(&'a mut MiriInterpCx<'tcx>) -> &'a mut IndexVec, ) -> InterpResult<'tcx, Option> { let this = self.eval_context_mut(); let value_place = this.deref_pointer_and_offset(lock_op, offset, lock_layout, this.machine.layouts.u32)?; + let next_index = get_objs(this).next_index(); // Since we are lazy, this update has to be atomic. let (old, success) = this .atomic_compare_exchange_scalar( &value_place, &ImmTy::from_uint(0u32, this.machine.layouts.u32), - Scalar::from_u32(next_id.to_u32()), + Scalar::from_u32(next_index.to_u32()), AtomicRwOrd::Relaxed, // deliberately *no* synchronization AtomicReadOrd::Relaxed, false, @@ -190,76 +194,22 @@ pub(super) trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { .to_scalar_pair(); Ok(if success.to_bool().expect("compare_exchange's second return value is a bool") { - // Caller of the closure needs to allocate next_id - None + // We set the in-memory ID to `next_index`, now also create this object in the machine + // state. + let new_index = get_objs(this).push(T::default()); + assert_eq!(next_index, new_index); + Some(new_index) } else { - Some(Id::from_u32(old.to_u32().expect("layout is u32"))) + let id = Id::from_u32(old.to_u32().expect("layout is u32")); + if get_objs(this).get(id).is_none() { + // The in-memory ID is invalid. + None + } else { + Some(id) + } }) } - /// Provides the closure with the next MutexId. Creates that mutex if the closure returns None, - /// otherwise returns the value from the closure. - #[inline] - fn mutex_get_or_create(&mut self, existing: F) -> InterpResult<'tcx, MutexId> - where - F: FnOnce(&mut MiriInterpCx<'tcx>, MutexId) -> InterpResult<'tcx, Option>, - { - let this = self.eval_context_mut(); - let next_index = this.machine.sync.mutexes.next_index(); - if let Some(old) = existing(this, next_index)? { - if this.machine.sync.mutexes.get(old).is_none() { - throw_ub_format!("mutex has invalid ID"); - } - Ok(old) - } else { - let new_index = this.machine.sync.mutexes.push(Default::default()); - assert_eq!(next_index, new_index); - Ok(new_index) - } - } - - /// Provides the closure with the next RwLockId. Creates that RwLock if the closure returns None, - /// otherwise returns the value from the closure. - #[inline] - fn rwlock_get_or_create(&mut self, existing: F) -> InterpResult<'tcx, RwLockId> - where - F: FnOnce(&mut MiriInterpCx<'tcx>, RwLockId) -> InterpResult<'tcx, Option>, - { - let this = self.eval_context_mut(); - let next_index = this.machine.sync.rwlocks.next_index(); - if let Some(old) = existing(this, next_index)? { - if this.machine.sync.rwlocks.get(old).is_none() { - throw_ub_format!("rwlock has invalid ID"); - } - Ok(old) - } else { - let new_index = this.machine.sync.rwlocks.push(Default::default()); - assert_eq!(next_index, new_index); - Ok(new_index) - } - } - - /// Provides the closure with the next CondvarId. Creates that Condvar if the closure returns None, - /// otherwise returns the value from the closure. - #[inline] - fn condvar_get_or_create(&mut self, existing: F) -> InterpResult<'tcx, CondvarId> - where - F: FnOnce(&mut MiriInterpCx<'tcx>, CondvarId) -> InterpResult<'tcx, Option>, - { - let this = self.eval_context_mut(); - let next_index = this.machine.sync.condvars.next_index(); - if let Some(old) = existing(this, next_index)? { - if this.machine.sync.condvars.get(old).is_none() { - throw_ub_format!("condvar has invalid ID"); - } - Ok(old) - } else { - let new_index = this.machine.sync.condvars.push(Default::default()); - assert_eq!(next_index, new_index); - Ok(new_index) - } - } - fn condvar_reacquire_mutex( &mut self, mutex: MutexId, @@ -293,9 +243,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { offset: u64, ) -> InterpResult<'tcx, MutexId> { let this = self.eval_context_mut(); - this.mutex_get_or_create(|ecx, next_id| { - ecx.get_or_create_id(next_id, lock_op, lock_layout, offset) - }) + this.get_or_create_id(lock_op, lock_layout, offset, |ecx| &mut ecx.machine.sync.mutexes)? + .ok_or_else(|| err_ub_format!("mutex has invalid ID").into()) } fn rwlock_get_or_create_id( @@ -305,9 +254,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { offset: u64, ) -> InterpResult<'tcx, RwLockId> { let this = self.eval_context_mut(); - this.rwlock_get_or_create(|ecx, next_id| { - ecx.get_or_create_id(next_id, lock_op, lock_layout, offset) - }) + this.get_or_create_id(lock_op, lock_layout, offset, |ecx| &mut ecx.machine.sync.rwlocks)? + .ok_or_else(|| err_ub_format!("rwlock has invalid ID").into()) } fn condvar_get_or_create_id( @@ -317,9 +265,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { offset: u64, ) -> InterpResult<'tcx, CondvarId> { let this = self.eval_context_mut(); - this.condvar_get_or_create(|ecx, next_id| { - ecx.get_or_create_id(next_id, lock_op, lock_layout, offset) - }) + this.get_or_create_id(lock_op, lock_layout, offset, |ecx| &mut ecx.machine.sync.condvars)? + .ok_or_else(|| err_ub_format!("condvar has invalid ID").into()) } #[inline] diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs index f72591f0c4b..a4d3e3f7af3 100644 --- a/src/tools/miri/src/concurrency/thread.rs +++ b/src/tools/miri/src/concurrency/thread.rs @@ -1157,7 +1157,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } #[inline] - fn get_thread_name<'c>(&'c self, thread: ThreadId) -> Option<&[u8]> + fn get_thread_name<'c>(&'c self, thread: ThreadId) -> Option<&'c [u8]> where 'tcx: 'c, { diff --git a/src/tools/miri/src/concurrency/weak_memory.rs b/src/tools/miri/src/concurrency/weak_memory.rs index 6f4171584a8..0605b744e6a 100644 --- a/src/tools/miri/src/concurrency/weak_memory.rs +++ b/src/tools/miri/src/concurrency/weak_memory.rs @@ -39,11 +39,10 @@ //! to attach store buffers to atomic objects. However, Rust follows LLVM in that it only has //! 'atomic accesses'. Therefore Miri cannot know when and where atomic 'objects' are being //! created or destroyed, to manage its store buffers. Instead, we hence lazily create an -//! atomic object on the first atomic access to a given region, and we destroy that object -//! on the next non-atomic or imperfectly overlapping atomic access to that region. +//! atomic object on the first atomic write to a given region, and we destroy that object +//! on the next non-atomic or imperfectly overlapping atomic write to that region. //! These lazy (de)allocations happen in memory_accessed() on non-atomic accesses, and -//! get_or_create_store_buffer() on atomic accesses. This mostly works well, but it does -//! lead to some issues (). +//! get_or_create_store_buffer_mut() on atomic writes. //! //! One consequence of this difference is that safe/sound Rust allows for more operations on atomic locations //! than the C++20 atomic API was intended to allow, such as non-atomically accessing @@ -144,11 +143,9 @@ struct StoreElement { /// The timestamp of the storing thread when it performed the store timestamp: VTimestamp, - /// The value of this store - // FIXME: this means the store must be fully initialized; - // we will have to change this if we want to support atomics on - // (partially) uninitialized data. - val: Scalar, + /// The value of this store. `None` means uninitialized. + // FIXME: Currently, we cannot represent partial initialization. + val: Option, /// Metadata about loads from this store element, /// behind a RefCell to keep load op take &self @@ -170,7 +167,7 @@ impl StoreBufferAlloc { /// When a non-atomic access happens on a location that has been atomically accessed /// before without data race, we can determine that the non-atomic access fully happens - /// after all the prior atomic accesses so the location no longer needs to exhibit + /// after all the prior atomic writes so the location no longer needs to exhibit /// any weak memory behaviours until further atomic accesses. pub fn memory_accessed(&self, range: AllocRange, global: &DataRaceState) { if !global.ongoing_action_data_race_free() { @@ -192,37 +189,29 @@ impl StoreBufferAlloc { } } - /// Gets a store buffer associated with an atomic object in this allocation, - /// or creates one with the specified initial value if no atomic object exists yet. - fn get_or_create_store_buffer<'tcx>( + /// Gets a store buffer associated with an atomic object in this allocation. + /// Returns `None` if there is no store buffer. + fn get_store_buffer<'tcx>( &self, range: AllocRange, - init: Scalar, - ) -> InterpResult<'tcx, Ref<'_, StoreBuffer>> { + ) -> InterpResult<'tcx, Option>> { let access_type = self.store_buffers.borrow().access_type(range); let pos = match access_type { AccessType::PerfectlyOverlapping(pos) => pos, - AccessType::Empty(pos) => { - let mut buffers = self.store_buffers.borrow_mut(); - buffers.insert_at_pos(pos, range, StoreBuffer::new(init)); - pos - } - AccessType::ImperfectlyOverlapping(pos_range) => { - // Once we reach here we would've already checked that this access is not racy. - let mut buffers = self.store_buffers.borrow_mut(); - buffers.remove_pos_range(pos_range.clone()); - buffers.insert_at_pos(pos_range.start, range, StoreBuffer::new(init)); - pos_range.start - } + // If there is nothing here yet, that means there wasn't an atomic write yet so + // we can't return anything outdated. + _ => return Ok(None), }; - Ok(Ref::map(self.store_buffers.borrow(), |buffer| &buffer[pos])) + let store_buffer = Ref::map(self.store_buffers.borrow(), |buffer| &buffer[pos]); + Ok(Some(store_buffer)) } - /// Gets a mutable store buffer associated with an atomic object in this allocation + /// Gets a mutable store buffer associated with an atomic object in this allocation, + /// or creates one with the specified initial value if no atomic object exists yet. fn get_or_create_store_buffer_mut<'tcx>( &mut self, range: AllocRange, - init: Scalar, + init: Option, ) -> InterpResult<'tcx, &mut StoreBuffer> { let buffers = self.store_buffers.get_mut(); let access_type = buffers.access_type(range); @@ -244,10 +233,8 @@ impl StoreBufferAlloc { } impl<'tcx> StoreBuffer { - fn new(init: Scalar) -> Self { + fn new(init: Option) -> Self { let mut buffer = VecDeque::new(); - buffer.reserve(STORE_BUFFER_LIMIT); - let mut ret = Self { buffer }; let store_elem = StoreElement { // The thread index and timestamp of the initialisation write // are never meaningfully used, so it's fine to leave them as 0 @@ -257,11 +244,11 @@ impl<'tcx> StoreBuffer { is_seqcst: false, load_info: RefCell::new(LoadInfo::default()), }; - ret.buffer.push_back(store_elem); - ret + buffer.push_back(store_elem); + Self { buffer } } - /// Reads from the last store in modification order + /// Reads from the last store in modification order, if any. fn read_from_last_store( &self, global: &DataRaceState, @@ -282,7 +269,7 @@ impl<'tcx> StoreBuffer { is_seqcst: bool, rng: &mut (impl rand::Rng + ?Sized), validate: impl FnOnce() -> InterpResult<'tcx>, - ) -> InterpResult<'tcx, (Scalar, LoadRecency)> { + ) -> InterpResult<'tcx, (Option, LoadRecency)> { // Having a live borrow to store_buffer while calling validate_atomic_load is fine // because the race detector doesn't touch store_buffer @@ -419,15 +406,15 @@ impl<'tcx> StoreBuffer { // In the language provided in the paper, an atomic store takes the value from a // non-atomic memory location. // But we already have the immediate value here so we don't need to do the memory - // access - val, + // access. + val: Some(val), is_seqcst, load_info: RefCell::new(LoadInfo::default()), }; - self.buffer.push_back(store_elem); - if self.buffer.len() > STORE_BUFFER_LIMIT { + if self.buffer.len() >= STORE_BUFFER_LIMIT { self.buffer.pop_front(); } + self.buffer.push_back(store_elem); if is_seqcst { // Every store that happens before this needs to be marked as SC // so that in a later SC load, only the last SC store (i.e. this one) or stores that @@ -450,7 +437,12 @@ impl StoreElement { /// buffer regardless of subsequent loads by the same thread; if the earliest load of another /// thread doesn't happen before the current one, then no subsequent load by the other thread /// can happen before the current one. - fn load_impl(&self, index: VectorIdx, clocks: &ThreadClockSet, is_seqcst: bool) -> Scalar { + fn load_impl( + &self, + index: VectorIdx, + clocks: &ThreadClockSet, + is_seqcst: bool, + ) -> Option { let mut load_info = self.load_info.borrow_mut(); load_info.sc_loaded |= is_seqcst; let _ = load_info.timestamps.try_insert(index, clocks.clock[index]); @@ -479,7 +471,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { global.sc_write(threads); } let range = alloc_range(base_offset, place.layout.size); - let buffer = alloc_buffers.get_or_create_store_buffer_mut(range, init)?; + let buffer = alloc_buffers.get_or_create_store_buffer_mut(range, Some(init))?; buffer.read_from_last_store(global, threads, atomic == AtomicRwOrd::SeqCst); buffer.buffered_write(new_val, global, threads, atomic == AtomicRwOrd::SeqCst)?; } @@ -492,47 +484,55 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { atomic: AtomicReadOrd, latest_in_mo: Scalar, validate: impl FnOnce() -> InterpResult<'tcx>, - ) -> InterpResult<'tcx, Scalar> { + ) -> InterpResult<'tcx, Option> { let this = self.eval_context_ref(); - if let Some(global) = &this.machine.data_race { - let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr(), 0)?; - if let Some(alloc_buffers) = this.get_alloc_extra(alloc_id)?.weak_memory.as_ref() { - if atomic == AtomicReadOrd::SeqCst { - global.sc_read(&this.machine.threads); - } - let mut rng = this.machine.rng.borrow_mut(); - let buffer = alloc_buffers.get_or_create_store_buffer( - alloc_range(base_offset, place.layout.size), - latest_in_mo, - )?; - let (loaded, recency) = buffer.buffered_read( - global, - &this.machine.threads, - atomic == AtomicReadOrd::SeqCst, - &mut *rng, - validate, - )?; - if global.track_outdated_loads && recency == LoadRecency::Outdated { - this.emit_diagnostic(NonHaltingDiagnostic::WeakMemoryOutdatedLoad { - ptr: place.ptr(), - }); - } + 'fallback: { + if let Some(global) = &this.machine.data_race { + let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr(), 0)?; + if let Some(alloc_buffers) = this.get_alloc_extra(alloc_id)?.weak_memory.as_ref() { + if atomic == AtomicReadOrd::SeqCst { + global.sc_read(&this.machine.threads); + } + let mut rng = this.machine.rng.borrow_mut(); + let Some(buffer) = alloc_buffers + .get_store_buffer(alloc_range(base_offset, place.layout.size))? + else { + // No old writes available, fall back to base case. + break 'fallback; + }; + let (loaded, recency) = buffer.buffered_read( + global, + &this.machine.threads, + atomic == AtomicReadOrd::SeqCst, + &mut *rng, + validate, + )?; + if global.track_outdated_loads && recency == LoadRecency::Outdated { + this.emit_diagnostic(NonHaltingDiagnostic::WeakMemoryOutdatedLoad { + ptr: place.ptr(), + }); + } - return Ok(loaded); + return Ok(loaded); + } } } // Race detector or weak memory disabled, simply read the latest value validate()?; - Ok(latest_in_mo) + Ok(Some(latest_in_mo)) } + /// Add the given write to the store buffer. (Does not change machine memory.) + /// + /// `init` says with which value to initialize the store buffer in case there wasn't a store + /// buffer for this memory range before. fn buffered_atomic_write( &mut self, val: Scalar, dest: &MPlaceTy<'tcx>, atomic: AtomicWriteOrd, - init: Scalar, + init: Option, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(dest.ptr(), 0)?; @@ -545,23 +545,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { global.sc_write(threads); } - // UGLY HACK: in write_scalar_atomic() we don't know the value before our write, - // so init == val always. If the buffer is fresh then we would've duplicated an entry, - // so we need to remove it. - // See https://github.com/rust-lang/miri/issues/2164 - let was_empty = matches!( - alloc_buffers - .store_buffers - .borrow() - .access_type(alloc_range(base_offset, dest.layout.size)), - AccessType::Empty(_) - ); let buffer = alloc_buffers .get_or_create_store_buffer_mut(alloc_range(base_offset, dest.layout.size), init)?; - if was_empty { - buffer.buffer.pop_front(); - } - buffer.buffered_write(val, global, threads, atomic == AtomicWriteOrd::SeqCst)?; } @@ -576,7 +561,6 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { &self, place: &MPlaceTy<'tcx>, atomic: AtomicReadOrd, - init: Scalar, ) -> InterpResult<'tcx> { let this = self.eval_context_ref(); @@ -587,8 +571,12 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let size = place.layout.size; let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr(), 0)?; if let Some(alloc_buffers) = this.get_alloc_extra(alloc_id)?.weak_memory.as_ref() { - let buffer = alloc_buffers - .get_or_create_store_buffer(alloc_range(base_offset, size), init)?; + let Some(buffer) = + alloc_buffers.get_store_buffer(alloc_range(base_offset, size))? + else { + // No store buffer, nothing to do. + return Ok(()); + }; buffer.read_from_last_store( global, &this.machine.threads, diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs index 1bed55743d4..92f344d13b7 100644 --- a/src/tools/miri/src/diagnostics.rs +++ b/src/tools/miri/src/diagnostics.rs @@ -116,7 +116,6 @@ pub enum NonHaltingDiagnostic { CreatedPointerTag(NonZero, Option, Option<(AllocId, AllocRange, ProvenanceExtra)>), /// This `Item` was popped from the borrow stack. The string explains the reason. PoppedPointerTag(Item, String), - CreatedCallId(CallId), CreatedAlloc(AllocId, Size, Align, MemoryKind), FreedAlloc(AllocId), AccessedAlloc(AllocId, AccessKind), @@ -607,7 +606,6 @@ impl<'tcx> MiriMachine<'tcx> { ("reborrow of reference to `extern type`".to_string(), DiagLevel::Warning), CreatedPointerTag(..) | PoppedPointerTag(..) - | CreatedCallId(..) | CreatedAlloc(..) | AccessedAlloc(..) | FreedAlloc(..) @@ -625,7 +623,6 @@ impl<'tcx> MiriMachine<'tcx> { "created tag {tag:?} with {perm} at {alloc_id:?}{range:?} derived from {orig_tag:?}" ), PoppedPointerTag(item, cause) => format!("popped tracked tag for item {item:?}{cause}"), - CreatedCallId(id) => format!("function call with id {id}"), CreatedAlloc(AllocId(id), size, align, kind) => format!( "created {kind} allocation of {size} bytes (alignment {align} bytes) with id {id}", diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs index d781188cd0c..bb623c66892 100644 --- a/src/tools/miri/src/eval.rs +++ b/src/tools/miri/src/eval.rs @@ -118,8 +118,6 @@ pub struct MiriConfig { pub seed: Option, /// The stacked borrows pointer ids to report about pub tracked_pointer_tags: FxHashSet, - /// The stacked borrows call IDs to report about - pub tracked_call_ids: FxHashSet, /// The allocation ids to report about. pub tracked_alloc_ids: FxHashSet, /// For the tracked alloc ids, also report read/write accesses. @@ -183,7 +181,6 @@ impl Default for MiriConfig { args: vec![], seed: None, tracked_pointer_tags: FxHashSet::default(), - tracked_call_ids: FxHashSet::default(), tracked_alloc_ids: FxHashSet::default(), track_alloc_accesses: false, data_race_detector: true, @@ -460,10 +457,13 @@ pub fn eval_entry<'tcx>( ecx.handle_ice(); panic::resume_unwind(panic_payload) }); + // `Ok` can never happen. + #[cfg(not(bootstrap))] + let Err(res) = res; + #[cfg(bootstrap)] let res = match res { Err(res) => res, // `Ok` can never happen - #[cfg(bootstrap)] Ok(never) => match never {}, }; diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 1bdf9f06dcd..04837456212 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -371,6 +371,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { path_ty_layout(this, &["std", "sys", "pal", "windows", "c", name]) } + /// Helper function to get `TyAndLayout` of an array that consists of `libc` type. + fn libc_array_ty_layout(&self, name: &str, size: u64) -> TyAndLayout<'tcx> { + let this = self.eval_context_ref(); + let elem_ty_layout = this.libc_ty_layout(name); + let array_ty = Ty::new_array(*this.tcx, elem_ty_layout.ty, size); + this.layout_of(array_ty).unwrap() + } + /// Project to the given *named* field (which must be a struct or union type). fn project_field_named>( &self, diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 966d38508f6..f796e845a23 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -12,7 +12,6 @@ #![feature(let_chains)] #![feature(trait_upcasting)] #![feature(strict_overflow_ops)] -#![feature(is_none_or)] // Configure clippy and other lints #![allow( clippy::collapsible_else_if, @@ -56,9 +55,9 @@ extern crate either; extern crate tracing; // The rustc crates we need -extern crate rustc_attr; extern crate rustc_apfloat; extern crate rustc_ast; +extern crate rustc_attr; extern crate rustc_const_eval; extern crate rustc_data_structures; extern crate rustc_errors; @@ -124,9 +123,7 @@ pub use crate::borrow_tracker::stacked_borrows::{ EvalContextExt as _, Item, Permission, Stack, Stacks, }; pub use crate::borrow_tracker::tree_borrows::{EvalContextExt as _, Tree}; -pub use crate::borrow_tracker::{ - BorTag, BorrowTrackerMethod, CallId, EvalContextExt as _, RetagFields, -}; +pub use crate::borrow_tracker::{BorTag, BorrowTrackerMethod, EvalContextExt as _, RetagFields}; pub use crate::clock::{Clock, Instant}; pub use crate::concurrency::{ cpu_affinity::MAX_CPUS, diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 754f8cf1381..264b7b269de 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -455,6 +455,9 @@ pub struct MiriMachine<'tcx> { /// The table of directory descriptors. pub(crate) dirs: shims::DirTable, + /// The list of all EpollEventInterest. + pub(crate) epoll_interests: shims::EpollInterestTable, + /// This machine's monotone clock. pub(crate) clock: Clock, @@ -649,6 +652,7 @@ impl<'tcx> MiriMachine<'tcx> { isolated_op: config.isolated_op, validation: config.validation, fds: shims::FdTable::init(config.mute_stdout_stderr), + epoll_interests: shims::EpollInterestTable::new(), dirs: Default::default(), layouts, threads, @@ -787,6 +791,7 @@ impl VisitProvenance for MiriMachine<'_> { data_race, alloc_addresses, fds, + epoll_interests:_, tcx: _, isolated_op: _, validation: _, @@ -941,16 +946,48 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { ecx.machine.validation == ValidationMode::Deep } - #[inline(always)] - fn enforce_abi(_ecx: &MiriInterpCx<'tcx>) -> bool { - true - } - #[inline(always)] fn ignore_optional_overflow_checks(ecx: &MiriInterpCx<'tcx>) -> bool { !ecx.tcx.sess.overflow_checks() } + fn check_fn_target_features( + ecx: &MiriInterpCx<'tcx>, + instance: ty::Instance<'tcx>, + ) -> InterpResult<'tcx> { + let attrs = ecx.tcx.codegen_fn_attrs(instance.def_id()); + if attrs + .target_features + .iter() + .any(|feature| !ecx.tcx.sess.target_features.contains(&feature.name)) + { + let unavailable = attrs + .target_features + .iter() + .filter(|&feature| { + !feature.implied && !ecx.tcx.sess.target_features.contains(&feature.name) + }) + .fold(String::new(), |mut s, feature| { + if !s.is_empty() { + s.push_str(", "); + } + s.push_str(feature.name.as_str()); + s + }); + let msg = format!( + "calling a function that requires unavailable target features: {unavailable}" + ); + // On WASM, this is not UB, but instead gets rejected during validation of the module + // (see #84988). + if ecx.tcx.sess.target.is_like_wasm { + throw_machine_stop!(TerminationInfo::Abort(msg)); + } else { + throw_ub_format!("{msg}"); + } + } + Ok(()) + } + #[inline(always)] fn find_mir_or_eval_fn( ecx: &mut MiriInterpCx<'tcx>, @@ -1055,6 +1092,10 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { ecx.generate_nan(inputs) } + fn ub_checks(ecx: &InterpCx<'tcx, Self>) -> InterpResult<'tcx, bool> { + Ok(ecx.tcx.sess.ub_checks()) + } + fn thread_local_static_pointer( ecx: &mut MiriInterpCx<'tcx>, def_id: DefId, @@ -1370,7 +1411,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { let borrow_tracker = ecx.machine.borrow_tracker.as_ref(); let extra = FrameExtra { - borrow_tracker: borrow_tracker.map(|bt| bt.borrow_mut().new_frame(&ecx.machine)), + borrow_tracker: borrow_tracker.map(|bt| bt.borrow_mut().new_frame()), catch_unwind: None, timing, is_user_relevant: ecx.machine.is_user_relevant(&frame), diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 7f6f63ff5e7..d40dbdba80f 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -8,7 +8,7 @@ use rustc_middle::mir; use rustc_middle::ty; use rustc_span::Symbol; use rustc_target::{ - abi::{Align, Size}, + abi::{Align, AlignFromBytesError, Size}, spec::abi::Abi, }; @@ -199,9 +199,20 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { if i128::from(size) > this.tcx.data_layout.pointer_size.signed_int_max() { throw_ub_format!("creating an allocation larger than half the address space"); } - if !align.is_power_of_two() { - throw_ub_format!("creating allocation with non-power-of-two alignment {}", align); + if let Err(e) = Align::from_bytes(align) { + match e { + AlignFromBytesError::TooLarge(_) => { + throw_unsup_format!( + "creating allocation with alignment {align} exceeding rustc's maximum \ + supported value" + ); + } + AlignFromBytesError::NotPowerOfTwo(_) => { + throw_ub_format!("creating allocation with non-power-of-two alignment {align}"); + } + } } + Ok(()) } @@ -289,8 +300,12 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { let [id, show_unnamed] = this.check_shim(abi, Abi::Rust, link_name, args)?; let id = this.read_scalar(id)?.to_u64()?; let show_unnamed = this.read_scalar(show_unnamed)?.to_bool()?; - if let Some(id) = std::num::NonZero::new(id) { - this.print_borrow_state(AllocId(id), show_unnamed)?; + if let Some(id) = std::num::NonZero::new(id).map(AllocId) + && this.get_alloc_info(id).2 == AllocKind::LiveData + { + this.print_borrow_state(id, show_unnamed)?; + } else { + eprintln!("{id} is not the ID of a live data allocation"); } } "miri_pointer_name" => { diff --git a/src/tools/miri/src/shims/mod.rs b/src/tools/miri/src/shims/mod.rs index a41a2883c91..7d5349f26b1 100644 --- a/src/tools/miri/src/shims/mod.rs +++ b/src/tools/miri/src/shims/mod.rs @@ -17,7 +17,7 @@ pub mod panic; pub mod time; pub mod tls; -pub use unix::{DirTable, FdTable}; +pub use unix::{DirTable, EpollInterestTable, FdTable}; /// What needs to be done after emulating an item (a shim or an intrinsic) is done. pub enum EmulateItemResult { diff --git a/src/tools/miri/src/shims/unix/fd.rs b/src/tools/miri/src/shims/unix/fd.rs index 1b25ef05769..e3b9835e360 100644 --- a/src/tools/miri/src/shims/unix/fd.rs +++ b/src/tools/miri/src/shims/unix/fd.rs @@ -2,13 +2,15 @@ //! standard file descriptors (stdin/stdout/stderr). use std::any::Any; -use std::cell::{Ref, RefCell, RefMut}; use std::collections::BTreeMap; use std::io::{self, ErrorKind, IsTerminal, Read, SeekFrom, Write}; +use std::ops::Deref; use std::rc::Rc; +use std::rc::Weak; use rustc_target::abi::Size; +use crate::shims::unix::linux::epoll::EpollReadyEvents; use crate::shims::unix::*; use crate::*; @@ -25,7 +27,8 @@ pub trait FileDescription: std::fmt::Debug + Any { /// Reads as much as possible into the given buffer, and returns the number of bytes read. fn read<'tcx>( - &mut self, + &self, + _self_ref: &FileDescriptionRef, _communicate_allowed: bool, _bytes: &mut [u8], _ecx: &mut MiriInterpCx<'tcx>, @@ -35,7 +38,8 @@ pub trait FileDescription: std::fmt::Debug + Any { /// Writes as much as possible from the given buffer, and returns the number of bytes written. fn write<'tcx>( - &mut self, + &self, + _self_ref: &FileDescriptionRef, _communicate_allowed: bool, _bytes: &[u8], _ecx: &mut MiriInterpCx<'tcx>, @@ -46,7 +50,7 @@ pub trait FileDescription: std::fmt::Debug + Any { /// Reads as much as possible into the given buffer from a given offset, /// and returns the number of bytes read. fn pread<'tcx>( - &mut self, + &self, _communicate_allowed: bool, _bytes: &mut [u8], _offset: u64, @@ -58,7 +62,7 @@ pub trait FileDescription: std::fmt::Debug + Any { /// Writes as much as possible from the given buffer starting at a given offset, /// and returns the number of bytes written. fn pwrite<'tcx>( - &mut self, + &self, _communicate_allowed: bool, _bytes: &[u8], _offset: u64, @@ -70,7 +74,7 @@ pub trait FileDescription: std::fmt::Debug + Any { /// Seeks to the given offset (which can be relative to the beginning, end, or current position). /// Returns the new position from the start of the stream. fn seek<'tcx>( - &mut self, + &self, _communicate_allowed: bool, _offset: SeekFrom, ) -> InterpResult<'tcx, io::Result> { @@ -80,6 +84,7 @@ pub trait FileDescription: std::fmt::Debug + Any { fn close<'tcx>( self: Box, _communicate_allowed: bool, + _ecx: &mut MiriInterpCx<'tcx>, ) -> InterpResult<'tcx, io::Result<()>> { throw_unsup_format!("cannot close {}", self.name()); } @@ -97,18 +102,18 @@ pub trait FileDescription: std::fmt::Debug + Any { // so we use a default impl here. false } + + /// Check the readiness of file description. + fn get_epoll_ready_events<'tcx>(&self) -> InterpResult<'tcx, EpollReadyEvents> { + throw_unsup_format!("{}: epoll does not support this file description", self.name()); + } } impl dyn FileDescription { #[inline(always)] - pub fn downcast_ref(&self) -> Option<&T> { + pub fn downcast(&self) -> Option<&T> { (self as &dyn Any).downcast_ref() } - - #[inline(always)] - pub fn downcast_mut(&mut self) -> Option<&mut T> { - (self as &mut dyn Any).downcast_mut() - } } impl FileDescription for io::Stdin { @@ -117,7 +122,8 @@ impl FileDescription for io::Stdin { } fn read<'tcx>( - &mut self, + &self, + _self_ref: &FileDescriptionRef, communicate_allowed: bool, bytes: &mut [u8], _ecx: &mut MiriInterpCx<'tcx>, @@ -126,7 +132,7 @@ impl FileDescription for io::Stdin { // We want isolation mode to be deterministic, so we have to disallow all reads, even stdin. helpers::isolation_abort_error("`read` from stdin")?; } - Ok(Read::read(self, bytes)) + Ok(Read::read(&mut { self }, bytes)) } fn is_tty(&self, communicate_allowed: bool) -> bool { @@ -140,13 +146,14 @@ impl FileDescription for io::Stdout { } fn write<'tcx>( - &mut self, + &self, + _self_ref: &FileDescriptionRef, _communicate_allowed: bool, bytes: &[u8], _ecx: &mut MiriInterpCx<'tcx>, ) -> InterpResult<'tcx, io::Result> { // We allow writing to stderr even with isolation enabled. - let result = Write::write(self, bytes); + let result = Write::write(&mut { self }, bytes); // Stdout is buffered, flush to make sure it appears on the // screen. This is the write() syscall of the interpreted // program, we want it to correspond to a write() syscall on @@ -168,7 +175,8 @@ impl FileDescription for io::Stderr { } fn write<'tcx>( - &mut self, + &self, + _self_ref: &FileDescriptionRef, _communicate_allowed: bool, bytes: &[u8], _ecx: &mut MiriInterpCx<'tcx>, @@ -193,7 +201,8 @@ impl FileDescription for NullOutput { } fn write<'tcx>( - &mut self, + &self, + _self_ref: &FileDescriptionRef, _communicate_allowed: bool, bytes: &[u8], _ecx: &mut MiriInterpCx<'tcx>, @@ -203,36 +212,85 @@ impl FileDescription for NullOutput { } } +/// Structure contains both the file description and its unique identifier. #[derive(Clone, Debug)] -pub struct FileDescriptionRef(Rc>>); +pub struct FileDescWithId { + id: FdId, + file_description: Box, +} + +#[derive(Clone, Debug)] +pub struct FileDescriptionRef(Rc>); + +impl Deref for FileDescriptionRef { + type Target = dyn FileDescription; + + fn deref(&self) -> &Self::Target { + &*self.0.file_description + } +} impl FileDescriptionRef { - fn new(fd: impl FileDescription) -> Self { - FileDescriptionRef(Rc::new(RefCell::new(Box::new(fd)))) + fn new(fd: impl FileDescription, id: FdId) -> Self { + FileDescriptionRef(Rc::new(FileDescWithId { id, file_description: Box::new(fd) })) } - pub fn borrow(&self) -> Ref<'_, dyn FileDescription> { - Ref::map(self.0.borrow(), |fd| fd.as_ref()) - } - - pub fn borrow_mut(&self) -> RefMut<'_, dyn FileDescription> { - RefMut::map(self.0.borrow_mut(), |fd| fd.as_mut()) - } - - pub fn close<'ctx>(self, communicate_allowed: bool) -> InterpResult<'ctx, io::Result<()>> { + pub fn close<'tcx>( + self, + communicate_allowed: bool, + ecx: &mut MiriInterpCx<'tcx>, + ) -> InterpResult<'tcx, io::Result<()>> { // Destroy this `Rc` using `into_inner` so we can call `close` instead of // implicitly running the destructor of the file description. + let id = self.get_id(); match Rc::into_inner(self.0) { - Some(fd) => RefCell::into_inner(fd).close(communicate_allowed), + Some(fd) => { + // Remove entry from the global epoll_event_interest table. + ecx.machine.epoll_interests.remove(id); + + fd.file_description.close(communicate_allowed, ecx) + } None => Ok(Ok(())), } } + + pub fn downgrade(&self) -> WeakFileDescriptionRef { + WeakFileDescriptionRef { weak_ref: Rc::downgrade(&self.0) } + } + + pub fn get_id(&self) -> FdId { + self.0.id + } } +/// Holds a weak reference to the actual file description. +#[derive(Clone, Debug, Default)] +pub struct WeakFileDescriptionRef { + weak_ref: Weak>, +} + +impl WeakFileDescriptionRef { + pub fn upgrade(&self) -> Option { + if let Some(file_desc_with_id) = self.weak_ref.upgrade() { + return Some(FileDescriptionRef(file_desc_with_id)); + } + None + } +} + +/// A unique id for file descriptions. While we could use the address, considering that +/// is definitely unique, the address would expose interpreter internal state when used +/// for sorting things. So instead we generate a unique id per file description that stays +/// the same even if a file descriptor is duplicated and gets a new integer file descriptor. +#[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Ord, PartialOrd)] +pub struct FdId(usize); + /// The file descriptor table #[derive(Debug)] pub struct FdTable { - fds: BTreeMap, + pub fds: BTreeMap, + /// Unique identifier for file description, used to differentiate between various file description. + next_file_description_id: FdId, } impl VisitProvenance for FdTable { @@ -243,7 +301,7 @@ impl VisitProvenance for FdTable { impl FdTable { fn new() -> Self { - FdTable { fds: BTreeMap::new() } + FdTable { fds: BTreeMap::new(), next_file_description_id: FdId(0) } } pub(crate) fn init(mute_stdout_stderr: bool) -> FdTable { let mut fds = FdTable::new(); @@ -258,10 +316,20 @@ impl FdTable { fds } + pub fn new_ref(&mut self, fd: impl FileDescription) -> FileDescriptionRef { + let file_handle = FileDescriptionRef::new(fd, self.next_file_description_id); + self.next_file_description_id = FdId(self.next_file_description_id.0.strict_add(1)); + file_handle + } + /// Insert a new file description to the FdTable. pub fn insert_new(&mut self, fd: impl FileDescription) -> i32 { - let file_handle = FileDescriptionRef::new(fd); - self.insert_ref_with_min_fd(file_handle, 0) + let fd_ref = self.new_ref(fd); + self.insert(fd_ref) + } + + pub fn insert(&mut self, fd_ref: FileDescriptionRef) -> i32 { + self.insert_ref_with_min_fd(fd_ref, 0) } /// Insert a file description, giving it a file descriptor that is at least `min_fd`. @@ -291,17 +359,7 @@ impl FdTable { new_fd } - pub fn get(&self, fd: i32) -> Option> { - let fd = self.fds.get(&fd)?; - Some(fd.borrow()) - } - - pub fn get_mut(&self, fd: i32) -> Option> { - let fd = self.fds.get(&fd)?; - Some(fd.borrow_mut()) - } - - pub fn get_ref(&self, fd: i32) -> Option { + pub fn get(&self, fd: i32) -> Option { let fd = self.fds.get(&fd)?; Some(fd.clone()) } @@ -320,7 +378,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn dup(&mut self, old_fd: i32) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - let Some(dup_fd) = this.machine.fds.get_ref(old_fd) else { + let Some(dup_fd) = this.machine.fds.get(old_fd) else { return Ok(Scalar::from_i32(this.fd_not_found()?)); }; Ok(Scalar::from_i32(this.machine.fds.insert_ref_with_min_fd(dup_fd, 0))) @@ -329,7 +387,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn dup2(&mut self, old_fd: i32, new_fd: i32) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - let Some(dup_fd) = this.machine.fds.get_ref(old_fd) else { + let Some(dup_fd) = this.machine.fds.get(old_fd) else { return Ok(Scalar::from_i32(this.fd_not_found()?)); }; if new_fd != old_fd { @@ -337,7 +395,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // If old_fd and new_fd point to the same description, then `dup_fd` ensures we keep the underlying file description alive. if let Some(file_description) = this.machine.fds.fds.insert(new_fd, dup_fd) { // Ignore close error (not interpreter's) according to dup2() doc. - file_description.close(this.machine.communicate())?.ok(); + file_description.close(this.machine.communicate(), this)?.ok(); } } Ok(Scalar::from_i32(new_fd)) @@ -415,7 +473,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } let start = this.read_scalar(&args[2])?.to_i32()?; - match this.machine.fds.get_ref(fd) { + match this.machine.fds.get(fd) { Some(dup_fd) => Ok(Scalar::from_i32(this.machine.fds.insert_ref_with_min_fd(dup_fd, start))), None => Ok(Scalar::from_i32(this.fd_not_found()?)), @@ -442,7 +500,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let Some(file_description) = this.machine.fds.remove(fd) else { return Ok(Scalar::from_i32(this.fd_not_found()?)); }; - let result = file_description.close(this.machine.communicate())?; + let result = file_description.close(this.machine.communicate(), this)?; // return `0` if close is successful let result = result.map(|()| 0i32); Ok(Scalar::from_i32(this.try_unwrap_io_result(result)?)) @@ -488,7 +546,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let communicate = this.machine.communicate(); // We temporarily dup the FD to be able to retain mutable access to `this`. - let Some(fd) = this.machine.fds.get_ref(fd) else { + let Some(fd) = this.machine.fds.get(fd) else { trace!("read: FD not found"); return Ok(Scalar::from_target_isize(this.fd_not_found()?, this)); }; @@ -499,17 +557,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // `usize::MAX` because it is bounded by the host's `isize`. let mut bytes = vec![0; usize::try_from(count).unwrap()]; let result = match offset { - None => fd.borrow_mut().read(communicate, &mut bytes, this), + None => fd.read(&fd, communicate, &mut bytes, this), Some(offset) => { let Ok(offset) = u64::try_from(offset) else { let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; return Ok(Scalar::from_target_isize(-1, this)); }; - fd.borrow_mut().pread(communicate, &mut bytes, offset, this) + fd.pread(communicate, &mut bytes, offset, this) } }; - drop(fd); // `File::read` never returns a value larger than `count`, so this cannot fail. match result?.map(|c| i64::try_from(c).unwrap()) { @@ -553,22 +610,21 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let bytes = this.read_bytes_ptr_strip_provenance(buf, Size::from_bytes(count))?.to_owned(); // We temporarily dup the FD to be able to retain mutable access to `this`. - let Some(fd) = this.machine.fds.get_ref(fd) else { + let Some(fd) = this.machine.fds.get(fd) else { return Ok(Scalar::from_target_isize(this.fd_not_found()?, this)); }; let result = match offset { - None => fd.borrow_mut().write(communicate, &bytes, this), + None => fd.write(&fd, communicate, &bytes, this), Some(offset) => { let Ok(offset) = u64::try_from(offset) else { let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; return Ok(Scalar::from_target_isize(-1, this)); }; - fd.borrow_mut().pwrite(communicate, &bytes, offset, this) + fd.pwrite(communicate, &bytes, offset, this) } }; - drop(fd); let result = result?.map(|c| i64::try_from(c).unwrap()); Ok(Scalar::from_target_isize(this.try_unwrap_io_result(result)?, this)) diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index 57930f9807d..273a99b3116 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -288,14 +288,25 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(result, dest)?; } - // Sockets + // Unnamed sockets and pipes "socketpair" => { let [domain, type_, protocol, sv] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.socketpair(domain, type_, protocol, sv)?; this.write_scalar(result, dest)?; } + "pipe" => { + let [pipefd] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let result = this.pipe2(pipefd, /*flags*/ None)?; + this.write_scalar(result, dest)?; + } + "pipe2" => { + let [pipefd, flags] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let result = this.pipe2(pipefd, Some(flags))?; + this.write_scalar(result, dest)?; + } // Time "gettimeofday" => { @@ -815,6 +826,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.handle_miri_start_unwind(payload)?; return Ok(EmulateItemResult::NeedsUnwind); } + "getuid" => { + let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + // For now, just pretend we always have this fixed UID. + this.write_int(UID, dest)?; + } // Incomplete shims that we "stub out" just to get pre-main initialization code to work. // These shims are enabled only when the caller is in the standard library. @@ -877,13 +893,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_null(dest)?; } - "getuid" - if this.frame_in_std() => { - let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - // For now, just pretend we always have this fixed UID. - this.write_int(super::UID, dest)?; - } - "getpwuid_r" | "__posix_getpwuid_r" if this.frame_in_std() => { // getpwuid_r is the standard name, __posix_getpwuid_r is used on solarish @@ -898,7 +907,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let result = this.deref_pointer(result)?; // Must be for "us". - if uid != crate::shims::unix::UID { + if uid != UID { throw_unsup_format!("`getpwuid_r` on other users is not supported"); } diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index d93374db818..e00758bb98d 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -12,6 +12,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_target::abi::Size; use crate::shims::os_str::bytes_to_os_str; +use crate::shims::unix::fd::FileDescriptionRef; use crate::shims::unix::*; use crate::*; use shims::time::system_time_to_duration; @@ -30,27 +31,29 @@ impl FileDescription for FileHandle { } fn read<'tcx>( - &mut self, + &self, + _self_ref: &FileDescriptionRef, communicate_allowed: bool, bytes: &mut [u8], _ecx: &mut MiriInterpCx<'tcx>, ) -> InterpResult<'tcx, io::Result> { assert!(communicate_allowed, "isolation should have prevented even opening a file"); - Ok(self.file.read(bytes)) + Ok((&mut &self.file).read(bytes)) } fn write<'tcx>( - &mut self, + &self, + _self_ref: &FileDescriptionRef, communicate_allowed: bool, bytes: &[u8], _ecx: &mut MiriInterpCx<'tcx>, ) -> InterpResult<'tcx, io::Result> { assert!(communicate_allowed, "isolation should have prevented even opening a file"); - Ok(self.file.write(bytes)) + Ok((&mut &self.file).write(bytes)) } fn pread<'tcx>( - &mut self, + &self, communicate_allowed: bool, bytes: &mut [u8], offset: u64, @@ -60,13 +63,13 @@ impl FileDescription for FileHandle { // Emulates pread using seek + read + seek to restore cursor position. // Correctness of this emulation relies on sequential nature of Miri execution. // The closure is used to emulate `try` block, since we "bubble" `io::Error` using `?`. + let file = &mut &self.file; let mut f = || { - let cursor_pos = self.file.stream_position()?; - self.file.seek(SeekFrom::Start(offset))?; - let res = self.file.read(bytes); + let cursor_pos = file.stream_position()?; + file.seek(SeekFrom::Start(offset))?; + let res = file.read(bytes); // Attempt to restore cursor position even if the read has failed - self.file - .seek(SeekFrom::Start(cursor_pos)) + file.seek(SeekFrom::Start(cursor_pos)) .expect("failed to restore file position, this shouldn't be possible"); res }; @@ -74,7 +77,7 @@ impl FileDescription for FileHandle { } fn pwrite<'tcx>( - &mut self, + &self, communicate_allowed: bool, bytes: &[u8], offset: u64, @@ -84,13 +87,13 @@ impl FileDescription for FileHandle { // Emulates pwrite using seek + write + seek to restore cursor position. // Correctness of this emulation relies on sequential nature of Miri execution. // The closure is used to emulate `try` block, since we "bubble" `io::Error` using `?`. + let file = &mut &self.file; let mut f = || { - let cursor_pos = self.file.stream_position()?; - self.file.seek(SeekFrom::Start(offset))?; - let res = self.file.write(bytes); + let cursor_pos = file.stream_position()?; + file.seek(SeekFrom::Start(offset))?; + let res = file.write(bytes); // Attempt to restore cursor position even if the write has failed - self.file - .seek(SeekFrom::Start(cursor_pos)) + file.seek(SeekFrom::Start(cursor_pos)) .expect("failed to restore file position, this shouldn't be possible"); res }; @@ -98,17 +101,18 @@ impl FileDescription for FileHandle { } fn seek<'tcx>( - &mut self, + &self, communicate_allowed: bool, offset: SeekFrom, ) -> InterpResult<'tcx, io::Result> { assert!(communicate_allowed, "isolation should have prevented even opening a file"); - Ok(self.file.seek(offset)) + Ok((&mut &self.file).seek(offset)) } fn close<'tcx>( self: Box, communicate_allowed: bool, + _ecx: &mut MiriInterpCx<'tcx>, ) -> InterpResult<'tcx, io::Result<()>> { assert!(communicate_allowed, "isolation should have prevented even opening a file"); // We sync the file if it was opened in a mode different than read-only. @@ -576,7 +580,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let communicate = this.machine.communicate(); - let Some(mut file_description) = this.machine.fds.get_mut(fd) else { + let Some(file_description) = this.machine.fds.get(fd) else { return Ok(Scalar::from_i64(this.fd_not_found()?)); }; let result = file_description @@ -1200,14 +1204,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { )?; } "freebsd" => { - this.write_int(ino, &this.project_field_named(&entry_place, "d_fileno")?)?; - // `d_off` only exists on FreeBSD 12+, but we support v11 as well. - // `libc` uses a build script to determine which version of the API to use, - // and cross-builds always end up using v11. - // To support both v11 and v12+, we dynamically check whether the field exists. - if this.projectable_has_field(&entry_place, "d_off") { - this.write_int(0, &this.project_field_named(&entry_place, "d_off")?)?; - } + #[rustfmt::skip] + this.write_int_fields_named( + &[ + ("d_fileno", ino.into()), + ("d_off", 0), + ], + &entry_place, + )?; } _ => unreachable!(), } @@ -1272,7 +1276,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // FIXME: Support ftruncate64 for all FDs let FileHandle { file, writable } = - file_description.downcast_ref::().ok_or_else(|| { + file_description.downcast::().ok_or_else(|| { err_unsup_format!("`ftruncate64` is only supported on file-backed file descriptors") })?; @@ -1324,7 +1328,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { }; // Only regular files support synchronization. let FileHandle { file, writable } = - file_description.downcast_ref::().ok_or_else(|| { + file_description.downcast::().ok_or_else(|| { err_unsup_format!("`fsync` is only supported on file-backed file descriptors") })?; let io_result = maybe_sync_file(file, *writable, File::sync_all); @@ -1349,7 +1353,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { }; // Only regular files support synchronization. let FileHandle { file, writable } = - file_description.downcast_ref::().ok_or_else(|| { + file_description.downcast::().ok_or_else(|| { err_unsup_format!("`fdatasync` is only supported on file-backed file descriptors") })?; let io_result = maybe_sync_file(file, *writable, File::sync_data); @@ -1397,7 +1401,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { }; // Only regular files support synchronization. let FileHandle { file, writable } = - file_description.downcast_ref::().ok_or_else(|| { + file_description.downcast::().ok_or_else(|| { err_unsup_format!( "`sync_data_range` is only supported on file-backed file descriptors" ) @@ -1704,7 +1708,7 @@ impl FileMetadata { }; let file = &file_description - .downcast_ref::() + .downcast::() .ok_or_else(|| { err_unsup_format!( "obtaining metadata is only supported on file-backed file descriptors" diff --git a/src/tools/miri/src/shims/unix/linux/epoll.rs b/src/tools/miri/src/shims/unix/linux/epoll.rs index 9127db3d004..fb1e0afdf9e 100644 --- a/src/tools/miri/src/shims/unix/linux/epoll.rs +++ b/src/tools/miri/src/shims/unix/linux/epoll.rs @@ -1,32 +1,127 @@ +use std::cell::RefCell; +use std::collections::BTreeMap; use std::io; +use std::rc::{Rc, Weak}; -use rustc_data_structures::fx::FxHashMap; - +use crate::shims::unix::fd::{FdId, FileDescriptionRef}; use crate::shims::unix::*; use crate::*; /// An `Epoll` file descriptor connects file handles and epoll events #[derive(Clone, Debug, Default)] struct Epoll { - /// The file descriptors we are watching, and what we are watching for. - file_descriptors: FxHashMap, + /// A map of EpollEventInterests registered under this epoll instance. + /// Each entry is differentiated using FdId and file descriptor value. + interest_list: RefCell>>>, + /// A map of EpollEventInstance that will be returned when `epoll_wait` is called. + /// Similar to interest_list, the entry is also differentiated using FdId + /// and file descriptor value. + // This is an Rc because EpollInterest need to hold a reference to update + // it. + ready_list: Rc>>, } -/// Epoll Events associate events with data. -/// These fields are currently unused by miri. -/// This matches the `epoll_event` struct defined +/// EpollEventInstance contains information that will be returned by epoll_wait. +#[derive(Debug)] +pub struct EpollEventInstance { + /// Xor-ed event types that happened to the file description. + events: u32, + /// Original data retrieved from `epoll_event` during `epoll_ctl`. + data: u64, +} + +impl EpollEventInstance { + pub fn new(events: u32, data: u64) -> EpollEventInstance { + EpollEventInstance { events, data } + } +} + +/// EpollEventInterest registers the file description information to an epoll +/// instance during a successful `epoll_ctl` call. It also stores additional +/// information needed to check and update readiness state for `epoll_wait`. +/// +/// `events` and `data` field matches the `epoll_event` struct defined /// by the epoll_ctl man page. For more information /// see the man page: /// /// #[derive(Clone, Debug)] -struct EpollEvent { - #[allow(dead_code)] +pub struct EpollEventInterest { + /// The file descriptor value of the file description registered. + file_descriptor: i32, + /// The events bitmask retrieved from `epoll_event`. events: u32, - /// `Scalar` is used to represent the - /// `epoll_data` type union. - #[allow(dead_code)] - data: Scalar, + /// The data retrieved from `epoll_event`. + /// libc's data field in epoll_event can store integer or pointer, + /// but only u64 is supported for now. + /// + data: u64, + /// Ready list of the epoll instance under which this EpollEventInterest is registered. + ready_list: Rc>>, +} + +/// EpollReadyEvents reflects the readiness of a file description. +pub struct EpollReadyEvents { + /// The associated file is available for read(2) operations, in the sense that a read will not block. + /// (I.e., returning EOF is considered "ready".) + pub epollin: bool, + /// The associated file is available for write(2) operations, in the sense that a write will not block. + pub epollout: bool, + /// Stream socket peer closed connection, or shut down writing + /// half of connection. + pub epollrdhup: bool, + /// For stream socket, this event merely indicates that the peer + /// closed its end of the channel. + /// Unlike epollrdhup, this should only be set when the stream is fully closed. + /// epollrdhup also gets set when only the write half is closed, which is possible + /// via `shutdown(_, SHUT_WR)`. + pub epollhup: bool, + /// Error condition happened on the associated file descriptor. + pub epollerr: bool, +} + +impl EpollReadyEvents { + pub fn new() -> Self { + EpollReadyEvents { + epollin: false, + epollout: false, + epollrdhup: false, + epollhup: false, + epollerr: false, + } + } + + pub fn get_event_bitmask<'tcx>(&self, ecx: &MiriInterpCx<'tcx>) -> u32 { + let epollin = ecx.eval_libc_u32("EPOLLIN"); + let epollout = ecx.eval_libc_u32("EPOLLOUT"); + let epollrdhup = ecx.eval_libc_u32("EPOLLRDHUP"); + let epollhup = ecx.eval_libc_u32("EPOLLHUP"); + let epollerr = ecx.eval_libc_u32("EPOLLERR"); + + let mut bitmask = 0; + if self.epollin { + bitmask |= epollin; + } + if self.epollout { + bitmask |= epollout; + } + if self.epollrdhup { + bitmask |= epollrdhup; + } + if self.epollhup { + bitmask |= epollhup; + } + if self.epollerr { + bitmask |= epollerr; + } + bitmask + } +} + +impl Epoll { + fn get_ready_list(&self) -> Rc>> { + Rc::clone(&self.ready_list) + } } impl FileDescription for Epoll { @@ -37,11 +132,51 @@ impl FileDescription for Epoll { fn close<'tcx>( self: Box, _communicate_allowed: bool, + _ecx: &mut MiriInterpCx<'tcx>, ) -> InterpResult<'tcx, io::Result<()>> { Ok(Ok(())) } } +/// The table of all EpollEventInterest. +/// The BTreeMap key is the FdId of an active file description registered with +/// any epoll instance. The value is a list of EpollEventInterest associated +/// with that file description. +pub struct EpollInterestTable(BTreeMap>>>); + +impl EpollInterestTable { + pub(crate) fn new() -> Self { + EpollInterestTable(BTreeMap::new()) + } + + pub fn insert_epoll_interest(&mut self, id: FdId, fd: Weak>) { + match self.0.get_mut(&id) { + Some(fds) => { + fds.push(fd); + } + None => { + let vec = vec![fd]; + self.0.insert(id, vec); + } + } + } + + pub fn get_epoll_interest(&self, id: FdId) -> Option<&Vec>>> { + self.0.get(&id) + } + + pub fn get_epoll_interest_mut( + &mut self, + id: FdId, + ) -> Option<&mut Vec>>> { + self.0.get_mut(&id) + } + + pub fn remove(&mut self, id: FdId) { + self.0.remove(&id); + } +} + impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { /// This function returns a file descriptor referring to the new `Epoll` instance. This file @@ -64,6 +199,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ); } + let mut epoll_instance = Epoll::default(); + epoll_instance.ready_list = Rc::new(RefCell::new(BTreeMap::new())); + let fd = this.machine.fds.insert_new(Epoll::default()); Ok(Scalar::from_i32(fd)) } @@ -90,48 +228,156 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - let epfd = this.read_scalar(epfd)?.to_i32()?; + let epfd_value = this.read_scalar(epfd)?.to_i32()?; let op = this.read_scalar(op)?.to_i32()?; let fd = this.read_scalar(fd)?.to_i32()?; - let _event = this.read_scalar(event)?.to_pointer(this)?; + let event = this.deref_pointer_as(event, this.libc_ty_layout("epoll_event"))?; let epoll_ctl_add = this.eval_libc_i32("EPOLL_CTL_ADD"); let epoll_ctl_mod = this.eval_libc_i32("EPOLL_CTL_MOD"); let epoll_ctl_del = this.eval_libc_i32("EPOLL_CTL_DEL"); + let epollin = this.eval_libc_u32("EPOLLIN"); + let epollout = this.eval_libc_u32("EPOLLOUT"); + let epollrdhup = this.eval_libc_u32("EPOLLRDHUP"); + let epollet = this.eval_libc_u32("EPOLLET"); + let epollhup = this.eval_libc_u32("EPOLLHUP"); + let epollerr = this.eval_libc_u32("EPOLLERR"); + + // Fail on unsupported operations. + if op & epoll_ctl_add != epoll_ctl_add + && op & epoll_ctl_mod != epoll_ctl_mod + && op & epoll_ctl_del != epoll_ctl_del + { + throw_unsup_format!("epoll_ctl: encountered unknown unsupported operation {:#x}", op); + } + + // Check if epfd is a valid epoll file descriptor. + let Some(epfd) = this.machine.fds.get(epfd_value) else { + return Ok(Scalar::from_i32(this.fd_not_found()?)); + }; + let epoll_file_description = epfd + .downcast::() + .ok_or_else(|| err_unsup_format!("non-epoll FD passed to `epoll_ctl`"))?; + + let mut interest_list = epoll_file_description.interest_list.borrow_mut(); + let ready_list = &epoll_file_description.ready_list; + + let Some(file_descriptor) = this.machine.fds.get(fd) else { + return Ok(Scalar::from_i32(this.fd_not_found()?)); + }; + let id = file_descriptor.get_id(); if op == epoll_ctl_add || op == epoll_ctl_mod { - let event = this.deref_pointer_as(event, this.libc_ty_layout("epoll_event"))?; + // Read event bitmask and data from epoll_event passed by caller. + let mut events = this.read_scalar(&this.project_field(&event, 0)?)?.to_u32()?; + let data = this.read_scalar(&this.project_field(&event, 1)?)?.to_u64()?; - let events = this.project_field(&event, 0)?; - let events = this.read_scalar(&events)?.to_u32()?; - let data = this.project_field(&event, 1)?; - let data = this.read_scalar(&data)?; - let event = EpollEvent { events, data }; + // Unset the flag we support to discover if any unsupported flags are used. + let mut flags = events; + // epoll_wait(2) will always wait for epollhup and epollerr; it is not + // necessary to set it in events when calling epoll_ctl(). + // So we will always set these two event types. + events |= epollhup; + events |= epollerr; - let Some(mut epfd) = this.machine.fds.get_mut(epfd) else { - return Ok(Scalar::from_i32(this.fd_not_found()?)); - }; - let epfd = epfd - .downcast_mut::() - .ok_or_else(|| err_unsup_format!("non-epoll FD passed to `epoll_ctl`"))?; + if events & epollet != epollet { + // We only support edge-triggered notification for now. + throw_unsup_format!("epoll_ctl: epollet flag must be included."); + } else { + flags &= !epollet; + } + if flags & epollin == epollin { + flags &= !epollin; + } + if flags & epollout == epollout { + flags &= !epollout; + } + if flags & epollrdhup == epollrdhup { + flags &= !epollrdhup; + } + if flags & epollhup == epollhup { + flags &= !epollhup; + } + if flags & epollerr == epollerr { + flags &= !epollerr; + } + if flags != 0 { + throw_unsup_format!( + "epoll_ctl: encountered unknown unsupported flags {:#x}", + flags + ); + } - epfd.file_descriptors.insert(fd, event); - Ok(Scalar::from_i32(0)) + let epoll_key = (id, fd); + + // Check the existence of fd in the interest list. + if op == epoll_ctl_add { + if interest_list.contains_key(&epoll_key) { + let eexist = this.eval_libc("EEXIST"); + this.set_last_error(eexist)?; + return Ok(Scalar::from_i32(-1)); + } + } else { + if !interest_list.contains_key(&epoll_key) { + let enoent = this.eval_libc("ENOENT"); + this.set_last_error(enoent)?; + return Ok(Scalar::from_i32(-1)); + } + } + + let id = file_descriptor.get_id(); + // Create an epoll_interest. + let interest = Rc::new(RefCell::new(EpollEventInterest { + file_descriptor: fd, + events, + data, + ready_list: Rc::clone(ready_list), + })); + + if op == epoll_ctl_add { + // Insert an epoll_interest to global epoll_interest list. + this.machine.epoll_interests.insert_epoll_interest(id, Rc::downgrade(&interest)); + interest_list.insert(epoll_key, interest); + } else { + // Directly modify the epoll_interest so the global epoll_event_interest table + // will be updated too. + let mut epoll_interest = interest_list.get_mut(&epoll_key).unwrap().borrow_mut(); + epoll_interest.events = events; + epoll_interest.data = data; + } + + // Readiness will be updated immediately when the epoll_event_interest is added or modified. + this.check_and_update_readiness(&file_descriptor)?; + + return Ok(Scalar::from_i32(0)); } else if op == epoll_ctl_del { - let Some(mut epfd) = this.machine.fds.get_mut(epfd) else { - return Ok(Scalar::from_i32(this.fd_not_found()?)); - }; - let epfd = epfd - .downcast_mut::() - .ok_or_else(|| err_unsup_format!("non-epoll FD passed to `epoll_ctl`"))?; + let epoll_key = (id, fd); - epfd.file_descriptors.remove(&fd); - Ok(Scalar::from_i32(0)) - } else { - let einval = this.eval_libc("EINVAL"); - this.set_last_error(einval)?; - Ok(Scalar::from_i32(-1)) + // Remove epoll_event_interest from interest_list. + let Some(epoll_interest) = interest_list.remove(&epoll_key) else { + let enoent = this.eval_libc("ENOENT"); + this.set_last_error(enoent)?; + return Ok(Scalar::from_i32(-1)); + }; + // All related Weak will fail to upgrade after the drop. + drop(epoll_interest); + + // Remove related epoll_interest from ready list. + ready_list.borrow_mut().remove(&epoll_key); + + // Remove dangling EpollEventInterest from its global table. + // .unwrap() below should succeed because the file description id must have registered + // at least one epoll_interest, if not, it will fail when removing epoll_interest from + // interest list. + this.machine + .epoll_interests + .get_epoll_interest_mut(id) + .unwrap() + .retain(|event| event.upgrade().is_some()); + + return Ok(Scalar::from_i32(0)); } + Ok(Scalar::from_i32(-1)) } /// The `epoll_wait()` system call waits for events on the `Epoll` @@ -166,25 +412,116 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn epoll_wait( &mut self, epfd: &OpTy<'tcx>, - events: &OpTy<'tcx>, + events_op: &OpTy<'tcx>, maxevents: &OpTy<'tcx>, timeout: &OpTy<'tcx>, ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); let epfd = this.read_scalar(epfd)?.to_i32()?; - let _events = this.read_scalar(events)?.to_pointer(this)?; - let _maxevents = this.read_scalar(maxevents)?.to_i32()?; - let _timeout = this.read_scalar(timeout)?.to_i32()?; + let events = this.read_immediate(events_op)?; + let maxevents = this.read_scalar(maxevents)?.to_i32()?; + let timeout = this.read_scalar(timeout)?.to_i32()?; - let Some(mut epfd) = this.machine.fds.get_mut(epfd) else { + if epfd <= 0 || maxevents <= 0 { + let einval = this.eval_libc("EINVAL"); + this.set_last_error(einval)?; + return Ok(Scalar::from_i32(-1)); + } + + // This needs to come after the maxevents value check, or else maxevents.try_into().unwrap() + // will fail. + let events = this.deref_pointer_as( + &events, + this.libc_array_ty_layout("epoll_event", maxevents.try_into().unwrap()), + )?; + + // FIXME: Implement blocking support + if timeout != 0 { + throw_unsup_format!("epoll_wait: timeout value can only be 0"); + } + + let Some(epfd) = this.machine.fds.get(epfd) else { return Ok(Scalar::from_i32(this.fd_not_found()?)); }; - let _epfd = epfd - .downcast_mut::() + let epoll_file_description = epfd + .downcast::() .ok_or_else(|| err_unsup_format!("non-epoll FD passed to `epoll_wait`"))?; - // FIXME return number of events ready when scheme for marking events ready exists - throw_unsup_format!("returning ready events from epoll_wait is not yet implemented"); + let ready_list = epoll_file_description.get_ready_list(); + let mut ready_list = ready_list.borrow_mut(); + let mut num_of_events: i32 = 0; + let mut array_iter = this.project_array_fields(&events)?; + + while let Some(des) = array_iter.next(this)? { + if let Some(epoll_event_instance) = ready_list_next(this, &mut ready_list) { + this.write_int_fields_named( + &[ + ("events", epoll_event_instance.events.into()), + ("u64", epoll_event_instance.data.into()), + ], + &des.1, + )?; + num_of_events = num_of_events.strict_add(1); + } else { + break; + } + } + Ok(Scalar::from_i32(num_of_events)) + } + + /// For a specific file description, get its ready events and update the corresponding ready + /// list. This function should be called whenever an event causes more bytes or an EOF to become + /// newly readable from an FD, and whenever more bytes can be written to an FD or no more future + /// writes are possible. + /// + /// This *will* report an event if anyone is subscribed to it, without any further filtering, so + /// do not call this function when an FD didn't have anything happen to it! + fn check_and_update_readiness(&self, fd_ref: &FileDescriptionRef) -> InterpResult<'tcx, ()> { + let this = self.eval_context_ref(); + let id = fd_ref.get_id(); + // Get a list of EpollEventInterest that is associated to a specific file description. + if let Some(epoll_interests) = this.machine.epoll_interests.get_epoll_interest(id) { + let epoll_ready_events = fd_ref.get_epoll_ready_events()?; + // Get the bitmask of ready events. + let ready_events = epoll_ready_events.get_event_bitmask(this); + + for weak_epoll_interest in epoll_interests { + if let Some(epoll_interest) = weak_epoll_interest.upgrade() { + // This checks if any of the events specified in epoll_event_interest.events + // match those in ready_events. + let epoll_event_interest = epoll_interest.borrow(); + let flags = epoll_event_interest.events & ready_events; + // If there is any event that we are interested in being specified as ready, + // insert an epoll_return to the ready list. + if flags != 0 { + let epoll_key = (id, epoll_event_interest.file_descriptor); + let ready_list = &mut epoll_event_interest.ready_list.borrow_mut(); + let event_instance = + EpollEventInstance::new(flags, epoll_event_interest.data); + ready_list.insert(epoll_key, event_instance); + } + } + } + } + Ok(()) } } + +/// This function takes in ready list and returns EpollEventInstance with file description +/// that is not closed. +fn ready_list_next( + ecx: &MiriInterpCx<'_>, + ready_list: &mut BTreeMap<(FdId, i32), EpollEventInstance>, +) -> Option { + while let Some((epoll_key, epoll_event_instance)) = ready_list.pop_first() { + // This ensures that we only return events that we are interested. The FD might have been closed since + // the event was generated, in which case we are not interested anymore. + // When a file description is fully closed, it gets removed from `machine.epoll_interests`, + // so we skip events whose FD is not in that map anymore. + if ecx.machine.epoll_interests.get_epoll_interest(epoll_key.0).is_some() { + return Some(epoll_event_instance); + } + } + return None; +} diff --git a/src/tools/miri/src/shims/unix/linux/eventfd.rs b/src/tools/miri/src/shims/unix/linux/eventfd.rs index 4ab8760d930..77d16a032aa 100644 --- a/src/tools/miri/src/shims/unix/linux/eventfd.rs +++ b/src/tools/miri/src/shims/unix/linux/eventfd.rs @@ -1,10 +1,13 @@ //! Linux `eventfd` implementation. +use std::cell::{Cell, RefCell}; use std::io; use std::io::{Error, ErrorKind}; use std::mem; use rustc_target::abi::Endian; +use crate::shims::unix::fd::FileDescriptionRef; +use crate::shims::unix::linux::epoll::{EpollReadyEvents, EvalContextExt as _}; use crate::shims::unix::*; use crate::{concurrency::VClock, *}; @@ -25,9 +28,9 @@ const MAX_COUNTER: u64 = u64::MAX - 1; struct Event { /// The object contains an unsigned 64-bit integer (uint64_t) counter that is maintained by the /// kernel. This counter is initialized with the value specified in the argument initval. - counter: u64, + counter: Cell, is_nonblock: bool, - clock: VClock, + clock: RefCell, } impl FileDescription for Event { @@ -35,16 +38,29 @@ impl FileDescription for Event { "event" } + fn get_epoll_ready_events<'tcx>(&self) -> InterpResult<'tcx, EpollReadyEvents> { + // We only check the status of EPOLLIN and EPOLLOUT flags for eventfd. If other event flags + // need to be supported in the future, the check should be added here. + + Ok(EpollReadyEvents { + epollin: self.counter.get() != 0, + epollout: self.counter.get() != MAX_COUNTER, + ..EpollReadyEvents::new() + }) + } + fn close<'tcx>( self: Box, _communicate_allowed: bool, + _ecx: &mut MiriInterpCx<'tcx>, ) -> InterpResult<'tcx, io::Result<()>> { Ok(Ok(())) } /// Read the counter in the buffer and return the counter if succeeded. fn read<'tcx>( - &mut self, + &self, + self_ref: &FileDescriptionRef, _communicate_allowed: bool, bytes: &mut [u8], ecx: &mut MiriInterpCx<'tcx>, @@ -54,7 +70,8 @@ impl FileDescription for Event { return Ok(Err(Error::from(ErrorKind::InvalidInput))); }; // Block when counter == 0. - if self.counter == 0 { + let counter = self.counter.get(); + if counter == 0 { if self.is_nonblock { return Ok(Err(Error::from(ErrorKind::WouldBlock))); } else { @@ -63,13 +80,17 @@ impl FileDescription for Event { } } else { // Synchronize with all prior `write` calls to this FD. - ecx.acquire_clock(&self.clock); + ecx.acquire_clock(&self.clock.borrow()); // Return the counter in the host endianness using the buffer provided by caller. *bytes = match ecx.tcx.sess.target.endian { - Endian::Little => self.counter.to_le_bytes(), - Endian::Big => self.counter.to_be_bytes(), + Endian::Little => counter.to_le_bytes(), + Endian::Big => counter.to_be_bytes(), }; - self.counter = 0; + self.counter.set(0); + // When any of the event happened, we check and update the status of all supported event + // types for current file description. + ecx.check_and_update_readiness(self_ref)?; + return Ok(Ok(U64_ARRAY_SIZE)); } } @@ -87,7 +108,8 @@ impl FileDescription for Event { /// supplied buffer is less than 8 bytes, or if an attempt is /// made to write the value 0xffffffffffffffff. fn write<'tcx>( - &mut self, + &self, + self_ref: &FileDescriptionRef, _communicate_allowed: bool, bytes: &[u8], ecx: &mut MiriInterpCx<'tcx>, @@ -107,13 +129,13 @@ impl FileDescription for Event { } // If the addition does not let the counter to exceed the maximum value, update the counter. // Else, block. - match self.counter.checked_add(num) { + match self.counter.get().checked_add(num) { Some(new_count @ 0..=MAX_COUNTER) => { // Future `read` calls will synchronize with this write, so update the FD clock. if let Some(clock) = &ecx.release_clock() { - self.clock.join(clock); + self.clock.borrow_mut().join(clock); } - self.counter = new_count; + self.counter.set(new_count); } None | Some(u64::MAX) => { if self.is_nonblock { @@ -124,6 +146,10 @@ impl FileDescription for Event { } } }; + // When any of the event happened, we check and update the status of all supported event + // types for current file description. + ecx.check_and_update_readiness(self_ref)?; + Ok(Ok(U64_ARRAY_SIZE)) } } @@ -178,11 +204,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { throw_unsup_format!("eventfd: encountered unknown unsupported flags {:#x}", flags); } - let fd = this.machine.fds.insert_new(Event { - counter: val.into(), + let fds = &mut this.machine.fds; + + let fd_value = fds.insert_new(Event { + counter: Cell::new(val.into()), is_nonblock, - clock: VClock::default(), + clock: RefCell::new(VClock::default()), }); - Ok(Scalar::from_i32(fd)) + + Ok(Scalar::from_i32(fd_value)) } } diff --git a/src/tools/miri/src/shims/unix/mod.rs b/src/tools/miri/src/shims/unix/mod.rs index dc9068fddde..7da6d7b02a2 100644 --- a/src/tools/miri/src/shims/unix/mod.rs +++ b/src/tools/miri/src/shims/unix/mod.rs @@ -4,9 +4,9 @@ mod env; mod fd; mod fs; mod mem; -mod socket; mod sync; mod thread; +mod unnamed_socket; mod android; mod freebsd; @@ -17,14 +17,15 @@ mod solarish; pub use env::UnixEnvVars; pub use fd::{FdTable, FileDescription}; pub use fs::DirTable; +pub use linux::epoll::EpollInterestTable; // All the Unix-specific extension traits pub use env::EvalContextExt as _; pub use fd::EvalContextExt as _; pub use fs::EvalContextExt as _; pub use mem::EvalContextExt as _; -pub use socket::EvalContextExt as _; pub use sync::EvalContextExt as _; pub use thread::EvalContextExt as _; +pub use unnamed_socket::EvalContextExt as _; // Make up some constants. const UID: u32 = 1000; diff --git a/src/tools/miri/src/shims/unix/socket.rs b/src/tools/miri/src/shims/unix/socket.rs deleted file mode 100644 index 455820a9e6e..00000000000 --- a/src/tools/miri/src/shims/unix/socket.rs +++ /dev/null @@ -1,232 +0,0 @@ -use std::cell::RefCell; -use std::collections::VecDeque; -use std::io; -use std::io::{Error, ErrorKind, Read}; -use std::rc::{Rc, Weak}; - -use crate::shims::unix::*; -use crate::{concurrency::VClock, *}; - -/// The maximum capacity of the socketpair buffer in bytes. -/// This number is arbitrary as the value can always -/// be configured in the real system. -const MAX_SOCKETPAIR_BUFFER_CAPACITY: usize = 212992; - -/// Pair of connected sockets. -#[derive(Debug)] -struct SocketPair { - // By making the write link weak, a `write` can detect when all readers are - // gone, and trigger EPIPE as appropriate. - writebuf: Weak>, - readbuf: Rc>, - is_nonblock: bool, -} - -#[derive(Debug)] -struct Buffer { - buf: VecDeque, - clock: VClock, - /// Indicates if there is at least one active writer to this buffer. - /// If all writers of this buffer are dropped, buf_has_writer becomes false and we - /// indicate EOF instead of blocking. - buf_has_writer: bool, -} - -impl FileDescription for SocketPair { - fn name(&self) -> &'static str { - "socketpair" - } - - fn close<'tcx>( - self: Box, - _communicate_allowed: bool, - ) -> InterpResult<'tcx, io::Result<()>> { - // This is used to signal socketfd of other side that there is no writer to its readbuf. - // If the upgrade fails, there is no need to update as all read ends have been dropped. - if let Some(writebuf) = self.writebuf.upgrade() { - writebuf.borrow_mut().buf_has_writer = false; - }; - Ok(Ok(())) - } - - fn read<'tcx>( - &mut self, - _communicate_allowed: bool, - bytes: &mut [u8], - ecx: &mut MiriInterpCx<'tcx>, - ) -> InterpResult<'tcx, io::Result> { - let request_byte_size = bytes.len(); - let mut readbuf = self.readbuf.borrow_mut(); - - // Always succeed on read size 0. - if request_byte_size == 0 { - return Ok(Ok(0)); - } - - if readbuf.buf.is_empty() { - if !readbuf.buf_has_writer { - // Socketpair with no writer and empty buffer. - // 0 bytes successfully read indicates end-of-file. - return Ok(Ok(0)); - } else { - if self.is_nonblock { - // Non-blocking socketpair with writer and empty buffer. - // https://linux.die.net/man/2/read - // EAGAIN or EWOULDBLOCK can be returned for socket, - // POSIX.1-2001 allows either error to be returned for this case. - // Since there is no ErrorKind for EAGAIN, WouldBlock is used. - return Ok(Err(Error::from(ErrorKind::WouldBlock))); - } else { - // Blocking socketpair with writer and empty buffer. - // FIXME: blocking is currently not supported - throw_unsup_format!("socketpair read: blocking isn't supported yet"); - } - } - } - - // Synchronize with all previous writes to this buffer. - // FIXME: this over-synchronizes; a more precise approach would be to - // only sync with the writes whose data we will read. - ecx.acquire_clock(&readbuf.clock); - // Do full read / partial read based on the space available. - // Conveniently, `read` exists on `VecDeque` and has exactly the desired behavior. - let actual_read_size = readbuf.buf.read(bytes).unwrap(); - return Ok(Ok(actual_read_size)); - } - - fn write<'tcx>( - &mut self, - _communicate_allowed: bool, - bytes: &[u8], - ecx: &mut MiriInterpCx<'tcx>, - ) -> InterpResult<'tcx, io::Result> { - let write_size = bytes.len(); - // Always succeed on write size 0. - // ("If count is zero and fd refers to a file other than a regular file, the results are not specified.") - if write_size == 0 { - return Ok(Ok(0)); - } - - let Some(writebuf) = self.writebuf.upgrade() else { - // If the upgrade from Weak to Rc fails, it indicates that all read ends have been - // closed. - return Ok(Err(Error::from(ErrorKind::BrokenPipe))); - }; - let mut writebuf = writebuf.borrow_mut(); - let data_size = writebuf.buf.len(); - let available_space = MAX_SOCKETPAIR_BUFFER_CAPACITY.strict_sub(data_size); - if available_space == 0 { - if self.is_nonblock { - // Non-blocking socketpair with a full buffer. - return Ok(Err(Error::from(ErrorKind::WouldBlock))); - } else { - // Blocking socketpair with a full buffer. - throw_unsup_format!("socketpair write: blocking isn't supported yet"); - } - } - // Remember this clock so `read` can synchronize with us. - if let Some(clock) = &ecx.release_clock() { - writebuf.clock.join(clock); - } - // Do full write / partial write based on the space available. - let actual_write_size = write_size.min(available_space); - writebuf.buf.extend(&bytes[..actual_write_size]); - return Ok(Ok(actual_write_size)); - } -} - -impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} -pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { - /// For more information on the arguments see the socketpair manpage: - /// - fn socketpair( - &mut self, - domain: &OpTy<'tcx>, - type_: &OpTy<'tcx>, - protocol: &OpTy<'tcx>, - sv: &OpTy<'tcx>, - ) -> InterpResult<'tcx, Scalar> { - let this = self.eval_context_mut(); - - let domain = this.read_scalar(domain)?.to_i32()?; - let mut type_ = this.read_scalar(type_)?.to_i32()?; - let protocol = this.read_scalar(protocol)?.to_i32()?; - let sv = this.deref_pointer(sv)?; - - let mut is_sock_nonblock = false; - - // Parse and remove the type flags that we support. If type != 0 after removing, - // unsupported flags are used. - if type_ & this.eval_libc_i32("SOCK_STREAM") == this.eval_libc_i32("SOCK_STREAM") { - type_ &= !(this.eval_libc_i32("SOCK_STREAM")); - } - - // SOCK_NONBLOCK only exists on Linux. - if this.tcx.sess.target.os == "linux" { - if type_ & this.eval_libc_i32("SOCK_NONBLOCK") == this.eval_libc_i32("SOCK_NONBLOCK") { - is_sock_nonblock = true; - type_ &= !(this.eval_libc_i32("SOCK_NONBLOCK")); - } - if type_ & this.eval_libc_i32("SOCK_CLOEXEC") == this.eval_libc_i32("SOCK_CLOEXEC") { - type_ &= !(this.eval_libc_i32("SOCK_CLOEXEC")); - } - } - - // Fail on unsupported input. - // AF_UNIX and AF_LOCAL are synonyms, so we accept both in case - // their values differ. - if domain != this.eval_libc_i32("AF_UNIX") && domain != this.eval_libc_i32("AF_LOCAL") { - throw_unsup_format!( - "socketpair: domain {:#x} is unsupported, only AF_UNIX \ - and AF_LOCAL are allowed", - domain - ); - } else if type_ != 0 { - throw_unsup_format!( - "socketpair: type {:#x} is unsupported, only SOCK_STREAM, \ - SOCK_CLOEXEC and SOCK_NONBLOCK are allowed", - type_ - ); - } else if protocol != 0 { - throw_unsup_format!( - "socketpair: socket protocol {protocol} is unsupported, \ - only 0 is allowed", - ); - } - - let buffer1 = Rc::new(RefCell::new(Buffer { - buf: VecDeque::new(), - clock: VClock::default(), - buf_has_writer: true, - })); - - let buffer2 = Rc::new(RefCell::new(Buffer { - buf: VecDeque::new(), - clock: VClock::default(), - buf_has_writer: true, - })); - - let socketpair_0 = SocketPair { - writebuf: Rc::downgrade(&buffer1), - readbuf: Rc::clone(&buffer2), - is_nonblock: is_sock_nonblock, - }; - - let socketpair_1 = SocketPair { - writebuf: Rc::downgrade(&buffer2), - readbuf: Rc::clone(&buffer1), - is_nonblock: is_sock_nonblock, - }; - - let fds = &mut this.machine.fds; - let sv0 = fds.insert_new(socketpair_0); - let sv1 = fds.insert_new(socketpair_1); - let sv0 = Scalar::from_int(sv0, sv.layout.size); - let sv1 = Scalar::from_int(sv1, sv.layout.size); - - this.write_scalar(sv0, &sv)?; - this.write_scalar(sv1, &sv.offset(sv.layout.size, sv.layout, this)?)?; - - Ok(Scalar::from_i32(0)) - } -} diff --git a/src/tools/miri/src/shims/unix/unnamed_socket.rs b/src/tools/miri/src/shims/unix/unnamed_socket.rs new file mode 100644 index 00000000000..745f27398d0 --- /dev/null +++ b/src/tools/miri/src/shims/unix/unnamed_socket.rs @@ -0,0 +1,386 @@ +//! This implements "anonymous" sockets, that do not correspond to anything on the host system and +//! are entirely implemented inside Miri. +//! We also use the same infrastructure to implement unnamed pipes. + +use std::cell::{Cell, OnceCell, RefCell}; +use std::collections::VecDeque; +use std::io; +use std::io::{Error, ErrorKind, Read}; + +use crate::shims::unix::fd::{FileDescriptionRef, WeakFileDescriptionRef}; +use crate::shims::unix::linux::epoll::{EpollReadyEvents, EvalContextExt as _}; +use crate::shims::unix::*; +use crate::{concurrency::VClock, *}; + +/// The maximum capacity of the socketpair buffer in bytes. +/// This number is arbitrary as the value can always +/// be configured in the real system. +const MAX_SOCKETPAIR_BUFFER_CAPACITY: usize = 212992; + +/// One end of a pair of connected unnamed sockets. +#[derive(Debug)] +struct AnonSocket { + /// The buffer we are reading from, or `None` if this is the writing end of a pipe. + /// (In that case, the peer FD will be the reading end of that pipe.) + readbuf: Option>, + /// The `AnonSocket` file descriptor that is our "peer", and that holds the buffer we are + /// writing to. This is a weak reference because the other side may be closed before us; all + /// future writes will then trigger EPIPE. + peer_fd: OnceCell, + /// Indicates whether the peer has lost data when the file description is closed. + /// This flag is set to `true` if the peer's `readbuf` is non-empty at the time + /// of closure. + peer_lost_data: Cell, + is_nonblock: bool, +} + +#[derive(Debug)] +struct Buffer { + buf: VecDeque, + clock: VClock, +} + +impl Buffer { + fn new() -> Self { + Buffer { buf: VecDeque::new(), clock: VClock::default() } + } +} + +impl AnonSocket { + fn peer_fd(&self) -> &WeakFileDescriptionRef { + self.peer_fd.get().unwrap() + } +} + +impl FileDescription for AnonSocket { + fn name(&self) -> &'static str { + "socketpair" + } + + fn get_epoll_ready_events<'tcx>(&self) -> InterpResult<'tcx, EpollReadyEvents> { + // We only check the status of EPOLLIN, EPOLLOUT, EPOLLHUP and EPOLLRDHUP flags. + // If other event flags need to be supported in the future, the check should be added here. + + let mut epoll_ready_events = EpollReadyEvents::new(); + + // Check if it is readable. + if let Some(readbuf) = &self.readbuf { + if !readbuf.borrow().buf.is_empty() { + epoll_ready_events.epollin = true; + } + } else { + // Without a read buffer, reading never blocks, so we are always ready. + epoll_ready_events.epollin = true; + } + + // Check if is writable. + if let Some(peer_fd) = self.peer_fd().upgrade() { + if let Some(writebuf) = &peer_fd.downcast::().unwrap().readbuf { + let data_size = writebuf.borrow().buf.len(); + let available_space = MAX_SOCKETPAIR_BUFFER_CAPACITY.strict_sub(data_size); + if available_space != 0 { + epoll_ready_events.epollout = true; + } + } else { + // Without a write buffer, writing never blocks. + epoll_ready_events.epollout = true; + } + } else { + // Peer FD has been closed. This always sets both the RDHUP and HUP flags + // as we do not support `shutdown` that could be used to partially close the stream. + epoll_ready_events.epollrdhup = true; + epoll_ready_events.epollhup = true; + // Since the peer is closed, even if no data is available reads will return EOF and + // writes will return EPIPE. In other words, they won't block, so we mark this as ready + // for read and write. + epoll_ready_events.epollin = true; + epoll_ready_events.epollout = true; + // If there is data lost in peer_fd, set EPOLLERR. + if self.peer_lost_data.get() { + epoll_ready_events.epollerr = true; + } + } + Ok(epoll_ready_events) + } + + fn close<'tcx>( + self: Box, + _communicate_allowed: bool, + ecx: &mut MiriInterpCx<'tcx>, + ) -> InterpResult<'tcx, io::Result<()>> { + if let Some(peer_fd) = self.peer_fd().upgrade() { + // If the current readbuf is non-empty when the file description is closed, + // notify the peer that data lost has happened in current file description. + if let Some(readbuf) = &self.readbuf { + if !readbuf.borrow().buf.is_empty() { + peer_fd.downcast::().unwrap().peer_lost_data.set(true); + } + } + // Notify peer fd that close has happened, since that can unblock reads and writes. + ecx.check_and_update_readiness(&peer_fd)?; + } + Ok(Ok(())) + } + + fn read<'tcx>( + &self, + _self_ref: &FileDescriptionRef, + _communicate_allowed: bool, + bytes: &mut [u8], + ecx: &mut MiriInterpCx<'tcx>, + ) -> InterpResult<'tcx, io::Result> { + let request_byte_size = bytes.len(); + + // Always succeed on read size 0. + if request_byte_size == 0 { + return Ok(Ok(0)); + } + + let Some(readbuf) = &self.readbuf else { + // FIXME: This should return EBADF, but there's no nice way to do that as there's no + // corresponding ErrorKind variant. + throw_unsup_format!("reading from the write end of a pipe"); + }; + let mut readbuf = readbuf.borrow_mut(); + if readbuf.buf.is_empty() { + if self.peer_fd().upgrade().is_none() { + // Socketpair with no peer and empty buffer. + // 0 bytes successfully read indicates end-of-file. + return Ok(Ok(0)); + } else { + if self.is_nonblock { + // Non-blocking socketpair with writer and empty buffer. + // https://linux.die.net/man/2/read + // EAGAIN or EWOULDBLOCK can be returned for socket, + // POSIX.1-2001 allows either error to be returned for this case. + // Since there is no ErrorKind for EAGAIN, WouldBlock is used. + return Ok(Err(Error::from(ErrorKind::WouldBlock))); + } else { + // Blocking socketpair with writer and empty buffer. + // FIXME: blocking is currently not supported + throw_unsup_format!("socketpair read: blocking isn't supported yet"); + } + } + } + + // Synchronize with all previous writes to this buffer. + // FIXME: this over-synchronizes; a more precise approach would be to + // only sync with the writes whose data we will read. + ecx.acquire_clock(&readbuf.clock); + + // Do full read / partial read based on the space available. + // Conveniently, `read` exists on `VecDeque` and has exactly the desired behavior. + let actual_read_size = readbuf.buf.read(bytes).unwrap(); + + // Need to drop before others can access the readbuf again. + drop(readbuf); + + // A notification should be provided for the peer file description even when it can + // only write 1 byte. This implementation is not compliant with the actual Linux kernel + // implementation. For optimization reasons, the kernel will only mark the file description + // as "writable" when it can write more than a certain number of bytes. Since we + // don't know what that *certain number* is, we will provide a notification every time + // a read is successful. This might result in our epoll emulation providing more + // notifications than the real system. + if let Some(peer_fd) = self.peer_fd().upgrade() { + ecx.check_and_update_readiness(&peer_fd)?; + } + + return Ok(Ok(actual_read_size)); + } + + fn write<'tcx>( + &self, + _self_ref: &FileDescriptionRef, + _communicate_allowed: bool, + bytes: &[u8], + ecx: &mut MiriInterpCx<'tcx>, + ) -> InterpResult<'tcx, io::Result> { + let write_size = bytes.len(); + // Always succeed on write size 0. + // ("If count is zero and fd refers to a file other than a regular file, the results are not specified.") + if write_size == 0 { + return Ok(Ok(0)); + } + + // We are writing to our peer's readbuf. + let Some(peer_fd) = self.peer_fd().upgrade() else { + // If the upgrade from Weak to Rc fails, it indicates that all read ends have been + // closed. + return Ok(Err(Error::from(ErrorKind::BrokenPipe))); + }; + + let Some(writebuf) = &peer_fd.downcast::().unwrap().readbuf else { + // FIXME: This should return EBADF, but there's no nice way to do that as there's no + // corresponding ErrorKind variant. + throw_unsup_format!("writing to the reading end of a pipe"); + }; + let mut writebuf = writebuf.borrow_mut(); + let data_size = writebuf.buf.len(); + let available_space = MAX_SOCKETPAIR_BUFFER_CAPACITY.strict_sub(data_size); + if available_space == 0 { + if self.is_nonblock { + // Non-blocking socketpair with a full buffer. + return Ok(Err(Error::from(ErrorKind::WouldBlock))); + } else { + // Blocking socketpair with a full buffer. + throw_unsup_format!("socketpair write: blocking isn't supported yet"); + } + } + // Remember this clock so `read` can synchronize with us. + if let Some(clock) = &ecx.release_clock() { + writebuf.clock.join(clock); + } + // Do full write / partial write based on the space available. + let actual_write_size = write_size.min(available_space); + writebuf.buf.extend(&bytes[..actual_write_size]); + + // Need to stop accessing peer_fd so that it can be notified. + drop(writebuf); + + // Notification should be provided for peer fd as it became readable. + // The kernel does this even if the fd was already readable before, so we follow suit. + ecx.check_and_update_readiness(&peer_fd)?; + + return Ok(Ok(actual_write_size)); + } +} + +impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} +pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { + /// For more information on the arguments see the socketpair manpage: + /// + fn socketpair( + &mut self, + domain: &OpTy<'tcx>, + type_: &OpTy<'tcx>, + protocol: &OpTy<'tcx>, + sv: &OpTy<'tcx>, + ) -> InterpResult<'tcx, Scalar> { + let this = self.eval_context_mut(); + + let domain = this.read_scalar(domain)?.to_i32()?; + let mut type_ = this.read_scalar(type_)?.to_i32()?; + let protocol = this.read_scalar(protocol)?.to_i32()?; + let sv = this.deref_pointer(sv)?; + + let mut is_sock_nonblock = false; + + // Parse and remove the type flags that we support. + // SOCK_NONBLOCK only exists on Linux. + if this.tcx.sess.target.os == "linux" { + if type_ & this.eval_libc_i32("SOCK_NONBLOCK") == this.eval_libc_i32("SOCK_NONBLOCK") { + is_sock_nonblock = true; + type_ &= !(this.eval_libc_i32("SOCK_NONBLOCK")); + } + if type_ & this.eval_libc_i32("SOCK_CLOEXEC") == this.eval_libc_i32("SOCK_CLOEXEC") { + type_ &= !(this.eval_libc_i32("SOCK_CLOEXEC")); + } + } + + // Fail on unsupported input. + // AF_UNIX and AF_LOCAL are synonyms, so we accept both in case + // their values differ. + if domain != this.eval_libc_i32("AF_UNIX") && domain != this.eval_libc_i32("AF_LOCAL") { + throw_unsup_format!( + "socketpair: domain {:#x} is unsupported, only AF_UNIX \ + and AF_LOCAL are allowed", + domain + ); + } else if type_ != this.eval_libc_i32("SOCK_STREAM") { + throw_unsup_format!( + "socketpair: type {:#x} is unsupported, only SOCK_STREAM, \ + SOCK_CLOEXEC and SOCK_NONBLOCK are allowed", + type_ + ); + } else if protocol != 0 { + throw_unsup_format!( + "socketpair: socket protocol {protocol} is unsupported, \ + only 0 is allowed", + ); + } + + // Generate file descriptions. + let fds = &mut this.machine.fds; + let fd0 = fds.new_ref(AnonSocket { + readbuf: Some(RefCell::new(Buffer::new())), + peer_fd: OnceCell::new(), + peer_lost_data: Cell::new(false), + is_nonblock: is_sock_nonblock, + }); + let fd1 = fds.new_ref(AnonSocket { + readbuf: Some(RefCell::new(Buffer::new())), + peer_fd: OnceCell::new(), + peer_lost_data: Cell::new(false), + is_nonblock: is_sock_nonblock, + }); + + // Make the file descriptions point to each other. + fd0.downcast::().unwrap().peer_fd.set(fd1.downgrade()).unwrap(); + fd1.downcast::().unwrap().peer_fd.set(fd0.downgrade()).unwrap(); + + // Insert the file description to the fd table, generating the file descriptors. + let sv0 = fds.insert(fd0); + let sv1 = fds.insert(fd1); + + // Return socketpair file descriptors to the caller. + let sv0 = Scalar::from_int(sv0, sv.layout.size); + let sv1 = Scalar::from_int(sv1, sv.layout.size); + this.write_scalar(sv0, &sv)?; + this.write_scalar(sv1, &sv.offset(sv.layout.size, sv.layout, this)?)?; + + Ok(Scalar::from_i32(0)) + } + + fn pipe2( + &mut self, + pipefd: &OpTy<'tcx>, + flags: Option<&OpTy<'tcx>>, + ) -> InterpResult<'tcx, Scalar> { + let this = self.eval_context_mut(); + + let pipefd = this.deref_pointer(pipefd)?; + let flags = match flags { + Some(flags) => this.read_scalar(flags)?.to_i32()?, + None => 0, + }; + + // As usual we ignore CLOEXEC. + let cloexec = this.eval_libc_i32("O_CLOEXEC"); + if flags != 0 && flags != cloexec { + throw_unsup_format!("unsupported flags in `pipe2`"); + } + + // Generate file descriptions. + // pipefd[0] refers to the read end of the pipe. + let fds = &mut this.machine.fds; + let fd0 = fds.new_ref(AnonSocket { + readbuf: Some(RefCell::new(Buffer::new())), + peer_fd: OnceCell::new(), + peer_lost_data: Cell::new(false), + is_nonblock: false, + }); + let fd1 = fds.new_ref(AnonSocket { + readbuf: None, + peer_fd: OnceCell::new(), + peer_lost_data: Cell::new(false), + is_nonblock: false, + }); + + // Make the file descriptions point to each other. + fd0.downcast::().unwrap().peer_fd.set(fd1.downgrade()).unwrap(); + fd1.downcast::().unwrap().peer_fd.set(fd0.downgrade()).unwrap(); + + // Insert the file description to the fd table, generating the file descriptors. + let pipefd0 = fds.insert(fd0); + let pipefd1 = fds.insert(fd1); + + // Return file descriptors to the caller. + let pipefd0 = Scalar::from_int(pipefd0, pipefd.layout.size); + let pipefd1 = Scalar::from_int(pipefd1, pipefd.layout.size); + this.write_scalar(pipefd0, &pipefd)?; + this.write_scalar(pipefd1, &pipefd.offset(pipefd.layout.size, pipefd.layout, this)?)?; + + Ok(Scalar::from_i32(0)) + } +} diff --git a/src/tools/miri/src/shims/x86/avx.rs b/src/tools/miri/src/shims/x86/avx.rs index f36bb4826e4..2f6569e1823 100644 --- a/src/tools/miri/src/shims/x86/avx.rs +++ b/src/tools/miri/src/shims/x86/avx.rs @@ -73,13 +73,12 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { round_all::(this, op, rounding, dest)?; } - // Used to implement _mm256_{sqrt,rcp,rsqrt}_ps functions. + // Used to implement _mm256_{rcp,rsqrt}_ps functions. // Performs the operations on all components of `op`. - "sqrt.ps.256" | "rcp.ps.256" | "rsqrt.ps.256" => { + "rcp.ps.256" | "rsqrt.ps.256" => { let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let which = match unprefixed_name { - "sqrt.ps.256" => FloatUnaryOp::Sqrt, "rcp.ps.256" => FloatUnaryOp::Rcp, "rsqrt.ps.256" => FloatUnaryOp::Rsqrt, _ => unreachable!(), diff --git a/src/tools/miri/src/shims/x86/mod.rs b/src/tools/miri/src/shims/x86/mod.rs index 1bd32fce8bd..305e59fa0cd 100644 --- a/src/tools/miri/src/shims/x86/mod.rs +++ b/src/tools/miri/src/shims/x86/mod.rs @@ -15,6 +15,7 @@ mod aesni; mod avx; mod avx2; mod bmi; +mod sha; mod sse; mod sse2; mod sse3; @@ -105,6 +106,11 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this, link_name, abi, args, dest, ); } + name if name.starts_with("sha") => { + return sha::EvalContextExt::emulate_x86_sha_intrinsic( + this, link_name, abi, args, dest, + ); + } name if name.starts_with("sse.") => { return sse::EvalContextExt::emulate_x86_sse_intrinsic( this, link_name, abi, args, dest, @@ -159,8 +165,6 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { #[derive(Copy, Clone)] enum FloatBinOp { - /// Arithmetic operation - Arith(mir::BinOp), /// Comparison /// /// The semantics of this operator is a case distinction: we compare the two operands, @@ -247,16 +251,11 @@ impl FloatBinOp { /// Performs `which` scalar operation on `left` and `right` and returns /// the result. fn bin_op_float<'tcx, F: rustc_apfloat::Float>( - this: &crate::MiriInterpCx<'tcx>, which: FloatBinOp, left: &ImmTy<'tcx>, right: &ImmTy<'tcx>, ) -> InterpResult<'tcx, Scalar> { match which { - FloatBinOp::Arith(which) => { - let res = this.binary_op(which, left, right)?; - Ok(res.to_scalar()) - } FloatBinOp::Cmp { gt, lt, eq, unord } => { let left = left.to_scalar().to_float::()?; let right = right.to_scalar().to_float::()?; @@ -323,7 +322,6 @@ fn bin_op_simd_float_first<'tcx, F: rustc_apfloat::Float>( assert_eq!(dest_len, right_len); let res0 = bin_op_float::( - this, which, &this.read_immediate(&this.project_index(&left, 0)?)?, &this.read_immediate(&this.project_index(&right, 0)?)?, @@ -358,7 +356,7 @@ fn bin_op_simd_float_all<'tcx, F: rustc_apfloat::Float>( let right = this.read_immediate(&this.project_index(&right, i)?)?; let dest = this.project_index(&dest, i)?; - let res = bin_op_float::(this, which, &left, &right)?; + let res = bin_op_float::(which, &left, &right)?; this.write_scalar(res, &dest)?; } @@ -367,11 +365,6 @@ fn bin_op_simd_float_all<'tcx, F: rustc_apfloat::Float>( #[derive(Copy, Clone)] enum FloatUnaryOp { - /// sqrt(x) - /// - /// - /// - Sqrt, /// Approximation of 1/x /// /// @@ -392,11 +385,6 @@ fn unary_op_f32<'tcx>( op: &ImmTy<'tcx>, ) -> InterpResult<'tcx, Scalar> { match which { - FloatUnaryOp::Sqrt => { - let op = op.to_scalar(); - // FIXME using host floats - Ok(Scalar::from_u32(f32::from_bits(op.to_u32()?).sqrt().to_bits())) - } FloatUnaryOp::Rcp => { let op = op.to_scalar().to_f32()?; let div = (Single::from_u128(1).value / op).value; diff --git a/src/tools/miri/src/shims/x86/sha.rs b/src/tools/miri/src/shims/x86/sha.rs new file mode 100644 index 00000000000..e9cc28be34c --- /dev/null +++ b/src/tools/miri/src/shims/x86/sha.rs @@ -0,0 +1,221 @@ +//! Implements sha256 SIMD instructions of x86 targets +//! +//! The functions that actually compute SHA256 were copied from [RustCrypto's sha256 module]. +//! +//! [RustCrypto's sha256 module]: https://github.com/RustCrypto/hashes/blob/6be8466247e936c415d8aafb848697f39894a386/sha2/src/sha256/soft.rs + +use rustc_span::Symbol; +use rustc_target::spec::abi::Abi; + +use crate::*; + +impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} +pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { + fn emulate_x86_sha_intrinsic( + &mut self, + link_name: Symbol, + abi: Abi, + args: &[OpTy<'tcx>], + dest: &MPlaceTy<'tcx>, + ) -> InterpResult<'tcx, EmulateItemResult> { + let this = self.eval_context_mut(); + this.expect_target_feature_for_intrinsic(link_name, "sha")?; + // Prefix should have already been checked. + let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.sha").unwrap(); + + fn read<'c>(this: &mut MiriInterpCx<'c>, reg: &MPlaceTy<'c>) -> InterpResult<'c, [u32; 4]> { + let mut res = [0; 4]; + // We reverse the order because x86 is little endian but the copied implementation uses + // big endian. + for (i, dst) in res.iter_mut().rev().enumerate() { + let projected = &this.project_index(reg, i.try_into().unwrap())?; + *dst = this.read_scalar(projected)?.to_u32()? + } + Ok(res) + } + + fn write<'c>( + this: &mut MiriInterpCx<'c>, + dest: &MPlaceTy<'c>, + val: [u32; 4], + ) -> InterpResult<'c, ()> { + // We reverse the order because x86 is little endian but the copied implementation uses + // big endian. + for (i, part) in val.into_iter().rev().enumerate() { + let projected = &this.project_index(dest, i.try_into().unwrap())?; + this.write_scalar(Scalar::from_u32(part), projected)?; + } + Ok(()) + } + + match unprefixed_name { + // Used to implement the _mm_sha256rnds2_epu32 function. + "256rnds2" => { + let [a, b, k] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + + let (a_reg, a_len) = this.operand_to_simd(a)?; + let (b_reg, b_len) = this.operand_to_simd(b)?; + let (k_reg, k_len) = this.operand_to_simd(k)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; + + assert_eq!(a_len, 4); + assert_eq!(b_len, 4); + assert_eq!(k_len, 4); + assert_eq!(dest_len, 4); + + let a = read(this, &a_reg)?; + let b = read(this, &b_reg)?; + let k = read(this, &k_reg)?; + + let result = sha256_digest_round_x2(a, b, k); + write(this, &dest, result)?; + } + // Used to implement the _mm_sha256msg1_epu32 function. + "256msg1" => { + let [a, b] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + + let (a_reg, a_len) = this.operand_to_simd(a)?; + let (b_reg, b_len) = this.operand_to_simd(b)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; + + assert_eq!(a_len, 4); + assert_eq!(b_len, 4); + assert_eq!(dest_len, 4); + + let a = read(this, &a_reg)?; + let b = read(this, &b_reg)?; + + let result = sha256msg1(a, b); + write(this, &dest, result)?; + } + // Used to implement the _mm_sha256msg2_epu32 function. + "256msg2" => { + let [a, b] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + + let (a_reg, a_len) = this.operand_to_simd(a)?; + let (b_reg, b_len) = this.operand_to_simd(b)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; + + assert_eq!(a_len, 4); + assert_eq!(b_len, 4); + assert_eq!(dest_len, 4); + + let a = read(this, &a_reg)?; + let b = read(this, &b_reg)?; + + let result = sha256msg2(a, b); + write(this, &dest, result)?; + } + _ => return Ok(EmulateItemResult::NotSupported), + } + Ok(EmulateItemResult::NeedsReturn) + } +} + +#[inline(always)] +fn shr(v: [u32; 4], o: u32) -> [u32; 4] { + [v[0] >> o, v[1] >> o, v[2] >> o, v[3] >> o] +} + +#[inline(always)] +fn shl(v: [u32; 4], o: u32) -> [u32; 4] { + [v[0] << o, v[1] << o, v[2] << o, v[3] << o] +} + +#[inline(always)] +fn or(a: [u32; 4], b: [u32; 4]) -> [u32; 4] { + [a[0] | b[0], a[1] | b[1], a[2] | b[2], a[3] | b[3]] +} + +#[inline(always)] +fn xor(a: [u32; 4], b: [u32; 4]) -> [u32; 4] { + [a[0] ^ b[0], a[1] ^ b[1], a[2] ^ b[2], a[3] ^ b[3]] +} + +#[inline(always)] +fn add(a: [u32; 4], b: [u32; 4]) -> [u32; 4] { + [ + a[0].wrapping_add(b[0]), + a[1].wrapping_add(b[1]), + a[2].wrapping_add(b[2]), + a[3].wrapping_add(b[3]), + ] +} + +fn sha256load(v2: [u32; 4], v3: [u32; 4]) -> [u32; 4] { + [v3[3], v2[0], v2[1], v2[2]] +} + +fn sha256_digest_round_x2(cdgh: [u32; 4], abef: [u32; 4], wk: [u32; 4]) -> [u32; 4] { + macro_rules! big_sigma0 { + ($a:expr) => { + ($a.rotate_right(2) ^ $a.rotate_right(13) ^ $a.rotate_right(22)) + }; + } + macro_rules! big_sigma1 { + ($a:expr) => { + ($a.rotate_right(6) ^ $a.rotate_right(11) ^ $a.rotate_right(25)) + }; + } + macro_rules! bool3ary_202 { + ($a:expr, $b:expr, $c:expr) => { + $c ^ ($a & ($b ^ $c)) + }; + } // Choose, MD5F, SHA1C + macro_rules! bool3ary_232 { + ($a:expr, $b:expr, $c:expr) => { + ($a & $b) ^ ($a & $c) ^ ($b & $c) + }; + } // Majority, SHA1M + + let [_, _, wk1, wk0] = wk; + let [a0, b0, e0, f0] = abef; + let [c0, d0, g0, h0] = cdgh; + + // a round + let x0 = + big_sigma1!(e0).wrapping_add(bool3ary_202!(e0, f0, g0)).wrapping_add(wk0).wrapping_add(h0); + let y0 = big_sigma0!(a0).wrapping_add(bool3ary_232!(a0, b0, c0)); + let (a1, b1, c1, d1, e1, f1, g1, h1) = + (x0.wrapping_add(y0), a0, b0, c0, x0.wrapping_add(d0), e0, f0, g0); + + // a round + let x1 = + big_sigma1!(e1).wrapping_add(bool3ary_202!(e1, f1, g1)).wrapping_add(wk1).wrapping_add(h1); + let y1 = big_sigma0!(a1).wrapping_add(bool3ary_232!(a1, b1, c1)); + let (a2, b2, _, _, e2, f2, _, _) = + (x1.wrapping_add(y1), a1, b1, c1, x1.wrapping_add(d1), e1, f1, g1); + + [a2, b2, e2, f2] +} + +fn sha256msg1(v0: [u32; 4], v1: [u32; 4]) -> [u32; 4] { + // sigma 0 on vectors + #[inline] + fn sigma0x4(x: [u32; 4]) -> [u32; 4] { + let t1 = or(shr(x, 7), shl(x, 25)); + let t2 = or(shr(x, 18), shl(x, 14)); + let t3 = shr(x, 3); + xor(xor(t1, t2), t3) + } + + add(v0, sigma0x4(sha256load(v0, v1))) +} + +fn sha256msg2(v4: [u32; 4], v3: [u32; 4]) -> [u32; 4] { + macro_rules! sigma1 { + ($a:expr) => { + $a.rotate_right(17) ^ $a.rotate_right(19) ^ ($a >> 10) + }; + } + + let [x3, x2, x1, x0] = v4; + let [w15, w14, _, _] = v3; + + let w16 = x0.wrapping_add(sigma1!(w14)); + let w17 = x1.wrapping_add(sigma1!(w15)); + let w18 = x2.wrapping_add(sigma1!(w16)); + let w19 = x3.wrapping_add(sigma1!(w17)); + + [w19, w18, w17, w16] +} diff --git a/src/tools/miri/src/shims/x86/sse.rs b/src/tools/miri/src/shims/x86/sse.rs index 32e8e8a66c1..07a4eaa85f3 100644 --- a/src/tools/miri/src/shims/x86/sse.rs +++ b/src/tools/miri/src/shims/x86/sse.rs @@ -1,5 +1,4 @@ use rustc_apfloat::ieee::Single; -use rustc_middle::mir; use rustc_span::Symbol; use rustc_target::spec::abi::Abi; @@ -29,18 +28,14 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // performed only on the first element, copying the remaining elements from the input // vector (for binary operations, from the left-hand side). match unprefixed_name { - // Used to implement _mm_{add,sub,mul,div,min,max}_ss functions. + // Used to implement _mm_{min,max}_ss functions. // Performs the operations on the first component of `left` and // `right` and copies the remaining components from `left`. - "add.ss" | "sub.ss" | "mul.ss" | "div.ss" | "min.ss" | "max.ss" => { + "min.ss" | "max.ss" => { let [left, right] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let which = match unprefixed_name { - "add.ss" => FloatBinOp::Arith(mir::BinOp::Add), - "sub.ss" => FloatBinOp::Arith(mir::BinOp::Sub), - "mul.ss" => FloatBinOp::Arith(mir::BinOp::Mul), - "div.ss" => FloatBinOp::Arith(mir::BinOp::Div), "min.ss" => FloatBinOp::Min, "max.ss" => FloatBinOp::Max, _ => unreachable!(), @@ -65,14 +60,13 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { bin_op_simd_float_all::(this, which, left, right, dest)?; } - // Used to implement _mm_{sqrt,rcp,rsqrt}_ss functions. + // Used to implement _mm_{rcp,rsqrt}_ss functions. // Performs the operations on the first component of `op` and // copies the remaining components from `op`. - "sqrt.ss" | "rcp.ss" | "rsqrt.ss" => { + "rcp.ss" | "rsqrt.ss" => { let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let which = match unprefixed_name { - "sqrt.ss" => FloatUnaryOp::Sqrt, "rcp.ss" => FloatUnaryOp::Rcp, "rsqrt.ss" => FloatUnaryOp::Rsqrt, _ => unreachable!(), @@ -82,11 +76,10 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } // Used to implement _mm_{sqrt,rcp,rsqrt}_ps functions. // Performs the operations on all components of `op`. - "sqrt.ps" | "rcp.ps" | "rsqrt.ps" => { + "rcp.ps" | "rsqrt.ps" => { let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let which = match unprefixed_name { - "sqrt.ps" => FloatUnaryOp::Sqrt, "rcp.ps" => FloatUnaryOp::Rcp, "rsqrt.ps" => FloatUnaryOp::Rsqrt, _ => unreachable!(), diff --git a/src/tools/miri/src/shims/x86/sse2.rs b/src/tools/miri/src/shims/x86/sse2.rs index 3efdd561d6c..163d74a6de4 100644 --- a/src/tools/miri/src/shims/x86/sse2.rs +++ b/src/tools/miri/src/shims/x86/sse2.rs @@ -227,46 +227,6 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { bin_op_simd_float_all::(this, which, left, right, dest)?; } - // Used to implement _mm_sqrt_sd functions. - // Performs the operations on the first component of `op` and - // copies the remaining components from `op`. - "sqrt.sd" => { - let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - - let (op, op_len) = this.operand_to_simd(op)?; - let (dest, dest_len) = this.mplace_to_simd(dest)?; - - assert_eq!(dest_len, op_len); - - let op0 = this.read_scalar(&this.project_index(&op, 0)?)?.to_u64()?; - // FIXME using host floats - let res0 = Scalar::from_u64(f64::from_bits(op0).sqrt().to_bits()); - this.write_scalar(res0, &this.project_index(&dest, 0)?)?; - - for i in 1..dest_len { - this.copy_op(&this.project_index(&op, i)?, &this.project_index(&dest, i)?)?; - } - } - // Used to implement _mm_sqrt_pd functions. - // Performs the operations on all components of `op`. - "sqrt.pd" => { - let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - - let (op, op_len) = this.operand_to_simd(op)?; - let (dest, dest_len) = this.mplace_to_simd(dest)?; - - assert_eq!(dest_len, op_len); - - for i in 0..dest_len { - let op = this.read_scalar(&this.project_index(&op, i)?)?.to_u64()?; - let dest = this.project_index(&dest, i)?; - - // FIXME using host floats - let res = Scalar::from_u64(f64::from_bits(op).sqrt().to_bits()); - - this.write_scalar(res, &dest)?; - } - } // Used to implement the _mm_cmp*_sd functions. // Performs a comparison operation on the first component of `left` // and `right`, returning 0 if false or `u64::MAX` if true. The remaining diff --git a/src/tools/miri/test_dependencies/Cargo.lock b/src/tools/miri/test_dependencies/Cargo.lock index e94bef52952..bbead878223 100644 --- a/src/tools/miri/test_dependencies/Cargo.lock +++ b/src/tools/miri/test_dependencies/Cargo.lock @@ -119,9 +119,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.155" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "linux-raw-sys" diff --git a/src/tools/miri/tests/fail-dep/tokio/sleep.rs b/src/tools/miri/tests/fail-dep/tokio/sleep.rs index d96d778e6ca..0fa5080d484 100644 --- a/src/tools/miri/tests/fail-dep/tokio/sleep.rs +++ b/src/tools/miri/tests/fail-dep/tokio/sleep.rs @@ -1,6 +1,6 @@ //@compile-flags: -Zmiri-permissive-provenance -Zmiri-backtrace=full //@only-target-x86_64-unknown-linux: support for tokio only on linux and x86 -//@error-in-other-file: returning ready events from epoll_wait is not yet implemented +//@error-in-other-file: timeout value can only be 0 //@normalize-stderr-test: " += note:.*\n" -> "" use tokio::time::{sleep, Duration, Instant}; diff --git a/src/tools/miri/tests/fail-dep/tokio/sleep.stderr b/src/tools/miri/tests/fail-dep/tokio/sleep.stderr index 6d19faab905..d5bf00fc175 100644 --- a/src/tools/miri/tests/fail-dep/tokio/sleep.stderr +++ b/src/tools/miri/tests/fail-dep/tokio/sleep.stderr @@ -1,4 +1,4 @@ -error: unsupported operation: returning ready events from epoll_wait is not yet implemented +error: unsupported operation: epoll_wait: timeout value can only be 0 --> CARGO_REGISTRY/.../epoll.rs:LL:CC | LL | / syscall!(epoll_wait( @@ -7,7 +7,7 @@ LL | | events.as_mut_ptr(), LL | | events.capacity() as i32, LL | | timeout, LL | | )) - | |__________^ returning ready events from epoll_wait is not yet implemented + | |__________^ epoll_wait: timeout value can only be 0 | = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support diff --git a/src/tools/miri/tests/fail/alloc/global_system_mixup.rs b/src/tools/miri/tests/fail/alloc/global_system_mixup.rs index 19c62913b4c..bbf069b7a2d 100644 --- a/src/tools/miri/tests/fail/alloc/global_system_mixup.rs +++ b/src/tools/miri/tests/fail/alloc/global_system_mixup.rs @@ -4,7 +4,9 @@ //@normalize-stderr-test: "using [A-Za-z]+ heap deallocation operation" -> "using PLATFORM heap deallocation operation" //@normalize-stderr-test: "\| +\^+" -> "| ^" -//@normalize-stderr-test: "libc::free\([^()]*\)|unsafe \{ HeapFree\([^}]*\};" -> "FREE();" +//@normalize-stderr-test: "unsafe \{ libc::free\([^()]*\) \}|unsafe \{ HeapFree\([^}]*\};" -> "FREE();" +//@normalize-stderr-test: "alloc::[A-Za-z]+::" -> "alloc::PLATFORM::" +//@normalize-stderr-test: "alloc/[A-Za-z]+.rs" -> "alloc/PLATFORM.rs" #![feature(allocator_api, slice_ptr_get)] @@ -13,7 +15,5 @@ use std::alloc::{Allocator, Global, Layout, System}; fn main() { let l = Layout::from_size_align(1, 1).unwrap(); let ptr = Global.allocate(l).unwrap().as_non_null_ptr(); - unsafe { - System.deallocate(ptr, l); - } + unsafe { System.deallocate(ptr, l) }; } diff --git a/src/tools/miri/tests/fail/alloc/global_system_mixup.stderr b/src/tools/miri/tests/fail/alloc/global_system_mixup.stderr index 7006b96ee1e..287a1f1a3e3 100644 --- a/src/tools/miri/tests/fail/alloc/global_system_mixup.stderr +++ b/src/tools/miri/tests/fail/alloc/global_system_mixup.stderr @@ -1,5 +1,5 @@ error: Undefined Behavior: deallocating ALLOC, which is Rust heap memory, using PLATFORM heap deallocation operation - --> RUSTLIB/std/src/sys/pal/PLATFORM/alloc.rs:LL:CC + --> RUSTLIB/std/src/sys/alloc/PLATFORM.rs:LL:CC | LL | FREE(); | ^ deallocating ALLOC, which is Rust heap memory, using PLATFORM heap deallocation operation @@ -7,12 +7,12 @@ LL | FREE(); = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: - = note: inside `std::sys::pal::PLATFORM::alloc::::dealloc` at RUSTLIB/std/src/sys/pal/PLATFORM/alloc.rs:LL:CC + = note: inside `std::sys::alloc::PLATFORM::::dealloc` at RUSTLIB/std/src/sys/alloc/PLATFORM.rs:LL:CC = note: inside `::deallocate` at RUSTLIB/std/src/alloc.rs:LL:CC note: inside `main` --> $DIR/global_system_mixup.rs:LL:CC | -LL | System.deallocate(ptr, l); +LL | unsafe { System.deallocate(ptr, l) }; | ^ note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/alloc/unsupported_big_alignment.rs b/src/tools/miri/tests/fail/alloc/unsupported_big_alignment.rs new file mode 100644 index 00000000000..08d84c461bf --- /dev/null +++ b/src/tools/miri/tests/fail/alloc/unsupported_big_alignment.rs @@ -0,0 +1,14 @@ +// Previously, attempting to allocate with an alignment greater than 2^29 would cause miri to ICE +// because rustc does not support alignments that large. +// https://github.com/rust-lang/miri/issues/3687 + +extern "Rust" { + fn __rust_alloc(size: usize, align: usize) -> *mut u8; +} + +fn main() { + unsafe { + __rust_alloc(1, 1 << 30); + //~^ERROR: exceeding rustc's maximum supported value + } +} diff --git a/src/tools/miri/tests/fail/alloc/unsupported_big_alignment.stderr b/src/tools/miri/tests/fail/alloc/unsupported_big_alignment.stderr new file mode 100644 index 00000000000..4c783b866c8 --- /dev/null +++ b/src/tools/miri/tests/fail/alloc/unsupported_big_alignment.stderr @@ -0,0 +1,14 @@ +error: unsupported operation: creating allocation with alignment ALIGN exceeding rustc's maximum supported value + --> $DIR/unsupported_big_alignment.rs:LL:CC + | +LL | __rust_alloc(1, 1 << 30); + | ^^^^^^^^^^^^^^^^^^^^^^^^ creating allocation with alignment ALIGN exceeding rustc's maximum supported value + | + = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support + = note: BACKTRACE: + = note: inside `main` at $DIR/unsupported_big_alignment.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/alloc/unsupported_non_power_two_alignment.rs b/src/tools/miri/tests/fail/alloc/unsupported_non_power_two_alignment.rs new file mode 100644 index 00000000000..a4ab8094bf4 --- /dev/null +++ b/src/tools/miri/tests/fail/alloc/unsupported_non_power_two_alignment.rs @@ -0,0 +1,11 @@ +// Test non-power-of-two alignment. +extern "Rust" { + fn __rust_alloc(size: usize, align: usize) -> *mut u8; +} + +fn main() { + unsafe { + __rust_alloc(1, 3); + //~^ERROR: creating allocation with non-power-of-two alignment + } +} diff --git a/src/tools/miri/tests/fail/alloc/unsupported_non_power_two_alignment.stderr b/src/tools/miri/tests/fail/alloc/unsupported_non_power_two_alignment.stderr new file mode 100644 index 00000000000..69a6c375f47 --- /dev/null +++ b/src/tools/miri/tests/fail/alloc/unsupported_non_power_two_alignment.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: creating allocation with non-power-of-two alignment ALIGN + --> $DIR/unsupported_non_power_two_alignment.rs:LL:CC + | +LL | __rust_alloc(1, 3); + | ^^^^^^^^^^^^^^^^^^ creating allocation with non-power-of-two alignment ALIGN + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/unsupported_non_power_two_alignment.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/both_borrows/aliasing_mut1.stack.stderr b/src/tools/miri/tests/fail/both_borrows/aliasing_mut1.stack.stderr index fe1f7060f1e..4f9e6222db2 100644 --- a/src/tools/miri/tests/fail/both_borrows/aliasing_mut1.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/aliasing_mut1.stack.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: not granting access to tag because that would remove [Unique for ] which is strongly protected because it is an argument of call ID +error: Undefined Behavior: not granting access to tag because that would remove [Unique for ] which is strongly protected --> $DIR/aliasing_mut1.rs:LL:CC | LL | pub fn safe(x: &mut i32, y: &mut i32) { - | ^ not granting access to tag because that would remove [Unique for ] which is strongly protected because it is an argument of call ID + | ^ not granting access to tag because that would remove [Unique for ] which is strongly protected | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information diff --git a/src/tools/miri/tests/fail/both_borrows/aliasing_mut2.stack.stderr b/src/tools/miri/tests/fail/both_borrows/aliasing_mut2.stack.stderr index c5bdfcb8fe4..54679d177da 100644 --- a/src/tools/miri/tests/fail/both_borrows/aliasing_mut2.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/aliasing_mut2.stack.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: not granting access to tag because that would remove [SharedReadOnly for ] which is strongly protected because it is an argument of call ID +error: Undefined Behavior: not granting access to tag because that would remove [SharedReadOnly for ] which is strongly protected --> $DIR/aliasing_mut2.rs:LL:CC | LL | pub fn safe(x: &i32, y: &mut i32) { - | ^ not granting access to tag because that would remove [SharedReadOnly for ] which is strongly protected because it is an argument of call ID + | ^ not granting access to tag because that would remove [SharedReadOnly for ] which is strongly protected | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information diff --git a/src/tools/miri/tests/fail/both_borrows/aliasing_mut4.stack.stderr b/src/tools/miri/tests/fail/both_borrows/aliasing_mut4.stack.stderr index 383eb086d1e..b3e97c92f1a 100644 --- a/src/tools/miri/tests/fail/both_borrows/aliasing_mut4.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/aliasing_mut4.stack.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: not granting access to tag because that would remove [SharedReadOnly for ] which is strongly protected because it is an argument of call ID +error: Undefined Behavior: not granting access to tag because that would remove [SharedReadOnly for ] which is strongly protected --> $DIR/aliasing_mut4.rs:LL:CC | LL | pub fn safe(x: &i32, y: &mut Cell) { - | ^ not granting access to tag because that would remove [SharedReadOnly for ] which is strongly protected because it is an argument of call ID + | ^ not granting access to tag because that would remove [SharedReadOnly for ] which is strongly protected | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information diff --git a/src/tools/miri/tests/fail/both_borrows/box_noalias_violation.stack.stderr b/src/tools/miri/tests/fail/both_borrows/box_noalias_violation.stack.stderr index 6e87d3ce06b..a9ea7a9e9c4 100644 --- a/src/tools/miri/tests/fail/both_borrows/box_noalias_violation.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/box_noalias_violation.stack.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: not granting access to tag because that would remove [Unique for ] which is weakly protected because it is an argument of call ID +error: Undefined Behavior: not granting access to tag because that would remove [Unique for ] which is weakly protected --> $DIR/box_noalias_violation.rs:LL:CC | LL | *y - | ^^ not granting access to tag because that would remove [Unique for ] which is weakly protected because it is an argument of call ID + | ^^ not granting access to tag because that would remove [Unique for ] which is weakly protected | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information diff --git a/src/tools/miri/tests/fail/both_borrows/illegal_write6.stack.stderr b/src/tools/miri/tests/fail/both_borrows/illegal_write6.stack.stderr index 159b6cc9a8e..b5484745c41 100644 --- a/src/tools/miri/tests/fail/both_borrows/illegal_write6.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/illegal_write6.stack.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: not granting access to tag because that would remove [Unique for ] which is strongly protected because it is an argument of call ID +error: Undefined Behavior: not granting access to tag because that would remove [Unique for ] which is strongly protected --> $DIR/illegal_write6.rs:LL:CC | LL | unsafe { *y = 2 }; - | ^^^^^^ not granting access to tag because that would remove [Unique for ] which is strongly protected because it is an argument of call ID + | ^^^^^^ not granting access to tag because that would remove [Unique for ] which is strongly protected | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information diff --git a/src/tools/miri/tests/fail/both_borrows/invalidate_against_protector2.stack.stderr b/src/tools/miri/tests/fail/both_borrows/invalidate_against_protector2.stack.stderr index 5d093aeae88..11edbc3270c 100644 --- a/src/tools/miri/tests/fail/both_borrows/invalidate_against_protector2.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/invalidate_against_protector2.stack.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: not granting access to tag because that would remove [SharedReadOnly for ] which is strongly protected because it is an argument of call ID +error: Undefined Behavior: not granting access to tag because that would remove [SharedReadOnly for ] which is strongly protected --> $DIR/invalidate_against_protector2.rs:LL:CC | LL | unsafe { *x = 0 }; - | ^^^^^^ not granting access to tag because that would remove [SharedReadOnly for ] which is strongly protected because it is an argument of call ID + | ^^^^^^ not granting access to tag because that would remove [SharedReadOnly for ] which is strongly protected | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information diff --git a/src/tools/miri/tests/fail/both_borrows/invalidate_against_protector3.stack.stderr b/src/tools/miri/tests/fail/both_borrows/invalidate_against_protector3.stack.stderr index 8426f56004b..c6666ceac2b 100644 --- a/src/tools/miri/tests/fail/both_borrows/invalidate_against_protector3.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/invalidate_against_protector3.stack.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: not granting access to tag because that would remove [SharedReadOnly for ] which is strongly protected because it is an argument of call ID +error: Undefined Behavior: not granting access to tag because that would remove [SharedReadOnly for ] which is strongly protected --> $DIR/invalidate_against_protector3.rs:LL:CC | LL | unsafe { *x = 0 }; - | ^^^^^^ not granting access to tag because that would remove [SharedReadOnly for ] which is strongly protected because it is an argument of call ID + | ^^^^^^ not granting access to tag because that would remove [SharedReadOnly for ] which is strongly protected | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information diff --git a/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.stack.stderr b/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.stack.stderr index c26c7f397b0..9f545e5687e 100644 --- a/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.stack.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: not granting access to tag because that would remove [Unique for ] which is strongly protected because it is an argument of call ID +error: Undefined Behavior: not granting access to tag because that would remove [Unique for ] which is strongly protected --> RUSTLIB/alloc/src/boxed.rs:LL:CC | LL | Box(unsafe { Unique::new_unchecked(raw) }, alloc) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not granting access to tag because that would remove [Unique for ] which is strongly protected because it is an argument of call ID + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not granting access to tag because that would remove [Unique for ] which is strongly protected | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information diff --git a/src/tools/miri/tests/fail/both_borrows/newtype_retagging.stack.stderr b/src/tools/miri/tests/fail/both_borrows/newtype_retagging.stack.stderr index ae54da70fe2..a4111f6f5cc 100644 --- a/src/tools/miri/tests/fail/both_borrows/newtype_retagging.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/newtype_retagging.stack.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: not granting access to tag because that would remove [Unique for ] which is strongly protected because it is an argument of call ID +error: Undefined Behavior: not granting access to tag because that would remove [Unique for ] which is strongly protected --> RUSTLIB/alloc/src/boxed.rs:LL:CC | LL | Box(unsafe { Unique::new_unchecked(raw) }, alloc) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not granting access to tag because that would remove [Unique for ] which is strongly protected because it is an argument of call ID + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not granting access to tag because that would remove [Unique for ] which is strongly protected | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information diff --git a/src/tools/miri/tests/fail/both_borrows/zero-sized-protected.rs b/src/tools/miri/tests/fail/both_borrows/zero-sized-protected.rs new file mode 100644 index 00000000000..aed5cb11258 --- /dev/null +++ b/src/tools/miri/tests/fail/both_borrows/zero-sized-protected.rs @@ -0,0 +1,19 @@ +//@revisions: stack tree +//@[tree]compile-flags: -Zmiri-tree-borrows +//@[tree]error-in-other-file: /deallocation .* is forbidden/ +use std::alloc::{alloc, dealloc, Layout}; + +// `x` is strongly protected but covers zero bytes. +// Let's see if deallocating the allocation x points to is UB: +// in TB, it is UB, but in SB it is not. +fn test(_x: &mut (), ptr: *mut u8, l: Layout) { + unsafe { dealloc(ptr, l) }; +} + +fn main() { + let l = Layout::from_size_align(1, 1).unwrap(); + let ptr = unsafe { alloc(l) }; + unsafe { test(&mut *ptr.cast::<()>(), ptr, l) }; + // In SB the test would pass if it weren't for this line. + unsafe { std::hint::unreachable_unchecked() }; //~[stack] ERROR: unreachable +} diff --git a/src/tools/miri/tests/fail/both_borrows/zero-sized-protected.stack.stderr b/src/tools/miri/tests/fail/both_borrows/zero-sized-protected.stack.stderr new file mode 100644 index 00000000000..672682ff294 --- /dev/null +++ b/src/tools/miri/tests/fail/both_borrows/zero-sized-protected.stack.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: entering unreachable code + --> $DIR/zero-sized-protected.rs:LL:CC + | +LL | unsafe { std::hint::unreachable_unchecked() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ entering unreachable code + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/zero-sized-protected.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/both_borrows/zero-sized-protected.tree.stderr b/src/tools/miri/tests/fail/both_borrows/zero-sized-protected.tree.stderr new file mode 100644 index 00000000000..ef981038e55 --- /dev/null +++ b/src/tools/miri/tests/fail/both_borrows/zero-sized-protected.tree.stderr @@ -0,0 +1,36 @@ +error: Undefined Behavior: deallocation through (root of the allocation) at ALLOC[0x0] is forbidden + --> RUSTLIB/alloc/src/alloc.rs:LL:CC + | +LL | unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ deallocation through (root of the allocation) at ALLOC[0x0] is forbidden + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental + = help: the allocation of the accessed tag (root of the allocation) also contains the strongly protected tag + = help: the strongly protected tag disallows deallocations +help: the accessed tag was created here + --> $DIR/zero-sized-protected.rs:LL:CC + | +LL | let ptr = unsafe { alloc(l) }; + | ^^^^^^^^ +help: the strongly protected tag was created here, in the initial state Reserved + --> $DIR/zero-sized-protected.rs:LL:CC + | +LL | fn test(_x: &mut (), ptr: *mut u8, l: Layout) { + | ^^ + = note: BACKTRACE (of the first span): + = note: inside `std::alloc::dealloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC +note: inside `test` + --> $DIR/zero-sized-protected.rs:LL:CC + | +LL | unsafe { dealloc(ptr, l) }; + | ^^^^^^^^^^^^^^^ +note: inside `main` + --> $DIR/zero-sized-protected.rs:LL:CC + | +LL | unsafe { test(&mut *ptr.cast::<()>(), ptr, l) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_to_raw_pointer.rs b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_to_raw_pointer.rs index 023bce1616b..3e20b8da622 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_to_raw_pointer.rs +++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_to_raw_pointer.rs @@ -1,4 +1,3 @@ -#![feature(raw_ref_op)] #![feature(strict_provenance)] use std::ptr; diff --git a/src/tools/miri/tests/fail/data_race/alloc_read_race.rs b/src/tools/miri/tests/fail/data_race/alloc_read_race.rs index c85c0ebe244..312b7ba05d3 100644 --- a/src/tools/miri/tests/fail/data_race/alloc_read_race.rs +++ b/src/tools/miri/tests/fail/data_race/alloc_read_race.rs @@ -1,7 +1,6 @@ //@compile-flags: -Zmiri-disable-weak-memory-emulation -Zmiri-preemption-rate=0 -Zmiri-disable-stacked-borrows // Avoid accidental synchronization via address reuse inside `thread::spawn`. //@compile-flags: -Zmiri-address-reuse-cross-thread-rate=0 -#![feature(new_uninit)] use std::mem::MaybeUninit; use std::ptr::null_mut; diff --git a/src/tools/miri/tests/fail/data_race/alloc_write_race.rs b/src/tools/miri/tests/fail/data_race/alloc_write_race.rs index 9e2a430dd94..f1f308b37e7 100644 --- a/src/tools/miri/tests/fail/data_race/alloc_write_race.rs +++ b/src/tools/miri/tests/fail/data_race/alloc_write_race.rs @@ -1,7 +1,6 @@ //@compile-flags: -Zmiri-disable-weak-memory-emulation -Zmiri-preemption-rate=0 -Zmiri-disable-stacked-borrows // Avoid accidental synchronization via address reuse inside `thread::spawn`. //@compile-flags: -Zmiri-address-reuse-cross-thread-rate=0 -#![feature(new_uninit)] use std::ptr::null_mut; use std::sync::atomic::{AtomicPtr, Ordering}; diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr index e0d1bed6332..609426bb289 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: not granting access to tag because that would remove [Unique for ] which is strongly protected because it is an argument of call ID +error: Undefined Behavior: not granting access to tag because that would remove [Unique for ] which is strongly protected --> $DIR/arg_inplace_mutate.rs:LL:CC | LL | unsafe { ptr.write(S(0)) }; - | ^^^^^^^^^^^^^^^ not granting access to tag because that would remove [Unique for ] which is strongly protected because it is an argument of call ID + | ^^^^^^^^^^^^^^^ not granting access to tag because that would remove [Unique for ] which is strongly protected | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr index 09c9a777eca..68b7c0307c8 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: not granting access to tag because that would remove [Unique for ] which is strongly protected because it is an argument of call ID +error: Undefined Behavior: not granting access to tag because that would remove [Unique for ] which is strongly protected --> $DIR/arg_inplace_observe_during.rs:LL:CC | LL | unsafe { ptr.read() }; - | ^^^^^^^^^^ not granting access to tag because that would remove [Unique for ] which is strongly protected because it is an argument of call ID + | ^^^^^^^^^^ not granting access to tag because that would remove [Unique for ] which is strongly protected | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind1.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind1.stderr index 42beed4ecde..a11a2b95689 100644 --- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind1.stderr +++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind1.stderr @@ -1,7 +1,7 @@ thread 'main' panicked at $DIR/exported_symbol_bad_unwind1.rs:LL:CC: explicit panic note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect error: Undefined Behavior: unwinding past a stack frame that does not allow unwinding --> $DIR/exported_symbol_bad_unwind1.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr index 112a9687837..12425cc4892 100644 --- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr +++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr @@ -1,7 +1,7 @@ thread 'main' panicked at $DIR/exported_symbol_bad_unwind2.rs:LL:CC: explicit panic note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC: panic in a function that cannot unwind stack backtrace: diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr index 112a9687837..12425cc4892 100644 --- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr +++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr @@ -1,7 +1,7 @@ thread 'main' panicked at $DIR/exported_symbol_bad_unwind2.rs:LL:CC: explicit panic note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC: panic in a function that cannot unwind stack backtrace: diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.extern_block.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.extern_block.stderr index bc3e4858716..f9e299bf5d2 100644 --- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.extern_block.stderr +++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.extern_block.stderr @@ -1,7 +1,7 @@ thread 'main' panicked at $DIR/exported_symbol_bad_unwind2.rs:LL:CC: explicit panic note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect error: Undefined Behavior: unwinding past a stack frame that does not allow unwinding --> $DIR/exported_symbol_bad_unwind2.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.none.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.none.stderr similarity index 82% rename from src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.none.stderr rename to src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.none.stderr index eb215a2d2e8..e8b766d0b0e 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.none.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.none.stderr @@ -1,5 +1,5 @@ error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory - --> $DIR/return_pointer_aliasing.rs:LL:CC + --> $DIR/return_pointer_aliasing_read.rs:LL:CC | LL | unsafe { ptr.read() }; | ^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory @@ -7,9 +7,9 @@ LL | unsafe { ptr.read() }; = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: - = note: inside `myfun` at $DIR/return_pointer_aliasing.rs:LL:CC + = note: inside `myfun` at $DIR/return_pointer_aliasing_read.rs:LL:CC note: inside `main` - --> $DIR/return_pointer_aliasing.rs:LL:CC + --> $DIR/return_pointer_aliasing_read.rs:LL:CC | LL | Call(*ptr = myfun(ptr), ReturnTo(after_call), UnwindContinue()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.rs similarity index 97% rename from src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs rename to src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.rs index c8e0782eff2..a6e0134bd17 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.rs @@ -1,7 +1,6 @@ //@revisions: stack tree none //@[tree]compile-flags: -Zmiri-tree-borrows //@[none]compile-flags: -Zmiri-disable-stacked-borrows -#![feature(raw_ref_op)] #![feature(core_intrinsics)] #![feature(custom_mir)] diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.stack.stderr similarity index 81% rename from src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr rename to src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.stack.stderr index 01357f430fc..941470e9295 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.stack.stderr @@ -1,13 +1,13 @@ -error: Undefined Behavior: not granting access to tag because that would remove [Unique for ] which is strongly protected because it is an argument of call ID - --> $DIR/return_pointer_aliasing.rs:LL:CC +error: Undefined Behavior: not granting access to tag because that would remove [Unique for ] which is strongly protected + --> $DIR/return_pointer_aliasing_read.rs:LL:CC | LL | unsafe { ptr.read() }; - | ^^^^^^^^^^ not granting access to tag because that would remove [Unique for ] which is strongly protected because it is an argument of call ID + | ^^^^^^^^^^ not granting access to tag because that would remove [Unique for ] which is strongly protected | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information help: was created by a SharedReadWrite retag at offsets [0x0..0x4] - --> $DIR/return_pointer_aliasing.rs:LL:CC + --> $DIR/return_pointer_aliasing_read.rs:LL:CC | LL | / mir! { LL | | { @@ -18,14 +18,14 @@ LL | | } LL | | } | |_____^ help: is this argument - --> $DIR/return_pointer_aliasing.rs:LL:CC + --> $DIR/return_pointer_aliasing_read.rs:LL:CC | LL | unsafe { ptr.read() }; | ^^^^^^^^^^^^^^^^^^^^^ = note: BACKTRACE (of the first span): - = note: inside `myfun` at $DIR/return_pointer_aliasing.rs:LL:CC + = note: inside `myfun` at $DIR/return_pointer_aliasing_read.rs:LL:CC note: inside `main` - --> $DIR/return_pointer_aliasing.rs:LL:CC + --> $DIR/return_pointer_aliasing_read.rs:LL:CC | LL | Call(*ptr = myfun(ptr), ReturnTo(after_call), UnwindContinue()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.tree.stderr similarity index 85% rename from src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr rename to src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.tree.stderr index bbedba5a7dd..715ee330619 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.tree.stderr @@ -1,5 +1,5 @@ error: Undefined Behavior: read access through (root of the allocation) at ALLOC[0x0] is forbidden - --> $DIR/return_pointer_aliasing.rs:LL:CC + --> $DIR/return_pointer_aliasing_read.rs:LL:CC | LL | unsafe { ptr.read() }; | ^^^^^^^^^^ read access through (root of the allocation) at ALLOC[0x0] is forbidden @@ -9,7 +9,7 @@ LL | unsafe { ptr.read() }; = help: this foreign read access would cause the protected tag (currently Active) to become Disabled = help: protected tags must never be Disabled help: the accessed tag was created here - --> $DIR/return_pointer_aliasing.rs:LL:CC + --> $DIR/return_pointer_aliasing_read.rs:LL:CC | LL | / mir! { LL | | { @@ -20,20 +20,20 @@ LL | | } LL | | } | |_____^ help: the protected tag was created here, in the initial state Reserved - --> $DIR/return_pointer_aliasing.rs:LL:CC + --> $DIR/return_pointer_aliasing_read.rs:LL:CC | LL | unsafe { ptr.read() }; | ^^^^^^^^^^^^^^^^^^^^^ help: the protected tag later transitioned to Active due to a child write access at offsets [0x0..0x4] - --> $DIR/return_pointer_aliasing.rs:LL:CC + --> $DIR/return_pointer_aliasing_read.rs:LL:CC | LL | unsafe { ptr.read() }; | ^^^^^^^^^^^^^^^^^^^^^ = help: this transition corresponds to the first write to a 2-phase borrowed mutable reference = note: BACKTRACE (of the first span): - = note: inside `myfun` at $DIR/return_pointer_aliasing.rs:LL:CC + = note: inside `myfun` at $DIR/return_pointer_aliasing_read.rs:LL:CC note: inside `main` - --> $DIR/return_pointer_aliasing.rs:LL:CC + --> $DIR/return_pointer_aliasing_read.rs:LL:CC | LL | Call(*ptr = myfun(ptr), ReturnTo(after_call), UnwindContinue()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.rs b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.rs similarity index 70% rename from src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.rs rename to src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.rs index 7db641538ce..6155e925c4b 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.rs +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.rs @@ -1,7 +1,6 @@ -// This does need an aliasing model. +// This does need an aliasing model and protectors. //@revisions: stack tree //@[tree]compile-flags: -Zmiri-tree-borrows -#![feature(raw_ref_op)] #![feature(core_intrinsics)] #![feature(custom_mir)] @@ -14,8 +13,8 @@ pub fn main() { let _x = 0; let ptr = &raw mut _x; // We arrange for `myfun` to have a pointer that aliases - // its return place. Even just reading from that pointer is UB. - Call(_x = myfun(ptr), ReturnTo(after_call), UnwindContinue()) + // its return place. Writing to that pointer is UB. + Call(*ptr = myfun(ptr), ReturnTo(after_call), UnwindContinue()) } after_call = { @@ -27,7 +26,7 @@ pub fn main() { fn myfun(ptr: *mut i32) -> i32 { // This overwrites the return place, which shouldn't be possible through another pointer. unsafe { ptr.write(0) }; - //~[stack]^ ERROR: tag does not exist in the borrow stack + //~[stack]^ ERROR: strongly protected //~[tree]| ERROR: /write access .* forbidden/ 13 } diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stack.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.stack.stderr similarity index 56% rename from src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stack.stderr rename to src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.stack.stderr index 04040827b0f..51cb270dd2e 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stack.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.stack.stderr @@ -1,16 +1,13 @@ -error: Undefined Behavior: attempting a write access using at ALLOC[0x0], but that tag does not exist in the borrow stack for this location - --> $DIR/return_pointer_aliasing2.rs:LL:CC +error: Undefined Behavior: not granting access to tag because that would remove [Unique for ] which is strongly protected + --> $DIR/return_pointer_aliasing_write.rs:LL:CC | LL | unsafe { ptr.write(0) }; - | ^^^^^^^^^^^^ - | | - | attempting a write access using at ALLOC[0x0], but that tag does not exist in the borrow stack for this location - | this error occurs as part of an access at ALLOC[0x0..0x4] + | ^^^^^^^^^^^^ not granting access to tag because that would remove [Unique for ] which is strongly protected | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information help: was created by a SharedReadWrite retag at offsets [0x0..0x4] - --> $DIR/return_pointer_aliasing2.rs:LL:CC + --> $DIR/return_pointer_aliasing_write.rs:LL:CC | LL | / mir! { LL | | { @@ -20,18 +17,18 @@ LL | | let ptr = &raw mut _x; LL | | } LL | | } | |_____^ -help: was later invalidated at offsets [0x0..0x4] by a Unique in-place function argument/return passing protection - --> $DIR/return_pointer_aliasing2.rs:LL:CC +help: is this argument + --> $DIR/return_pointer_aliasing_write.rs:LL:CC | LL | unsafe { ptr.write(0) }; | ^^^^^^^^^^^^^^^^^^^^^^^ = note: BACKTRACE (of the first span): - = note: inside `myfun` at $DIR/return_pointer_aliasing2.rs:LL:CC + = note: inside `myfun` at $DIR/return_pointer_aliasing_write.rs:LL:CC note: inside `main` - --> $DIR/return_pointer_aliasing2.rs:LL:CC + --> $DIR/return_pointer_aliasing_write.rs:LL:CC | -LL | Call(_x = myfun(ptr), ReturnTo(after_call), UnwindContinue()) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | Call(*ptr = myfun(ptr), ReturnTo(after_call), UnwindContinue()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.tree.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.tree.stderr similarity index 81% rename from src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.tree.stderr rename to src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.tree.stderr index 146bcfc7c47..66ca1027edc 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.tree.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.tree.stderr @@ -1,5 +1,5 @@ error: Undefined Behavior: write access through (root of the allocation) at ALLOC[0x0] is forbidden - --> $DIR/return_pointer_aliasing2.rs:LL:CC + --> $DIR/return_pointer_aliasing_write.rs:LL:CC | LL | unsafe { ptr.write(0) }; | ^^^^^^^^^^^^ write access through (root of the allocation) at ALLOC[0x0] is forbidden @@ -9,7 +9,7 @@ LL | unsafe { ptr.write(0) }; = help: this foreign write access would cause the protected tag (currently Active) to become Disabled = help: protected tags must never be Disabled help: the accessed tag was created here - --> $DIR/return_pointer_aliasing2.rs:LL:CC + --> $DIR/return_pointer_aliasing_write.rs:LL:CC | LL | / mir! { LL | | { @@ -20,23 +20,23 @@ LL | | } LL | | } | |_____^ help: the protected tag was created here, in the initial state Reserved - --> $DIR/return_pointer_aliasing2.rs:LL:CC + --> $DIR/return_pointer_aliasing_write.rs:LL:CC | LL | unsafe { ptr.write(0) }; | ^^^^^^^^^^^^^^^^^^^^^^^ help: the protected tag later transitioned to Active due to a child write access at offsets [0x0..0x4] - --> $DIR/return_pointer_aliasing2.rs:LL:CC + --> $DIR/return_pointer_aliasing_write.rs:LL:CC | LL | unsafe { ptr.write(0) }; | ^^^^^^^^^^^^^^^^^^^^^^^ = help: this transition corresponds to the first write to a 2-phase borrowed mutable reference = note: BACKTRACE (of the first span): - = note: inside `myfun` at $DIR/return_pointer_aliasing2.rs:LL:CC + = note: inside `myfun` at $DIR/return_pointer_aliasing_write.rs:LL:CC note: inside `main` - --> $DIR/return_pointer_aliasing2.rs:LL:CC + --> $DIR/return_pointer_aliasing_write.rs:LL:CC | -LL | Call(_x = myfun(ptr), ReturnTo(after_call), UnwindContinue()) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | Call(*ptr = myfun(ptr), ReturnTo(after_call), UnwindContinue()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.rs b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.rs new file mode 100644 index 00000000000..37ee7ae1b0d --- /dev/null +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.rs @@ -0,0 +1,38 @@ +// This does need an aliasing model and protectors. +//@revisions: stack tree +//@[tree]compile-flags: -Zmiri-tree-borrows +#![feature(core_intrinsics)] +#![feature(custom_mir)] +#![feature(explicit_tail_calls)] +#![allow(incomplete_features)] + +use std::intrinsics::mir::*; + +#[custom_mir(dialect = "runtime", phase = "optimized")] +pub fn main() { + mir! { + { + let _x = 0; + let ptr = &raw mut _x; + // We arrange for `myfun` to have a pointer that aliases + // its return place. Writing to that pointer is UB. + Call(*ptr = myfun(ptr), ReturnTo(after_call), UnwindContinue()) + } + + after_call = { + Return() + } + } +} + +fn myfun(ptr: *mut i32) -> i32 { + become myfun2(ptr) +} + +fn myfun2(ptr: *mut i32) -> i32 { + // This overwrites the return place, which shouldn't be possible through another pointer. + unsafe { ptr.write(0) }; + //~[stack]^ ERROR: strongly protected + //~[tree]| ERROR: /write access .* forbidden/ + 13 +} diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.stack.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.stack.stderr new file mode 100644 index 00000000000..7e527a440d1 --- /dev/null +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.stack.stderr @@ -0,0 +1,37 @@ +error: Undefined Behavior: not granting access to tag because that would remove [Unique for ] which is strongly protected + --> $DIR/return_pointer_aliasing_write_tail_call.rs:LL:CC + | +LL | unsafe { ptr.write(0) }; + | ^^^^^^^^^^^^ not granting access to tag because that would remove [Unique for ] which is strongly protected + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental + = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information +help: was created by a SharedReadWrite retag at offsets [0x0..0x4] + --> $DIR/return_pointer_aliasing_write_tail_call.rs:LL:CC + | +LL | / mir! { +LL | | { +LL | | let _x = 0; +LL | | let ptr = &raw mut _x; +... | +LL | | } +LL | | } + | |_____^ +help: is this argument + --> $DIR/return_pointer_aliasing_write_tail_call.rs:LL:CC + | +LL | unsafe { ptr.write(0) }; + | ^^^^^^^^^^^^^^^^^^^^^^^ + = note: BACKTRACE (of the first span): + = note: inside `myfun2` at $DIR/return_pointer_aliasing_write_tail_call.rs:LL:CC +note: inside `main` + --> $DIR/return_pointer_aliasing_write_tail_call.rs:LL:CC + | +LL | Call(*ptr = myfun(ptr), ReturnTo(after_call), UnwindContinue()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.tree.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.tree.stderr new file mode 100644 index 00000000000..b1f2cab031e --- /dev/null +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.tree.stderr @@ -0,0 +1,45 @@ +error: Undefined Behavior: write access through (root of the allocation) at ALLOC[0x0] is forbidden + --> $DIR/return_pointer_aliasing_write_tail_call.rs:LL:CC + | +LL | unsafe { ptr.write(0) }; + | ^^^^^^^^^^^^ write access through (root of the allocation) at ALLOC[0x0] is forbidden + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental + = help: the accessed tag (root of the allocation) is foreign to the protected tag (i.e., it is not a child) + = help: this foreign write access would cause the protected tag (currently Active) to become Disabled + = help: protected tags must never be Disabled +help: the accessed tag was created here + --> $DIR/return_pointer_aliasing_write_tail_call.rs:LL:CC + | +LL | / mir! { +LL | | { +LL | | let _x = 0; +LL | | let ptr = &raw mut _x; +... | +LL | | } +LL | | } + | |_____^ +help: the protected tag was created here, in the initial state Reserved + --> $DIR/return_pointer_aliasing_write_tail_call.rs:LL:CC + | +LL | unsafe { ptr.write(0) }; + | ^^^^^^^^^^^^^^^^^^^^^^^ +help: the protected tag later transitioned to Active due to a child write access at offsets [0x0..0x4] + --> $DIR/return_pointer_aliasing_write_tail_call.rs:LL:CC + | +LL | unsafe { ptr.write(0) }; + | ^^^^^^^^^^^^^^^^^^^^^^^ + = help: this transition corresponds to the first write to a 2-phase borrowed mutable reference + = note: BACKTRACE (of the first span): + = note: inside `myfun2` at $DIR/return_pointer_aliasing_write_tail_call.rs:LL:CC +note: inside `main` + --> $DIR/return_pointer_aliasing_write_tail_call.rs:LL:CC + | +LL | Call(*ptr = myfun(ptr), ReturnTo(after_call), UnwindContinue()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.rs b/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.rs index 244acd8f2be..698a893f897 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.rs +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.rs @@ -1,6 +1,5 @@ // Doesn't need an aliasing model. //@compile-flags: -Zmiri-disable-stacked-borrows -#![feature(raw_ref_op)] #![feature(core_intrinsics)] #![feature(custom_mir)] diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr index a2fa4c1d590..83efc9974e8 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr @@ -1,7 +1,7 @@ thread 'main' panicked at $DIR/return_pointer_on_unwind.rs:LL:CC: explicit panic note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory --> $DIR/return_pointer_on_unwind.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/intrinsics/intrinsic_target_feature.rs b/src/tools/miri/tests/fail/intrinsics/intrinsic_target_feature.rs index 9263ad381d1..860798f2ab1 100644 --- a/src/tools/miri/tests/fail/intrinsics/intrinsic_target_feature.rs +++ b/src/tools/miri/tests/fail/intrinsics/intrinsic_target_feature.rs @@ -24,7 +24,7 @@ fn main() { unsafe { // Pass, since SSE is enabled - addss(_mm_setzero_ps(), _mm_setzero_ps()); + minss(_mm_setzero_ps(), _mm_setzero_ps()); // Fail, since SSE4.1 is not enabled dpps(_mm_setzero_ps(), _mm_setzero_ps(), 0); @@ -34,8 +34,8 @@ fn main() { #[allow(improper_ctypes)] extern "C" { - #[link_name = "llvm.x86.sse.add.ss"] - fn addss(a: __m128, b: __m128) -> __m128; + #[link_name = "llvm.x86.sse.min.ss"] + fn minss(a: __m128, b: __m128) -> __m128; #[link_name = "llvm.x86.sse41.dpps"] fn dpps(a: __m128, b: __m128, imm8: u8) -> __m128; diff --git a/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr b/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr index 8dd76edafea..67fd60e572e 100644 --- a/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr +++ b/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr @@ -1,7 +1,7 @@ thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC: aborted execution: attempted to instantiate uninhabited type `!` note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect thread caused non-unwinding panic. aborting. error: abnormal termination: the program aborted execution --> RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC diff --git a/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr b/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr index 55f66a275b6..f89a1fc4bbb 100644 --- a/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr +++ b/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr @@ -1,7 +1,7 @@ thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC: aborted execution: attempted to zero-initialize type `fn()`, which is invalid note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect thread caused non-unwinding panic. aborting. error: abnormal termination: the program aborted execution --> RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC diff --git a/src/tools/miri/tests/fail/panic/bad_unwind.stderr b/src/tools/miri/tests/fail/panic/bad_unwind.stderr index 230e8337c7c..c08fe5153b1 100644 --- a/src/tools/miri/tests/fail/panic/bad_unwind.stderr +++ b/src/tools/miri/tests/fail/panic/bad_unwind.stderr @@ -1,7 +1,7 @@ thread 'main' panicked at $DIR/bad_unwind.rs:LL:CC: explicit panic note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect error: Undefined Behavior: unwinding past a stack frame that does not allow unwinding --> $DIR/bad_unwind.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/panic/double_panic.stderr b/src/tools/miri/tests/fail/panic/double_panic.stderr index 5829c1897bb..0395fe418d9 100644 --- a/src/tools/miri/tests/fail/panic/double_panic.stderr +++ b/src/tools/miri/tests/fail/panic/double_panic.stderr @@ -1,7 +1,7 @@ thread 'main' panicked at $DIR/double_panic.rs:LL:CC: first note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect thread 'main' panicked at $DIR/double_panic.rs:LL:CC: second stack backtrace: diff --git a/src/tools/miri/tests/fail/panic/panic_abort1.stderr b/src/tools/miri/tests/fail/panic/panic_abort1.stderr index d4abf19cd1e..6c7cac23bec 100644 --- a/src/tools/miri/tests/fail/panic/panic_abort1.stderr +++ b/src/tools/miri/tests/fail/panic/panic_abort1.stderr @@ -1,7 +1,7 @@ thread 'main' panicked at $DIR/panic_abort1.rs:LL:CC: panicking from libstd note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect error: abnormal termination: the program aborted execution --> RUSTLIB/panic_abort/src/lib.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/panic/panic_abort2.stderr b/src/tools/miri/tests/fail/panic/panic_abort2.stderr index 507f17abf4e..1eda5449d1b 100644 --- a/src/tools/miri/tests/fail/panic/panic_abort2.stderr +++ b/src/tools/miri/tests/fail/panic/panic_abort2.stderr @@ -1,7 +1,7 @@ thread 'main' panicked at $DIR/panic_abort2.rs:LL:CC: 42-panicking from libstd note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect error: abnormal termination: the program aborted execution --> RUSTLIB/panic_abort/src/lib.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/panic/panic_abort3.stderr b/src/tools/miri/tests/fail/panic/panic_abort3.stderr index a5d8b4d2eeb..5c7c5e17bee 100644 --- a/src/tools/miri/tests/fail/panic/panic_abort3.stderr +++ b/src/tools/miri/tests/fail/panic/panic_abort3.stderr @@ -1,7 +1,7 @@ thread 'main' panicked at $DIR/panic_abort3.rs:LL:CC: panicking from libcore note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect error: abnormal termination: the program aborted execution --> RUSTLIB/panic_abort/src/lib.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/panic/panic_abort4.stderr b/src/tools/miri/tests/fail/panic/panic_abort4.stderr index 62fbbf942cb..c8104f570f6 100644 --- a/src/tools/miri/tests/fail/panic/panic_abort4.stderr +++ b/src/tools/miri/tests/fail/panic/panic_abort4.stderr @@ -1,7 +1,7 @@ thread 'main' panicked at $DIR/panic_abort4.rs:LL:CC: 42-panicking from libcore note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect error: abnormal termination: the program aborted execution --> RUSTLIB/panic_abort/src/lib.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector1.stderr b/src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector1.stderr index 2cc714f935a..2a8d4f3aea0 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector1.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector1.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: deallocating while item [Unique for ] is strongly protected by call ID +error: Undefined Behavior: deallocating while item [Unique for ] is strongly protected --> RUSTLIB/alloc/src/alloc.rs:LL:CC | LL | unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ deallocating while item [Unique for ] is strongly protected by call ID + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ deallocating while item [Unique for ] is strongly protected | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information diff --git a/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_protector.stderr b/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_protector.stderr index 627c790f843..5147bcd458c 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_protector.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_protector.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: not granting access to tag because that would remove [Unique for ] which is strongly protected because it is an argument of call ID +error: Undefined Behavior: not granting access to tag because that would remove [Unique for ] which is strongly protected --> $DIR/drop_in_place_protector.rs:LL:CC | LL | let _val = *P; - | ^^ not granting access to tag because that would remove [Unique for ] which is strongly protected because it is an argument of call ID + | ^^ not granting access to tag because that would remove [Unique for ] which is strongly protected | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information diff --git a/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector1.stderr b/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector1.stderr index 22a0b42cfd8..96cdce5a778 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector1.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector1.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: not granting access to tag because that would remove [Unique for ] which is strongly protected because it is an argument of call ID +error: Undefined Behavior: not granting access to tag because that would remove [Unique for ] which is strongly protected --> $DIR/invalidate_against_protector1.rs:LL:CC | LL | let _val = unsafe { *x }; - | ^^ not granting access to tag because that would remove [Unique for ] which is strongly protected because it is an argument of call ID + | ^^ not granting access to tag because that would remove [Unique for ] which is strongly protected | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information diff --git a/src/tools/miri/tests/fail/terminate-terminator.stderr b/src/tools/miri/tests/fail/terminate-terminator.stderr index a5fa0b3e07a..6384689c563 100644 --- a/src/tools/miri/tests/fail/terminate-terminator.stderr +++ b/src/tools/miri/tests/fail/terminate-terminator.stderr @@ -3,7 +3,7 @@ warning: You have explicitly enabled MIR optimizations, overriding Miri's defaul thread 'main' panicked at $DIR/terminate-terminator.rs:LL:CC: explicit panic note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC: panic in a function that cannot unwind stack backtrace: diff --git a/src/tools/miri/tests/fail/tree_borrows/reserved/cell-protected-write.stderr b/src/tools/miri/tests/fail/tree_borrows/reserved/cell-protected-write.stderr index ce9a5b7f158..133a50938f2 100644 --- a/src/tools/miri/tests/fail/tree_borrows/reserved/cell-protected-write.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/reserved/cell-protected-write.stderr @@ -2,11 +2,11 @@ Warning: this tree is indicative only. Some tags may have been hidden. 0.. 1 | Act | └─┬── -| RsM | └─┬── -| RsM | ├─┬── -| RsM | │ └─┬── -| Rs | │ └──── Strongly protected -| RsM | └──── +| ReIM| └─┬── +| ReIM| ├─┬── +| ReIM| │ └─┬── +| Res | │ └──── Strongly protected +| ReIM| └──── ────────────────────────────────────────────────── error: Undefined Behavior: write access through (y, callee:y, caller:y) at ALLOC[0x0] is forbidden --> $DIR/cell-protected-write.rs:LL:CC diff --git a/src/tools/miri/tests/fail/tree_borrows/reserved/int-protected-write.stderr b/src/tools/miri/tests/fail/tree_borrows/reserved/int-protected-write.stderr index 41559587bda..a4dc123979e 100644 --- a/src/tools/miri/tests/fail/tree_borrows/reserved/int-protected-write.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/reserved/int-protected-write.stderr @@ -2,11 +2,11 @@ Warning: this tree is indicative only. Some tags may have been hidden. 0.. 1 | Act | └─┬── -| Rs | └─┬── -| Rs | ├─┬── -| Rs | │ └─┬── -| Rs | │ └──── Strongly protected -| Rs | └──── +| Res | └─┬── +| Res | ├─┬── +| Res | │ └─┬── +| Res | │ └──── Strongly protected +| Res | └──── ────────────────────────────────────────────────── error: Undefined Behavior: write access through (y, callee:y, caller:y) at ALLOC[0x0] is forbidden --> $DIR/int-protected-write.rs:LL:CC diff --git a/src/tools/miri/tests/fail/unwind-action-terminate.stderr b/src/tools/miri/tests/fail/unwind-action-terminate.stderr index 547d550d3d0..fd67bdf4a90 100644 --- a/src/tools/miri/tests/fail/unwind-action-terminate.stderr +++ b/src/tools/miri/tests/fail/unwind-action-terminate.stderr @@ -1,7 +1,7 @@ thread 'main' panicked at $DIR/unwind-action-terminate.rs:LL:CC: explicit panic note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC: panic in a function that cannot unwind stack backtrace: diff --git a/src/tools/miri/tests/fail/weak_memory/weak_uninit.rs b/src/tools/miri/tests/fail/weak_memory/weak_uninit.rs new file mode 100644 index 00000000000..79c97a5b752 --- /dev/null +++ b/src/tools/miri/tests/fail/weak_memory/weak_uninit.rs @@ -0,0 +1,42 @@ +//@compile-flags: -Zmiri-ignore-leaks -Zmiri-preemption-rate=0 + +// Tests showing weak memory behaviours are exhibited. All tests +// return true when the desired behaviour is seen. +// This is scheduler and pseudo-RNG dependent, so each test is +// run multiple times until one try returns true. +// Spurious failure is possible, if you are really unlucky with +// the RNG and always read the latest value from the store buffer. + +use std::sync::atomic::*; +use std::thread::spawn; + +#[allow(dead_code)] +#[derive(Copy, Clone)] +struct EvilSend(pub T); + +unsafe impl Send for EvilSend {} +unsafe impl Sync for EvilSend {} + +// We can't create static items because we need to run each test multiple times. +fn static_uninit_atomic() -> &'static AtomicUsize { + unsafe { Box::leak(Box::new_uninit()).assume_init_ref() } +} + +fn relaxed() { + let x = static_uninit_atomic(); + let j1 = spawn(move || { + x.store(1, Ordering::Relaxed); + }); + + let j2 = spawn(move || x.load(Ordering::Relaxed)); //~ERROR: using uninitialized data + + j1.join().unwrap(); + j2.join().unwrap(); +} + +pub fn main() { + // If we try often enough, we should hit UB. + for _ in 0..100 { + relaxed(); + } +} diff --git a/src/tools/miri/tests/fail/weak_memory/weak_uninit.stderr b/src/tools/miri/tests/fail/weak_memory/weak_uninit.stderr new file mode 100644 index 00000000000..9aa5bc2fa76 --- /dev/null +++ b/src/tools/miri/tests/fail/weak_memory/weak_uninit.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory + --> $DIR/weak_uninit.rs:LL:CC + | +LL | let j2 = spawn(move || x.load(Ordering::Relaxed)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE on thread `unnamed-ID`: + = note: inside closure at $DIR/weak_uninit.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/panic/alloc_error_handler_hook.stderr b/src/tools/miri/tests/panic/alloc_error_handler_hook.stderr index 5b309ed09bb..319a10febb3 100644 --- a/src/tools/miri/tests/panic/alloc_error_handler_hook.stderr +++ b/src/tools/miri/tests/panic/alloc_error_handler_hook.stderr @@ -1,5 +1,5 @@ thread 'main' panicked at $DIR/alloc_error_handler_hook.rs:LL:CC: alloc error hook called note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect yes we are unwinding! diff --git a/src/tools/miri/tests/panic/alloc_error_handler_panic.stderr b/src/tools/miri/tests/panic/alloc_error_handler_panic.stderr index 3d5457799f6..2cdff03f10f 100644 --- a/src/tools/miri/tests/panic/alloc_error_handler_panic.stderr +++ b/src/tools/miri/tests/panic/alloc_error_handler_panic.stderr @@ -1,5 +1,5 @@ thread 'main' panicked at RUSTLIB/std/src/alloc.rs:LL:CC: memory allocation of 4 bytes failed note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect yes we are unwinding! diff --git a/src/tools/miri/tests/panic/div-by-zero-2.stderr b/src/tools/miri/tests/panic/div-by-zero-2.stderr index f0b84ea6fd6..ed394f76b0e 100644 --- a/src/tools/miri/tests/panic/div-by-zero-2.stderr +++ b/src/tools/miri/tests/panic/div-by-zero-2.stderr @@ -1,4 +1,4 @@ thread 'main' panicked at $DIR/div-by-zero-2.rs:LL:CC: attempt to divide by zero note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect diff --git a/src/tools/miri/tests/panic/function_calls/exported_symbol_good_unwind.stderr b/src/tools/miri/tests/panic/function_calls/exported_symbol_good_unwind.stderr index f77f6f01119..6733f2e42c1 100644 --- a/src/tools/miri/tests/panic/function_calls/exported_symbol_good_unwind.stderr +++ b/src/tools/miri/tests/panic/function_calls/exported_symbol_good_unwind.stderr @@ -1,7 +1,7 @@ thread 'main' panicked at $DIR/exported_symbol_good_unwind.rs:LL:CC: explicit panic note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect thread 'main' panicked at $DIR/exported_symbol_good_unwind.rs:LL:CC: explicit panic thread 'main' panicked at $DIR/exported_symbol_good_unwind.rs:LL:CC: diff --git a/src/tools/miri/tests/panic/oob_subslice.stderr b/src/tools/miri/tests/panic/oob_subslice.stderr index c116f8eb525..46f0f643a47 100644 --- a/src/tools/miri/tests/panic/oob_subslice.stderr +++ b/src/tools/miri/tests/panic/oob_subslice.stderr @@ -1,4 +1,4 @@ thread 'main' panicked at $DIR/oob_subslice.rs:LL:CC: range end index 5 out of range for slice of length 4 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect diff --git a/src/tools/miri/tests/panic/overflowing-lsh-neg.stderr b/src/tools/miri/tests/panic/overflowing-lsh-neg.stderr index 1d057ea5eb4..be822bd0285 100644 --- a/src/tools/miri/tests/panic/overflowing-lsh-neg.stderr +++ b/src/tools/miri/tests/panic/overflowing-lsh-neg.stderr @@ -1,4 +1,4 @@ thread 'main' panicked at $DIR/overflowing-lsh-neg.rs:LL:CC: attempt to shift left with overflow note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect diff --git a/src/tools/miri/tests/panic/overflowing-rsh-1.stderr b/src/tools/miri/tests/panic/overflowing-rsh-1.stderr index d1a79400bfa..fc090aba5fd 100644 --- a/src/tools/miri/tests/panic/overflowing-rsh-1.stderr +++ b/src/tools/miri/tests/panic/overflowing-rsh-1.stderr @@ -1,4 +1,4 @@ thread 'main' panicked at $DIR/overflowing-rsh-1.rs:LL:CC: attempt to shift right with overflow note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect diff --git a/src/tools/miri/tests/panic/overflowing-rsh-2.stderr b/src/tools/miri/tests/panic/overflowing-rsh-2.stderr index 612b0c0c4c2..77160e1870f 100644 --- a/src/tools/miri/tests/panic/overflowing-rsh-2.stderr +++ b/src/tools/miri/tests/panic/overflowing-rsh-2.stderr @@ -1,4 +1,4 @@ thread 'main' panicked at $DIR/overflowing-rsh-2.rs:LL:CC: attempt to shift right with overflow note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect diff --git a/src/tools/miri/tests/panic/panic2.stderr b/src/tools/miri/tests/panic/panic2.stderr index 792c71346fd..f7408310093 100644 --- a/src/tools/miri/tests/panic/panic2.stderr +++ b/src/tools/miri/tests/panic/panic2.stderr @@ -1,4 +1,4 @@ thread 'main' panicked at $DIR/panic2.rs:LL:CC: 42-panicking from libstd note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect diff --git a/src/tools/miri/tests/panic/panic3.stderr b/src/tools/miri/tests/panic/panic3.stderr index f8016bc3912..32ba400e025 100644 --- a/src/tools/miri/tests/panic/panic3.stderr +++ b/src/tools/miri/tests/panic/panic3.stderr @@ -1,4 +1,4 @@ thread 'main' panicked at $DIR/panic3.rs:LL:CC: panicking from libcore note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect diff --git a/src/tools/miri/tests/panic/panic4.stderr b/src/tools/miri/tests/panic/panic4.stderr index 67410bf3b1a..a8a23ee3ce1 100644 --- a/src/tools/miri/tests/panic/panic4.stderr +++ b/src/tools/miri/tests/panic/panic4.stderr @@ -1,4 +1,4 @@ thread 'main' panicked at $DIR/panic4.rs:LL:CC: 42-panicking from libcore note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect diff --git a/src/tools/miri/tests/pass/function_calls/target_feature_wasm.rs b/src/tools/miri/tests/panic/target_feature_wasm.rs similarity index 61% rename from src/tools/miri/tests/pass/function_calls/target_feature_wasm.rs rename to src/tools/miri/tests/panic/target_feature_wasm.rs index 5056f32de44..c67d2983f78 100644 --- a/src/tools/miri/tests/pass/function_calls/target_feature_wasm.rs +++ b/src/tools/miri/tests/panic/target_feature_wasm.rs @@ -2,7 +2,9 @@ //@compile-flags: -C target-feature=-simd128 fn main() { - // Calling functions with `#[target_feature]` is not unsound on WASM, see #84988 + // Calling functions with `#[target_feature]` is not unsound on WASM, see #84988. + // But if the compiler actually uses the target feature, it will lead to an error when the module is loaded. + // We emulate this with an "unsupported" error. assert!(!cfg!(target_feature = "simd128")); simd128_fn(); } diff --git a/src/tools/miri/tests/panic/transmute_fat2.stderr b/src/tools/miri/tests/panic/transmute_fat2.stderr index 2ee01d46931..021ca1c4b32 100644 --- a/src/tools/miri/tests/panic/transmute_fat2.stderr +++ b/src/tools/miri/tests/panic/transmute_fat2.stderr @@ -1,4 +1,4 @@ thread 'main' panicked at $DIR/transmute_fat2.rs:LL:CC: index out of bounds: the len is 0 but the index is 0 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect diff --git a/src/tools/miri/tests/panic/unsupported_foreign_function.stderr b/src/tools/miri/tests/panic/unsupported_foreign_function.stderr index d0a7d8dafc5..fcc4220bfce 100644 --- a/src/tools/miri/tests/panic/unsupported_foreign_function.stderr +++ b/src/tools/miri/tests/panic/unsupported_foreign_function.stderr @@ -1,4 +1,4 @@ thread 'main' panicked at $DIR/unsupported_foreign_function.rs:LL:CC: unsupported Miri functionality: can't call foreign function `foo` on $OS note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect diff --git a/src/tools/miri/tests/panic/unsupported_syscall.stderr b/src/tools/miri/tests/panic/unsupported_syscall.stderr index f802159cb1c..660cfba8900 100644 --- a/src/tools/miri/tests/panic/unsupported_syscall.stderr +++ b/src/tools/miri/tests/panic/unsupported_syscall.stderr @@ -1,4 +1,4 @@ thread 'main' panicked at $DIR/unsupported_syscall.rs:LL:CC: unsupported Miri functionality: can't execute syscall with ID 0 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect diff --git a/src/tools/miri/tests/pass-dep/libc/libc-epoll.rs b/src/tools/miri/tests/pass-dep/libc/libc-epoll.rs new file mode 100644 index 00000000000..052ce73de23 --- /dev/null +++ b/src/tools/miri/tests/pass-dep/libc/libc-epoll.rs @@ -0,0 +1,632 @@ +//@only-target-linux + +#![feature(strict_provenance)] +use std::convert::TryInto; + +fn main() { + test_epoll_socketpair(); + test_epoll_socketpair_both_sides(); + test_socketpair_read(); + test_epoll_eventfd(); + + test_event_overwrite(); + test_not_fully_closed_fd(); + test_closed_fd(); + test_two_epoll_instance(); + test_no_notification_for_unregister_flag(); + test_epoll_ctl_mod(); + test_epoll_ctl_del(); + test_two_same_fd_in_same_epoll_instance(); + test_epoll_wait_maxevent_zero(); + test_socketpair_epollerr(); + test_epoll_lost_events(); + test_ready_list_fetching_logic(); +} + +// Using `as` cast since `EPOLLET` wraps around +const EPOLL_IN_OUT_ET: u32 = (libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET) as _; + +#[track_caller] +fn check_epoll_wait(epfd: i32, expected_notifications: &[(u32, u64)]) { + let epoll_event = libc::epoll_event { events: 0, u64: 0 }; + let mut array: [libc::epoll_event; N] = [epoll_event; N]; + let maxsize = N; + let array_ptr = array.as_mut_ptr(); + let res = unsafe { libc::epoll_wait(epfd, array_ptr, maxsize.try_into().unwrap(), 0) }; + if res < 0 { + panic!("epoll_wait failed: {}", std::io::Error::last_os_error()); + } + assert_eq!( + res, + expected_notifications.len().try_into().unwrap(), + "got wrong number of notifications" + ); + let slice = unsafe { std::slice::from_raw_parts(array_ptr, res.try_into().unwrap()) }; + for (return_event, expected_event) in slice.iter().zip(expected_notifications.iter()) { + let event = return_event.events; + let data = return_event.u64; + assert_eq!(event, expected_event.0, "got wrong events"); + assert_eq!(data, expected_event.1, "got wrong data"); + } +} + +fn test_epoll_socketpair() { + // Create an epoll instance. + let epfd = unsafe { libc::epoll_create1(0) }; + assert_ne!(epfd, -1); + + // Create a socketpair instance. + let mut fds = [-1, -1]; + let res = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }; + assert_eq!(res, 0); + + // Write to fd[0] + let data = "abcde".as_bytes().as_ptr(); + let res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5) }; + assert_eq!(res, 5); + + // Register fd[1] with EPOLLIN|EPOLLOUT|EPOLLET|EPOLLRDHUP + let mut ev = libc::epoll_event { + events: (libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET | libc::EPOLLRDHUP) as _, + u64: u64::try_from(fds[1]).unwrap(), + }; + let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) }; + assert_eq!(res, 0); + + // Check result from epoll_wait. + let expected_event = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap(); + let expected_value = u64::try_from(fds[1]).unwrap(); + check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]); + + // Check that this is indeed using "ET" (edge-trigger) semantics: a second epoll should return nothing. + check_epoll_wait::<8>(epfd, &[]); + + // Write some more to fd[0]. + let data = "abcde".as_bytes().as_ptr(); + let res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5) }; + assert_eq!(res, 5); + + // This did not change the readiness of fd[1]. And yet, we're seeing the event reported + // again by the kernel, so Miri does the same. + check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]); + + // Close the peer socketpair. + let res = unsafe { libc::close(fds[0]) }; + assert_eq!(res, 0); + + // Check result from epoll_wait. + // We expect to get a read, write, HUP notification from the close since closing an FD always unblocks reads and writes on its peer. + let expected_event = + u32::try_from(libc::EPOLLRDHUP | libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLHUP).unwrap(); + let expected_value = u64::try_from(fds[1]).unwrap(); + check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]); +} + +// This test first registers a file description with a flag that does not lead to notification, +// then EPOLL_CTL_MOD to add another flag that will lead to notification. +fn test_epoll_ctl_mod() { + // Create an epoll instance. + let epfd = unsafe { libc::epoll_create1(0) }; + assert_ne!(epfd, -1); + + // Create a socketpair instance. + let mut fds = [-1, -1]; + let res = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }; + assert_eq!(res, 0); + + // Register fd[1] with EPOLLIN|EPOLLET. + let mut ev = libc::epoll_event { + events: (libc::EPOLLIN | libc::EPOLLET) as _, + u64: u64::try_from(fds[1]).unwrap(), + }; + let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) }; + assert_eq!(res, 0); + + // Check result from epoll_wait. No notification would be returned. + check_epoll_wait::<8>(epfd, &[]); + + // Use EPOLL_CTL_MOD to change to EPOLLOUT flag. + let mut ev = libc::epoll_event { + events: (libc::EPOLLOUT | libc::EPOLLET) as _, + u64: u64::try_from(fds[1]).unwrap(), + }; + let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_MOD, fds[1], &mut ev) }; + assert_eq!(res, 0); + + // Check result from epoll_wait. EPOLLOUT notification is expected. + let expected_event = u32::try_from(libc::EPOLLOUT).unwrap(); + let expected_value = u64::try_from(fds[1]).unwrap(); + check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]); +} + +fn test_epoll_ctl_del() { + // Create an epoll instance. + let epfd = unsafe { libc::epoll_create1(0) }; + assert_ne!(epfd, -1); + + // Create a socketpair instance. + let mut fds = [-1, -1]; + let res = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }; + assert_eq!(res, 0); + + // Write to fd[0] + let data = "abcde".as_bytes().as_ptr(); + let res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5) }; + assert_eq!(res, 5); + + // Register fd[1] with EPOLLIN|EPOLLOUT|EPOLLET + let mut ev = libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: u64::try_from(fds[1]).unwrap() }; + let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) }; + assert_eq!(res, 0); + + // Test EPOLL_CTL_DEL. + let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_DEL, fds[1], &mut ev) }; + assert_eq!(res, 0); + check_epoll_wait::<8>(epfd, &[]); +} + +// This test is for one fd registered under two different epoll instance. +fn test_two_epoll_instance() { + // Create two epoll instance. + let epfd1 = unsafe { libc::epoll_create1(0) }; + assert_ne!(epfd1, -1); + let epfd2 = unsafe { libc::epoll_create1(0) }; + assert_ne!(epfd2, -1); + + // Create a socketpair instance. + let mut fds = [-1, -1]; + let res = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }; + assert_eq!(res, 0); + + // Write to the socketpair. + let data = "abcde".as_bytes().as_ptr(); + let res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5) }; + assert_eq!(res, 5); + + // Register one side of the socketpair with EPOLLIN | EPOLLOUT | EPOLLET. + let mut ev = libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: u64::try_from(fds[1]).unwrap() }; + let res = unsafe { libc::epoll_ctl(epfd1, libc::EPOLL_CTL_ADD, fds[1], &mut ev) }; + assert_eq!(res, 0); + let res = unsafe { libc::epoll_ctl(epfd2, libc::EPOLL_CTL_ADD, fds[1], &mut ev) }; + assert_eq!(res, 0); + + // Notification should be received from both instance of epoll. + let expected_event = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap(); + let expected_value = u64::try_from(fds[1]).unwrap(); + check_epoll_wait::<8>(epfd1, &[(expected_event, expected_value)]); + check_epoll_wait::<8>(epfd2, &[(expected_event, expected_value)]); +} + +// This test is for two same file description registered under the same epoll instance through dup. +// Notification should be provided for both. +fn test_two_same_fd_in_same_epoll_instance() { + // Create an epoll instance. + let epfd = unsafe { libc::epoll_create1(0) }; + assert_ne!(epfd, -1); + + // Create a socketpair instance. + let mut fds = [-1, -1]; + let res = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }; + assert_eq!(res, 0); + + // Dup the fd. + let newfd = unsafe { libc::dup(fds[1]) }; + assert_ne!(newfd, -1); + + // Register both fd to the same epoll instance. + let mut ev = libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: 5 as u64 }; + let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) }; + assert_eq!(res, 0); + let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, newfd, &mut ev) }; + assert_eq!(res, 0); + + // Write to the socketpair. + let data = "abcde".as_bytes().as_ptr(); + let res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5) }; + assert_eq!(res, 5); + + //Two notification should be received. + let expected_event = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap(); + let expected_value = 5 as u64; + check_epoll_wait::<8>( + epfd, + &[(expected_event, expected_value), (expected_event, expected_value)], + ); +} + +fn test_epoll_eventfd() { + // Create an eventfd instance. + let flags = libc::EFD_NONBLOCK | libc::EFD_CLOEXEC; + let fd = unsafe { libc::eventfd(0, flags) }; + + // Write to the eventfd instance. + let sized_8_data: [u8; 8] = 1_u64.to_ne_bytes(); + let res = unsafe { libc::write(fd, sized_8_data.as_ptr() as *const libc::c_void, 8) }; + assert_eq!(res, 8); + + // Create an epoll instance. + let epfd = unsafe { libc::epoll_create1(0) }; + assert_ne!(epfd, -1); + + // Register eventfd with EPOLLIN | EPOLLOUT | EPOLLET + let mut ev = libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: u64::try_from(fd).unwrap() }; + let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fd, &mut ev) }; + assert_eq!(res, 0); + + // Check result from epoll_wait. + let expected_event = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap(); + let expected_value = u64::try_from(fd).unwrap(); + check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]); +} + +// When read/write happened on one side of the socketpair, only the other side will be notified. +fn test_epoll_socketpair_both_sides() { + // Create an epoll instance. + let epfd = unsafe { libc::epoll_create1(0) }; + assert_ne!(epfd, -1); + + // Create a socketpair instance. + let mut fds = [-1, -1]; + let res = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }; + assert_eq!(res, 0); + + // Register both fd to the same epoll instance. + let mut ev = libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: fds[0] as u64 }; + let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[0], &mut ev) }; + assert_eq!(res, 0); + let mut ev = libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: fds[1] as u64 }; + let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) }; + assert_eq!(res, 0); + + // Write to fds[1]. + let data = "abcde".as_bytes().as_ptr(); + let res = unsafe { libc::write(fds[1], data as *const libc::c_void, 5) }; + assert_eq!(res, 5); + + //Two notification should be received. + let expected_event0 = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap(); + let expected_value0 = fds[0] as u64; + let expected_event1 = u32::try_from(libc::EPOLLOUT).unwrap(); + let expected_value1 = fds[1] as u64; + check_epoll_wait::<8>( + epfd, + &[(expected_event0, expected_value0), (expected_event1, expected_value1)], + ); + + // Read from fds[0]. + let mut buf: [u8; 5] = [0; 5]; + let res = unsafe { libc::read(fds[0], buf.as_mut_ptr().cast(), buf.len() as libc::size_t) }; + assert_eq!(res, 5); + assert_eq!(buf, "abcde".as_bytes()); + + // Notification should be provided for fds[1]. + let expected_event = u32::try_from(libc::EPOLLOUT).unwrap(); + let expected_value = fds[1] as u64; + check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]); +} + +// When file description is fully closed, epoll_wait should not provide any notification for +// that file description. +fn test_closed_fd() { + // Create an epoll instance. + let epfd = unsafe { libc::epoll_create1(0) }; + assert_ne!(epfd, -1); + + // Create an eventfd instance. + let flags = libc::EFD_NONBLOCK | libc::EFD_CLOEXEC; + let fd = unsafe { libc::eventfd(0, flags) }; + + // Register eventfd with EPOLLIN | EPOLLOUT | EPOLLET + let mut ev = libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: u64::try_from(fd).unwrap() }; + let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fd, &mut ev) }; + assert_eq!(res, 0); + + // Write to the eventfd instance. + let sized_8_data: [u8; 8] = 1_u64.to_ne_bytes(); + let res = unsafe { libc::write(fd, sized_8_data.as_ptr() as *const libc::c_void, 8) }; + assert_eq!(res, 8); + + // Close the eventfd. + let res = unsafe { libc::close(fd) }; + assert_eq!(res, 0); + + // No notification should be provided because the file description is closed. + check_epoll_wait::<8>(epfd, &[]); +} + +// When a certain file descriptor registered with epoll is closed, but the underlying file description +// is not closed, notification should still be provided. +// +// This is a quirk of epoll being described in https://man7.org/linux/man-pages/man7/epoll.7.html +// A file descriptor is removed from an interest list only after all the file descriptors +// referring to the underlying open file description have been closed. +fn test_not_fully_closed_fd() { + // Create an epoll instance. + let epfd = unsafe { libc::epoll_create1(0) }; + assert_ne!(epfd, -1); + + // Create an eventfd instance. + let flags = libc::EFD_NONBLOCK | libc::EFD_CLOEXEC; + let fd = unsafe { libc::eventfd(0, flags) }; + + // Dup the fd. + let newfd = unsafe { libc::dup(fd) }; + assert_ne!(newfd, -1); + + // Register eventfd with EPOLLIN | EPOLLOUT | EPOLLET + let mut ev = libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: u64::try_from(fd).unwrap() }; + let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fd, &mut ev) }; + assert_eq!(res, 0); + + // Close the original fd that being used to register with epoll. + let res = unsafe { libc::close(fd) }; + assert_eq!(res, 0); + + // Notification should still be provided because the file description is not closed. + let expected_event = u32::try_from(libc::EPOLLOUT).unwrap(); + let expected_value = fd as u64; + check_epoll_wait::<1>(epfd, &[(expected_event, expected_value)]); + + // Write to the eventfd instance to produce notification. + let sized_8_data: [u8; 8] = 1_u64.to_ne_bytes(); + let res = unsafe { libc::write(newfd, sized_8_data.as_ptr() as *const libc::c_void, 8) }; + assert_eq!(res, 8); + + // Close the dupped fd. + let res = unsafe { libc::close(newfd) }; + assert_eq!(res, 0); + + // No notification should be provided. + check_epoll_wait::<1>(epfd, &[]); +} + +// Each time a notification is provided, it should reflect the file description's readiness +// at the moment the latest event occurred. +fn test_event_overwrite() { + // Create an eventfd instance. + let flags = libc::EFD_NONBLOCK | libc::EFD_CLOEXEC; + let fd = unsafe { libc::eventfd(0, flags) }; + + // Write to the eventfd instance. + let sized_8_data: [u8; 8] = 1_u64.to_ne_bytes(); + let res = unsafe { libc::write(fd, sized_8_data.as_ptr() as *const libc::c_void, 8) }; + assert_eq!(res, 8); + + // Create an epoll instance. + let epfd = unsafe { libc::epoll_create1(0) }; + assert_ne!(epfd, -1); + + // Register eventfd with EPOLLIN | EPOLLOUT | EPOLLET + let mut ev = libc::epoll_event { + events: (libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET) as _, + u64: u64::try_from(fd).unwrap(), + }; + let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fd, &mut ev) }; + assert_eq!(res, 0); + + // Read from the eventfd instance. + let mut buf: [u8; 8] = [0; 8]; + let res = unsafe { libc::read(fd, buf.as_mut_ptr().cast(), 8) }; + assert_eq!(res, 8); + + // Check result from epoll_wait. + let expected_event = u32::try_from(libc::EPOLLOUT).unwrap(); + let expected_value = u64::try_from(fd).unwrap(); + check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]); +} + +// An epoll notification will be provided for every succesful read in a socketpair. +// This behaviour differs from the real system. +fn test_socketpair_read() { + // Create an epoll instance. + let epfd = unsafe { libc::epoll_create1(0) }; + assert_ne!(epfd, -1); + + // Create a socketpair instance. + let mut fds = [-1, -1]; + let res = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }; + assert_eq!(res, 0); + + // Register both fd to the same epoll instance. + let mut ev = libc::epoll_event { + events: (libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET) as _, + u64: fds[0] as u64, + }; + let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[0], &mut ev) }; + assert_eq!(res, 0); + let mut ev = libc::epoll_event { + events: (libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET) as _, + u64: fds[1] as u64, + }; + let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) }; + assert_eq!(res, 0); + + // Write 5 bytes to fds[1]. + let data = "abcde".as_bytes().as_ptr(); + let res = unsafe { libc::write(fds[1], data as *const libc::c_void, 5) }; + assert_eq!(res, 5); + + //Two notification should be received. + let expected_event0 = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap(); + let expected_value0 = fds[0] as u64; + let expected_event1 = u32::try_from(libc::EPOLLOUT).unwrap(); + let expected_value1 = fds[1] as u64; + check_epoll_wait::<8>( + epfd, + &[(expected_event0, expected_value0), (expected_event1, expected_value1)], + ); + + // Read 3 bytes from fds[0]. + let mut buf: [u8; 3] = [0; 3]; + let res = unsafe { libc::read(fds[0], buf.as_mut_ptr().cast(), buf.len() as libc::size_t) }; + assert_eq!(res, 3); + assert_eq!(buf, "abc".as_bytes()); + + // Notification will be provided in Miri. + // But in real systems, no notification will be provided here, since Linux prefers to avoid + // wakeups that are likely to lead to only small amounts of data being read/written. + // We make the test work in both cases, thus documenting the difference in behavior. + let expected_event = u32::try_from(libc::EPOLLOUT).unwrap(); + let expected_value = fds[1] as u64; + if cfg!(miri) { + check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]); + } else { + check_epoll_wait::<8>(epfd, &[]); + } + + // Read until the buffer is empty. + let mut buf: [u8; 2] = [0; 2]; + let res = unsafe { libc::read(fds[0], buf.as_mut_ptr().cast(), buf.len() as libc::size_t) }; + assert_eq!(res, 2); + assert_eq!(buf, "de".as_bytes()); + + // Notification will be provided. + // In real system, notification will be provided too. + let expected_event = u32::try_from(libc::EPOLLOUT).unwrap(); + let expected_value = fds[1] as u64; + check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]); +} + +// This is to test whether flag that we don't register won't trigger notification. +fn test_no_notification_for_unregister_flag() { + // Create an epoll instance. + let epfd = unsafe { libc::epoll_create1(0) }; + assert_ne!(epfd, -1); + + // Create a socketpair instance. + let mut fds = [-1, -1]; + let res = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }; + assert_eq!(res, 0); + + // Register fd[0] with EPOLLOUT|EPOLLET. + let mut ev = libc::epoll_event { + events: (libc::EPOLLOUT | libc::EPOLLET) as _, + u64: u64::try_from(fds[0]).unwrap(), + }; + let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) }; + assert_eq!(res, 0); + + // Write to fd[1]. + let data = "abcde".as_bytes().as_ptr(); + let res: i32 = + unsafe { libc::write(fds[1], data as *const libc::c_void, 5).try_into().unwrap() }; + assert_eq!(res, 5); + + // Check result from epoll_wait. Since we didn't register EPOLLIN flag, the notification won't + // contain EPOLLIN even though fds[0] is now readable. + let expected_event = u32::try_from(libc::EPOLLOUT).unwrap(); + let expected_value = u64::try_from(fds[0]).unwrap(); + check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]); +} + +fn test_epoll_wait_maxevent_zero() { + // Create an epoll instance. + let epfd = unsafe { libc::epoll_create1(0) }; + assert_ne!(epfd, -1); + // It is ok to use a dangling pointer here because it will error out before the + // pointer actually gets accessed. + let array_ptr = std::ptr::without_provenance_mut::(0x100); + let res = unsafe { libc::epoll_wait(epfd, array_ptr, 0, 0) }; + let e = std::io::Error::last_os_error(); + assert_eq!(e.raw_os_error(), Some(libc::EINVAL)); + assert_eq!(res, -1); +} + +fn test_socketpair_epollerr() { + // Create an epoll instance. + let epfd = unsafe { libc::epoll_create1(0) }; + assert_ne!(epfd, -1); + + // Create a socketpair instance. + let mut fds = [-1, -1]; + let res = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }; + assert_eq!(res, 0); + + // Write to fd[0] + let data = "abcde".as_bytes().as_ptr(); + let res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5) }; + assert_eq!(res, 5); + + // Close fds[1]. + // EPOLLERR will be triggered if we close peer fd that still has data in its read buffer. + let res = unsafe { libc::close(fds[1]) }; + assert_eq!(res, 0); + + // Register fd[1] with EPOLLIN|EPOLLOUT|EPOLLET|EPOLLRDHUP + let mut ev = libc::epoll_event { + events: (libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET | libc::EPOLLRDHUP) as _, + u64: u64::try_from(fds[1]).unwrap(), + }; + let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[0], &mut ev) }; + assert_ne!(res, -1); + + // Check result from epoll_wait. + let expected_event = u32::try_from( + libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLHUP | libc::EPOLLRDHUP | libc::EPOLLERR, + ) + .unwrap(); + let expected_value = u64::try_from(fds[1]).unwrap(); + check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]); +} + +// This is a test for https://github.com/rust-lang/miri/issues/3812, +// epoll can lose events if they don't fit in the output buffer. +fn test_epoll_lost_events() { + // Create an epoll instance. + let epfd = unsafe { libc::epoll_create1(0) }; + assert_ne!(epfd, -1); + + // Create a socketpair instance. + let mut fds = [-1, -1]; + let res = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }; + assert_eq!(res, 0); + + // Register both fd to the same epoll instance. + let mut ev = libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: fds[0] as u64 }; + let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[0], &mut ev) }; + assert_eq!(res, 0); + let mut ev = libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: fds[1] as u64 }; + let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) }; + assert_eq!(res, 0); + + //Two notification should be received. But we only provide buffer for one event. + let expected_event0 = u32::try_from(libc::EPOLLOUT).unwrap(); + let expected_value0 = fds[0] as u64; + check_epoll_wait::<1>(epfd, &[(expected_event0, expected_value0)]); + + // Previous event should be returned for the second epoll_wait. + let expected_event1 = u32::try_from(libc::EPOLLOUT).unwrap(); + let expected_value1 = fds[1] as u64; + check_epoll_wait::<1>(epfd, &[(expected_event1, expected_value1)]); +} + +// This is testing if closing an fd that is already in ready list will cause an empty entry in +// returned notification. +// Related discussion in https://github.com/rust-lang/miri/pull/3818#discussion_r1720679440. +fn test_ready_list_fetching_logic() { + // Create an epoll instance. + let epfd = unsafe { libc::epoll_create1(0) }; + assert_ne!(epfd, -1); + + // Create two eventfd instances. + let flags = libc::EFD_NONBLOCK | libc::EFD_CLOEXEC; + let fd0 = unsafe { libc::eventfd(0, flags) }; + let fd1 = unsafe { libc::eventfd(0, flags) }; + + // Register both fd to the same epoll instance. At this point, both of them are on the ready list. + let mut ev = libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: fd0 as u64 }; + let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fd0, &mut ev) }; + assert_eq!(res, 0); + let mut ev = libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: fd1 as u64 }; + let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fd1, &mut ev) }; + assert_eq!(res, 0); + + // Close fd0 so the first entry in the ready list will be empty. + let res = unsafe { libc::close(fd0) }; + assert_eq!(res, 0); + + // Notification for fd1 should be returned. + let expected_event1 = u32::try_from(libc::EPOLLOUT).unwrap(); + let expected_value1 = fd1 as u64; + check_epoll_wait::<1>(epfd, &[(expected_event1, expected_value1)]); +} diff --git a/src/tools/miri/tests/pass-dep/libc/libc-misc.rs b/src/tools/miri/tests/pass-dep/libc/libc-misc.rs index f7e1d9faa6a..a5b944e9d42 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-misc.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-misc.rs @@ -75,11 +75,15 @@ fn test_dlsym() { assert_eq!(errno, libc::EBADF); } +fn test_getuid() { + let _val = unsafe { libc::getuid() }; +} + fn main() { test_thread_local_errno(); test_environ(); - test_dlsym(); + test_getuid(); #[cfg(target_os = "linux")] test_sigrt(); diff --git a/src/tools/miri/tests/pass-dep/libc/libc-pipe.rs b/src/tools/miri/tests/pass-dep/libc/libc-pipe.rs new file mode 100644 index 00000000000..5dff612bd89 --- /dev/null +++ b/src/tools/miri/tests/pass-dep/libc/libc-pipe.rs @@ -0,0 +1,99 @@ +//@ignore-target-windows: No libc pipe on Windows +// test_race depends on a deterministic schedule. +//@compile-flags: -Zmiri-preemption-rate=0 +use std::thread; +fn main() { + test_pipe(); + test_pipe_threaded(); + test_race(); +} + +fn test_pipe() { + let mut fds = [-1, -1]; + let res = unsafe { libc::pipe(fds.as_mut_ptr()) }; + assert_eq!(res, 0); + + // Read size == data available in buffer. + let data = "12345".as_bytes().as_ptr(); + let res = unsafe { libc::write(fds[1], data as *const libc::c_void, 5) }; + assert_eq!(res, 5); + let mut buf3: [u8; 5] = [0; 5]; + let res = unsafe { libc::read(fds[0], buf3.as_mut_ptr().cast(), buf3.len() as libc::size_t) }; + assert_eq!(res, 5); + assert_eq!(buf3, "12345".as_bytes()); + + // Read size > data available in buffer. + let data = "123".as_bytes().as_ptr(); + let res = unsafe { libc::write(fds[1], data as *const libc::c_void, 3) }; + assert_eq!(res, 3); + let mut buf4: [u8; 5] = [0; 5]; + let res = unsafe { libc::read(fds[0], buf4.as_mut_ptr().cast(), buf4.len() as libc::size_t) }; + assert_eq!(res, 3); + assert_eq!(&buf4[0..3], "123".as_bytes()); +} + +fn test_pipe_threaded() { + let mut fds = [-1, -1]; + let res = unsafe { libc::pipe(fds.as_mut_ptr()) }; + assert_eq!(res, 0); + + let thread1 = thread::spawn(move || { + let mut buf: [u8; 5] = [0; 5]; + let res: i64 = unsafe { + libc::read(fds[0], buf.as_mut_ptr().cast(), buf.len() as libc::size_t) + .try_into() + .unwrap() + }; + assert_eq!(res, 5); + assert_eq!(buf, "abcde".as_bytes()); + }); + // FIXME: we should yield here once blocking is implemented. + //thread::yield_now(); + let data = "abcde".as_bytes().as_ptr(); + let res = unsafe { libc::write(fds[1], data as *const libc::c_void, 5) }; + assert_eq!(res, 5); + thread1.join().unwrap(); + + // Read and write from different direction + let thread2 = thread::spawn(move || { + // FIXME: we should yield here once blocking is implemented. + //thread::yield_now(); + let data = "12345".as_bytes().as_ptr(); + let res = unsafe { libc::write(fds[1], data as *const libc::c_void, 5) }; + assert_eq!(res, 5); + }); + // FIXME: we should not yield here once blocking is implemented. + thread::yield_now(); + let mut buf: [u8; 5] = [0; 5]; + let res = unsafe { libc::read(fds[0], buf.as_mut_ptr().cast(), buf.len() as libc::size_t) }; + assert_eq!(res, 5); + assert_eq!(buf, "12345".as_bytes()); + thread2.join().unwrap(); +} + +fn test_race() { + static mut VAL: u8 = 0; + let mut fds = [-1, -1]; + let res = unsafe { libc::pipe(fds.as_mut_ptr()) }; + assert_eq!(res, 0); + let thread1 = thread::spawn(move || { + let mut buf: [u8; 1] = [0; 1]; + // write() from the main thread will occur before the read() here + // because preemption is disabled and the main thread yields after write(). + let res: i32 = unsafe { + libc::read(fds[0], buf.as_mut_ptr().cast(), buf.len() as libc::size_t) + .try_into() + .unwrap() + }; + assert_eq!(res, 1); + assert_eq!(buf, "a".as_bytes()); + // The read above establishes a happens-before so it is now safe to access this global variable. + unsafe { assert_eq!(VAL, 1) }; + }); + unsafe { VAL = 1 }; + let data = "a".as_bytes().as_ptr(); + let res = unsafe { libc::write(fds[1], data as *const libc::c_void, 1) }; + assert_eq!(res, 1); + thread::yield_now(); + thread1.join().unwrap(); +} diff --git a/src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs b/src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs index 324c0127ee9..15e040116de 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs @@ -10,65 +10,68 @@ fn main() { fn test_socketpair() { let mut fds = [-1, -1]; - let mut res = - unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }; + let res = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }; assert_eq!(res, 0); // Read size == data available in buffer. let data = "abcde".as_bytes().as_ptr(); - res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5).try_into().unwrap() }; + let res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5) }; assert_eq!(res, 5); let mut buf: [u8; 5] = [0; 5]; - res = unsafe { - libc::read(fds[1], buf.as_mut_ptr().cast(), buf.len() as libc::size_t).try_into().unwrap() - }; + let res = unsafe { libc::read(fds[1], buf.as_mut_ptr().cast(), buf.len() as libc::size_t) }; assert_eq!(res, 5); assert_eq!(buf, "abcde".as_bytes()); // Read size > data available in buffer. let data = "abc".as_bytes().as_ptr(); - res = unsafe { libc::write(fds[0], data as *const libc::c_void, 3).try_into().unwrap() }; + let res = unsafe { libc::write(fds[0], data as *const libc::c_void, 3) }; assert_eq!(res, 3); let mut buf2: [u8; 5] = [0; 5]; - res = unsafe { - libc::read(fds[1], buf2.as_mut_ptr().cast(), buf2.len() as libc::size_t).try_into().unwrap() - }; + let res = unsafe { libc::read(fds[1], buf2.as_mut_ptr().cast(), buf2.len() as libc::size_t) }; assert_eq!(res, 3); assert_eq!(&buf2[0..3], "abc".as_bytes()); // Test read and write from another direction. // Read size == data available in buffer. let data = "12345".as_bytes().as_ptr(); - res = unsafe { libc::write(fds[1], data as *const libc::c_void, 5).try_into().unwrap() }; + let res = unsafe { libc::write(fds[1], data as *const libc::c_void, 5) }; assert_eq!(res, 5); let mut buf3: [u8; 5] = [0; 5]; - res = unsafe { - libc::read(fds[0], buf3.as_mut_ptr().cast(), buf3.len() as libc::size_t).try_into().unwrap() - }; + let res = unsafe { libc::read(fds[0], buf3.as_mut_ptr().cast(), buf3.len() as libc::size_t) }; assert_eq!(res, 5); assert_eq!(buf3, "12345".as_bytes()); // Read size > data available in buffer. let data = "123".as_bytes().as_ptr(); - res = unsafe { libc::write(fds[1], data as *const libc::c_void, 3).try_into().unwrap() }; + let res = unsafe { libc::write(fds[1], data as *const libc::c_void, 3) }; assert_eq!(res, 3); let mut buf4: [u8; 5] = [0; 5]; - res = unsafe { - libc::read(fds[0], buf4.as_mut_ptr().cast(), buf4.len() as libc::size_t).try_into().unwrap() - }; + let res = unsafe { libc::read(fds[0], buf4.as_mut_ptr().cast(), buf4.len() as libc::size_t) }; assert_eq!(res, 3); assert_eq!(&buf4[0..3], "123".as_bytes()); + + // Test when happens when we close one end, with some data in the buffer. + let res = unsafe { libc::write(fds[0], data as *const libc::c_void, 3) }; + assert_eq!(res, 3); + unsafe { libc::close(fds[0]) }; + // Reading the other end should return that data, then EOF. + let mut buf: [u8; 5] = [0; 5]; + let res = unsafe { libc::read(fds[1], buf.as_mut_ptr().cast(), buf.len() as libc::size_t) }; + assert_eq!(res, 3); + assert_eq!(&buf[0..3], "123".as_bytes()); + let res = unsafe { libc::read(fds[1], buf.as_mut_ptr().cast(), buf.len() as libc::size_t) }; + assert_eq!(res, 0); // 0-sized read: EOF. + // Writing the other end should emit EPIPE. + let res = unsafe { libc::write(fds[1], data as *const libc::c_void, 1) }; + assert_eq!(res, -1); + assert_eq!(std::io::Error::last_os_error().raw_os_error(), Some(libc::EPIPE)); } fn test_socketpair_threaded() { let mut fds = [-1, -1]; - let mut res = - unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }; + let res = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }; assert_eq!(res, 0); - let data = "abcde".as_bytes().as_ptr(); - res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5).try_into().unwrap() }; - assert_eq!(res, 5); let thread1 = thread::spawn(move || { let mut buf: [u8; 5] = [0; 5]; let res: i64 = unsafe { @@ -79,28 +82,34 @@ fn test_socketpair_threaded() { assert_eq!(res, 5); assert_eq!(buf, "abcde".as_bytes()); }); + // FIXME: we should yield here once blocking is implemented. + //thread::yield_now(); + let data = "abcde".as_bytes().as_ptr(); + let res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5) }; + assert_eq!(res, 5); thread1.join().unwrap(); // Read and write from different direction let thread2 = thread::spawn(move || { + // FIXME: we should yield here once blocking is implemented. + //thread::yield_now(); let data = "12345".as_bytes().as_ptr(); - let res: i64 = - unsafe { libc::write(fds[0], data as *const libc::c_void, 5).try_into().unwrap() }; + let res = unsafe { libc::write(fds[1], data as *const libc::c_void, 5) }; assert_eq!(res, 5); }); - thread2.join().unwrap(); + // FIXME: we should not yield here once blocking is implemented. + thread::yield_now(); let mut buf: [u8; 5] = [0; 5]; - res = unsafe { - libc::read(fds[1], buf.as_mut_ptr().cast(), buf.len() as libc::size_t).try_into().unwrap() - }; + let res = unsafe { libc::read(fds[0], buf.as_mut_ptr().cast(), buf.len() as libc::size_t) }; assert_eq!(res, 5); assert_eq!(buf, "12345".as_bytes()); + thread2.join().unwrap(); } + fn test_race() { static mut VAL: u8 = 0; let mut fds = [-1, -1]; - let mut res = - unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }; + let res = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }; assert_eq!(res, 0); let thread1 = thread::spawn(move || { let mut buf: [u8; 1] = [0; 1]; @@ -113,11 +122,12 @@ fn test_race() { }; assert_eq!(res, 1); assert_eq!(buf, "a".as_bytes()); + // The read above establishes a happens-before so it is now safe to access this global variable. unsafe { assert_eq!(VAL, 1) }; }); unsafe { VAL = 1 }; let data = "a".as_bytes().as_ptr(); - res = unsafe { libc::write(fds[0], data as *const libc::c_void, 1).try_into().unwrap() }; + let res = unsafe { libc::write(fds[0], data as *const libc::c_void, 1) }; assert_eq!(res, 1); thread::yield_now(); thread1.join().unwrap(); diff --git a/src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs b/src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs index a5cbe2a0d1d..04a55d7007c 100644 --- a/src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs +++ b/src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs @@ -1,4 +1,3 @@ -#![feature(raw_ref_op)] #![feature(core_intrinsics)] #![feature(custom_mir)] diff --git a/src/tools/miri/tests/pass/panic/catch_panic.stderr b/src/tools/miri/tests/pass/panic/catch_panic.stderr index a472a5d80cb..f61b39493ed 100644 --- a/src/tools/miri/tests/pass/panic/catch_panic.stderr +++ b/src/tools/miri/tests/pass/panic/catch_panic.stderr @@ -1,7 +1,7 @@ thread 'main' panicked at $DIR/catch_panic.rs:LL:CC: Hello from std::panic note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect Caught panic message (&str): Hello from std::panic thread 'main' panicked at $DIR/catch_panic.rs:LL:CC: Hello from std::panic: 1 diff --git a/src/tools/miri/tests/pass/panic/concurrent-panic.stderr b/src/tools/miri/tests/pass/panic/concurrent-panic.stderr index b2a5cf4922c..fe0d16ca78a 100644 --- a/src/tools/miri/tests/pass/panic/concurrent-panic.stderr +++ b/src/tools/miri/tests/pass/panic/concurrent-panic.stderr @@ -3,7 +3,7 @@ Thread 1 reported it has started thread '' panicked at $DIR/concurrent-panic.rs:LL:CC: panic in thread 2 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect Thread 2 blocking on thread 1 Thread 2 reported it has started Unlocking mutex diff --git a/src/tools/miri/tests/pass/panic/nested_panic_caught.stderr b/src/tools/miri/tests/pass/panic/nested_panic_caught.stderr index 3efb4be40f9..a346d31f645 100644 --- a/src/tools/miri/tests/pass/panic/nested_panic_caught.stderr +++ b/src/tools/miri/tests/pass/panic/nested_panic_caught.stderr @@ -1,7 +1,7 @@ thread 'main' panicked at $DIR/nested_panic_caught.rs:LL:CC: once note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect thread 'main' panicked at $DIR/nested_panic_caught.rs:LL:CC: twice stack backtrace: diff --git a/src/tools/miri/tests/pass/panic/thread_panic.stderr b/src/tools/miri/tests/pass/panic/thread_panic.stderr index bdfe4f98ba3..0fde5922c19 100644 --- a/src/tools/miri/tests/pass/panic/thread_panic.stderr +++ b/src/tools/miri/tests/pass/panic/thread_panic.stderr @@ -1,6 +1,6 @@ thread '' panicked at $DIR/thread_panic.rs:LL:CC: Hello! note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect thread 'childthread' panicked at $DIR/thread_panic.rs:LL:CC: Hello, world! diff --git a/src/tools/miri/tests/pass/rc.rs b/src/tools/miri/tests/pass/rc.rs index b1470dabc26..ce01e611b2c 100644 --- a/src/tools/miri/tests/pass/rc.rs +++ b/src/tools/miri/tests/pass/rc.rs @@ -1,7 +1,6 @@ //@revisions: stack tree //@[tree]compile-flags: -Zmiri-tree-borrows //@compile-flags: -Zmiri-strict-provenance -#![feature(new_uninit)] #![feature(get_mut_unchecked)] #![allow(ambiguous_wide_pointer_comparisons)] diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-sha.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-sha.rs new file mode 100644 index 00000000000..e65fdc3fbed --- /dev/null +++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-sha.rs @@ -0,0 +1,270 @@ +// Ignore everything except x86 and x86_64 +// Any new targets that are added to CI should be ignored here. +// (We cannot use `cfg`-based tricks here since the `target-feature` flags below only work on x86.) +//@ignore-target-aarch64 +//@ignore-target-arm +//@ignore-target-avr +//@ignore-target-s390x +//@ignore-target-thumbv7em +//@ignore-target-wasm32 +//@compile-flags: -C target-feature=+sha,+sse2,+ssse3,+sse4.1 + +#[cfg(target_arch = "x86")] +use std::arch::x86::*; +#[cfg(target_arch = "x86_64")] +use std::arch::x86_64::*; + +macro_rules! rounds4 { + ($abef:ident, $cdgh:ident, $rest:expr, $i:expr) => {{ + let k = K32X4[$i]; + let kv = _mm_set_epi32(k[0] as i32, k[1] as i32, k[2] as i32, k[3] as i32); + let t1 = _mm_add_epi32($rest, kv); + $cdgh = _mm_sha256rnds2_epu32($cdgh, $abef, t1); + let t2 = _mm_shuffle_epi32(t1, 0x0E); + $abef = _mm_sha256rnds2_epu32($abef, $cdgh, t2); + }}; +} + +macro_rules! schedule_rounds4 { + ( + $abef:ident, $cdgh:ident, + $w0:expr, $w1:expr, $w2:expr, $w3:expr, $w4:expr, + $i: expr + ) => {{ + $w4 = schedule($w0, $w1, $w2, $w3); + rounds4!($abef, $cdgh, $w4, $i); + }}; +} + +fn main() { + assert!(is_x86_feature_detected!("sha")); + assert!(is_x86_feature_detected!("sse2")); + assert!(is_x86_feature_detected!("ssse3")); + assert!(is_x86_feature_detected!("sse4.1")); + + unsafe { + test_sha256rnds2(); + test_sha256msg1(); + test_sha256msg2(); + test_sha256(); + } +} + +#[target_feature(enable = "sha,sse2,ssse3,sse4.1")] +unsafe fn test_sha256rnds2() { + let test_vectors = [ + ( + [0x3c6ef372, 0xa54ff53a, 0x1f83d9ab, 0x5be0cd19], + [0x6a09e667, 0xbb67ae85, 0x510e527f, 0x9b05688c], + [0x592340c6, 0x17386142, 0x91a0b7b1, 0x94ffa30c], + [0xeef39c6c, 0x4e7dfbc1, 0x467a98f3, 0xeb3d5616], + ), + ( + [0x6a09e667, 0xbb67ae85, 0x510e527f, 0x9b05688c], + [0xeef39c6c, 0x4e7dfbc1, 0x467a98f3, 0xeb3d5616], + [0x91a0b7b1, 0x94ffa30c, 0x592340c6, 0x17386142], + [0x7e7f3c9d, 0x78db9a20, 0xd82fe6ed, 0xaf1f2704], + ), + ( + [0xeef39c6c, 0x4e7dfbc1, 0x467a98f3, 0xeb3d5616], + [0x7e7f3c9d, 0x78db9a20, 0xd82fe6ed, 0xaf1f2704], + [0x1a89c3f6, 0xf3b6e817, 0x7a5a8511, 0x8bcc35cf], + [0xc9292f7e, 0x49137bd9, 0x7e5f9e08, 0xd10f9247], + ), + ]; + for (cdgh, abef, wk, expected) in test_vectors { + let output_reg = _mm_sha256rnds2_epu32(set_arr(cdgh), set_arr(abef), set_arr(wk)); + let mut output = [0u32; 4]; + _mm_storeu_si128(output.as_mut_ptr().cast(), output_reg); + // The values are stored as little endian, so we need to reverse them + output.reverse(); + assert_eq!(output, expected); + } +} + +#[target_feature(enable = "sha,sse2,ssse3,sse4.1")] +unsafe fn test_sha256msg1() { + let test_vectors = [ + ( + [0x6f6d6521, 0x61776573, 0x20697320, 0x52757374], + [0x6f6d6521, 0x61776573, 0x20697320, 0x52757374], + [0x2da4b536, 0x77f29328, 0x541a4d59, 0x6afb680c], + ), + ( + [0x6f6d6521, 0x61776573, 0x20697320, 0x52757374], + [0x6f6d6521, 0x61776573, 0x20697320, 0x52757374], + [0x2da4b536, 0x77f29328, 0x541a4d59, 0x6afb680c], + ), + ( + [0x6f6d6521, 0x61776573, 0x20697320, 0x52757374], + [0x6f6d6521, 0x61776573, 0x20697320, 0x52757374], + [0x2da4b536, 0x77f29328, 0x541a4d59, 0x6afb680c], + ), + ]; + for (v0, v1, expected) in test_vectors { + let output_reg = _mm_sha256msg1_epu32(set_arr(v0), set_arr(v1)); + let mut output = [0u32; 4]; + _mm_storeu_si128(output.as_mut_ptr().cast(), output_reg); + // The values are stored as little endian, so we need to reverse them + output.reverse(); + assert_eq!(output, expected); + } +} + +#[target_feature(enable = "sha,sse2,ssse3,sse4.1")] +unsafe fn test_sha256msg2() { + let test_vectors = [ + ( + [0x801a28aa, 0xe75ff849, 0xb591b2cc, 0x8b64db2c], + [0x6f6d6521, 0x61776573, 0x20697320, 0x52757374], + [0xe7c46c4e, 0x8ce92ccc, 0xd3c0f3ce, 0xe9745c78], + ), + ( + [0x171911ae, 0xe75ff849, 0xb591b2cc, 0x8b64db2c], + [0xe7c46c4e, 0x8ce92ccc, 0xd3c0f3ce, 0xe9745c78], + [0xc17c6ea3, 0xc4d10083, 0x712910cd, 0x3f41c8ce], + ), + ( + [0x6ce67e04, 0x5fb6ff76, 0xe1037a25, 0x3ebc5bda], + [0xc17c6ea3, 0xc4d10083, 0x712910cd, 0x3f41c8ce], + [0xf5ab4eff, 0x83d732a5, 0x9bb941af, 0xdf1d0a8c], + ), + ]; + for (v4, v3, expected) in test_vectors { + let output_reg = _mm_sha256msg2_epu32(set_arr(v4), set_arr(v3)); + let mut output = [0u32; 4]; + _mm_storeu_si128(output.as_mut_ptr().cast(), output_reg); + // The values are stored as little endian, so we need to reverse them + output.reverse(); + assert_eq!(output, expected); + } +} + +#[target_feature(enable = "sha,sse2,ssse3,sse4.1")] +unsafe fn set_arr(x: [u32; 4]) -> __m128i { + _mm_set_epi32(x[0] as i32, x[1] as i32, x[2] as i32, x[3] as i32) +} + +#[target_feature(enable = "sha,sse2,ssse3,sse4.1")] +unsafe fn test_sha256() { + use std::fmt::Write; + + /// The initial state of the hash engine. + const INITIAL_STATE: [u32; 8] = [ + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, + 0x5be0cd19, + ]; + + // We don't want to bother with hash finalization algorithm so we just feed constant data. + // This is the content that's being hashed - you can feed it to sha256sum and it'll output + // the same hash (beware of newlines though). + let first_block = *b"Rust is awesome!Rust is awesome!Rust is awesome!Rust is awesome!"; + // sha256 is fianlized by appending 0x80, then zeros and finally the data lenght at the + // end. + let mut final_block = [0; 64]; + final_block[0] = 0x80; + final_block[(64 - 8)..].copy_from_slice(&(8u64 * 64).to_be_bytes()); + + let mut state = INITIAL_STATE; + digest_blocks(&mut state, &[first_block, final_block]); + + // We compare strings because it's easier to check the hex and the output of panic. + let mut hash = String::new(); + for chunk in &state { + write!(hash, "{:08x}", chunk).expect("writing to String doesn't fail"); + } + assert_eq!(hash, "1b2293d21b17a0cb0c18737307c37333dea775eded18cefed45e50389f9f8184"); +} + +// Almost full SHA256 implementation copied from RustCrypto's sha2 crate +// https://github.com/RustCrypto/hashes/blob/6be8466247e936c415d8aafb848697f39894a386/sha2/src/sha256/x86.rs + +#[target_feature(enable = "sha,sse2,ssse3,sse4.1")] +unsafe fn schedule(v0: __m128i, v1: __m128i, v2: __m128i, v3: __m128i) -> __m128i { + let t1 = _mm_sha256msg1_epu32(v0, v1); + let t2 = _mm_alignr_epi8(v3, v2, 4); + let t3 = _mm_add_epi32(t1, t2); + _mm_sha256msg2_epu32(t3, v3) +} + +// we use unaligned loads with `__m128i` pointers +#[allow(clippy::cast_ptr_alignment)] +#[target_feature(enable = "sha,sse2,ssse3,sse4.1")] +unsafe fn digest_blocks(state: &mut [u32; 8], blocks: &[[u8; 64]]) { + #[allow(non_snake_case)] + let MASK: __m128i = + _mm_set_epi64x(0x0C0D_0E0F_0809_0A0Bu64 as i64, 0x0405_0607_0001_0203u64 as i64); + + let state_ptr: *const __m128i = state.as_ptr().cast(); + let dcba = _mm_loadu_si128(state_ptr.add(0)); + let efgh = _mm_loadu_si128(state_ptr.add(1)); + + let cdab = _mm_shuffle_epi32(dcba, 0xB1); + let efgh = _mm_shuffle_epi32(efgh, 0x1B); + let mut abef = _mm_alignr_epi8(cdab, efgh, 8); + let mut cdgh = _mm_blend_epi16(efgh, cdab, 0xF0); + + for block in blocks { + let abef_save = abef; + let cdgh_save = cdgh; + + let block_ptr: *const __m128i = block.as_ptr().cast(); + let mut w0 = _mm_shuffle_epi8(_mm_loadu_si128(block_ptr.add(0)), MASK); + let mut w1 = _mm_shuffle_epi8(_mm_loadu_si128(block_ptr.add(1)), MASK); + let mut w2 = _mm_shuffle_epi8(_mm_loadu_si128(block_ptr.add(2)), MASK); + let mut w3 = _mm_shuffle_epi8(_mm_loadu_si128(block_ptr.add(3)), MASK); + let mut w4; + + rounds4!(abef, cdgh, w0, 0); + rounds4!(abef, cdgh, w1, 1); + rounds4!(abef, cdgh, w2, 2); + rounds4!(abef, cdgh, w3, 3); + schedule_rounds4!(abef, cdgh, w0, w1, w2, w3, w4, 4); + schedule_rounds4!(abef, cdgh, w1, w2, w3, w4, w0, 5); + schedule_rounds4!(abef, cdgh, w2, w3, w4, w0, w1, 6); + schedule_rounds4!(abef, cdgh, w3, w4, w0, w1, w2, 7); + schedule_rounds4!(abef, cdgh, w4, w0, w1, w2, w3, 8); + schedule_rounds4!(abef, cdgh, w0, w1, w2, w3, w4, 9); + schedule_rounds4!(abef, cdgh, w1, w2, w3, w4, w0, 10); + schedule_rounds4!(abef, cdgh, w2, w3, w4, w0, w1, 11); + schedule_rounds4!(abef, cdgh, w3, w4, w0, w1, w2, 12); + schedule_rounds4!(abef, cdgh, w4, w0, w1, w2, w3, 13); + schedule_rounds4!(abef, cdgh, w0, w1, w2, w3, w4, 14); + schedule_rounds4!(abef, cdgh, w1, w2, w3, w4, w0, 15); + + abef = _mm_add_epi32(abef, abef_save); + cdgh = _mm_add_epi32(cdgh, cdgh_save); + } + + let feba = _mm_shuffle_epi32(abef, 0x1B); + let dchg = _mm_shuffle_epi32(cdgh, 0xB1); + let dcba = _mm_blend_epi16(feba, dchg, 0xF0); + let hgef = _mm_alignr_epi8(dchg, feba, 8); + + let state_ptr_mut: *mut __m128i = state.as_mut_ptr().cast(); + _mm_storeu_si128(state_ptr_mut.add(0), dcba); + _mm_storeu_si128(state_ptr_mut.add(1), hgef); +} + +/// Swapped round constants for SHA-256 family of digests +pub static K32X4: [[u32; 4]; 16] = { + let mut res = [[0u32; 4]; 16]; + let mut i = 0; + while i < 16 { + res[i] = [K32[4 * i + 3], K32[4 * i + 2], K32[4 * i + 1], K32[4 * i]]; + i += 1; + } + res +}; + +/// Round constants for SHA-256 family of digests +pub static K32: [u32; 64] = [ + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, +]; diff --git a/src/tools/miri/tests/pass/slices.rs b/src/tools/miri/tests/pass/slices.rs index 0b9805681b4..459d04d6761 100644 --- a/src/tools/miri/tests/pass/slices.rs +++ b/src/tools/miri/tests/pass/slices.rs @@ -1,7 +1,6 @@ //@revisions: stack tree //@[tree]compile-flags: -Zmiri-tree-borrows //@compile-flags: -Zmiri-strict-provenance -#![feature(new_uninit)] #![feature(slice_as_chunks)] #![feature(slice_partition_dedup)] #![feature(layout_for_ptr)] diff --git a/src/tools/miri/tests/pass/tls/tls_leak_main_thread_allowed.rs b/src/tools/miri/tests/pass/tls/tls_leak_main_thread_allowed.rs index 7732e3f9217..341b2280e01 100644 --- a/src/tools/miri/tests/pass/tls/tls_leak_main_thread_allowed.rs +++ b/src/tools/miri/tests/pass/tls/tls_leak_main_thread_allowed.rs @@ -1,5 +1,4 @@ -//@ignore-target-windows: Windows uses a different mechanism for `thread_local!` -#![feature(thread_local)] +#![feature(thread_local, cfg_target_thread_local)] use std::cell::Cell; @@ -8,16 +7,20 @@ use std::cell::Cell; // // The test covers both TLS statics and the TLS macro. pub fn main() { - thread_local! { - static TLS_KEY: Cell> = Cell::new(None); - } - - TLS_KEY.with(|cell| { - cell.set(Some(Box::leak(Box::new(123)))); - }); - #[thread_local] static TLS: Cell> = Cell::new(None); TLS.set(Some(Box::leak(Box::new(123)))); + + // We can only ignore leaks on targets that use `#[thread_local]` statics to implement + // `thread_local!`. Ignore the test on targest that don't. + if cfg!(target_thread_local) { + thread_local! { + static TLS_KEY: Cell> = Cell::new(None); + } + + TLS_KEY.with(|cell| { + cell.set(Some(Box::leak(Box::new(123)))); + }); + } } diff --git a/src/tools/miri/tests/pass/tree_borrows/cell-alternate-writes.stderr b/src/tools/miri/tests/pass/tree_borrows/cell-alternate-writes.stderr index 57caa09c888..d13e9ad0215 100644 --- a/src/tools/miri/tests/pass/tree_borrows/cell-alternate-writes.stderr +++ b/src/tools/miri/tests/pass/tree_borrows/cell-alternate-writes.stderr @@ -2,7 +2,7 @@ Warning: this tree is indicative only. Some tags may have been hidden. 0.. 1 | Act | └─┬── -| RsM | └──── +| ReIM| └──── ────────────────────────────────────────────────── ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. diff --git a/src/tools/miri/tests/pass/tree_borrows/end-of-protector.stderr b/src/tools/miri/tests/pass/tree_borrows/end-of-protector.stderr index 69b8a17dc5e..4d77d96776d 100644 --- a/src/tools/miri/tests/pass/tree_borrows/end-of-protector.stderr +++ b/src/tools/miri/tests/pass/tree_borrows/end-of-protector.stderr @@ -2,27 +2,27 @@ Warning: this tree is indicative only. Some tags may have been hidden. 0.. 1 | Act | └─┬── -| Rs | └─┬── -| Rs | └──── +| Res | └─┬── +| Res | └──── ────────────────────────────────────────────────── ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. 0.. 1 | Act | └─┬── -| Rs | └─┬── -| Rs | └─┬── -| Rs | └─┬── -| Rs | └──── Strongly protected +| Res | └─┬── +| Res | └─┬── +| Res | └─┬── +| Res | └──── Strongly protected ────────────────────────────────────────────────── ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. 0.. 1 | Act | └─┬── -| Rs | └─┬── -| Rs | ├─┬── -| Rs | │ └─┬── -| Rs | │ └──── -| Rs | └──── +| Res | └─┬── +| Res | ├─┬── +| Res | │ └─┬── +| Res | │ └──── +| Res | └──── ────────────────────────────────────────────────── ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. diff --git a/src/tools/miri/tests/pass/tree_borrows/formatting.stderr b/src/tools/miri/tests/pass/tree_borrows/formatting.stderr index 235ab68fe01..29f99034bab 100644 --- a/src/tools/miri/tests/pass/tree_borrows/formatting.stderr +++ b/src/tools/miri/tests/pass/tree_borrows/formatting.stderr @@ -2,7 +2,7 @@ Warning: this tree is indicative only. Some tags may have been hidden. 0.. 1.. 2.. 10.. 11.. 100.. 101..1000..1001..1024 | Act | Act | Act | Act | Act | Act | Act | Act | Act | └─┬── -| Rs | Act | Rs | Act | Rs | Act | Rs | Act | Rs | └─┬── +| Res | Act | Res | Act | Res | Act | Res | Act | Res | └─┬── |-----| Act |-----|?Dis |-----|?Dis |-----|?Dis |-----| ├──── |-----|-----|-----| Act |-----|?Dis |-----|?Dis |-----| ├──── |-----|-----|-----|-----|-----| Frz |-----|?Dis |-----| ├──── diff --git a/src/tools/miri/tests/pass/tree_borrows/reborrow-is-read.stderr b/src/tools/miri/tests/pass/tree_borrows/reborrow-is-read.stderr index f09aa52f1a1..d589a062111 100644 --- a/src/tools/miri/tests/pass/tree_borrows/reborrow-is-read.stderr +++ b/src/tools/miri/tests/pass/tree_borrows/reborrow-is-read.stderr @@ -11,5 +11,5 @@ Warning: this tree is indicative only. Some tags may have been hidden. | Act | └─┬── | Act | └─┬── | Frz | ├──── -| Rs | └──── +| Res | └──── ────────────────────────────────────────────────── diff --git a/src/tools/miri/tests/pass/tree_borrows/reserved.stderr b/src/tools/miri/tests/pass/tree_borrows/reserved.stderr index d149a4065f9..be90382640b 100644 --- a/src/tools/miri/tests/pass/tree_borrows/reserved.stderr +++ b/src/tools/miri/tests/pass/tree_borrows/reserved.stderr @@ -3,20 +3,20 @@ Warning: this tree is indicative only. Some tags may have been hidden. 0.. 1 | Act | └─┬── -| RsM | └─┬── -| RsM | ├─┬── -| RsM | │ └─┬── -| RsC | │ └──── -| RsM | └──── +| ReIM| └─┬── +| ReIM| ├─┬── +| ReIM| │ └─┬── +| ResC| │ └──── +| ReIM| └──── ────────────────────────────────────────────────── [interior mut] Foreign Read: Re* -> Re* ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. 0.. 8 | Act | └─┬── -| RsM | └─┬── -| RsM | ├──── -| RsM | └──── +| ReIM| └─┬── +| ReIM| ├──── +| ReIM| └──── ────────────────────────────────────────────────── [interior mut] Foreign Write: Re* -> Re* ────────────────────────────────────────────────── @@ -24,7 +24,7 @@ Warning: this tree is indicative only. Some tags may have been hidden. 0.. 8 | Act | └─┬── | Act | └─┬── -| RsM | ├──── +| ReIM| ├──── | Act | └──── ────────────────────────────────────────────────── [protected] Foreign Read: Res -> Frz @@ -32,20 +32,20 @@ Warning: this tree is indicative only. Some tags may have been hidden. Warning: this tree is indicative only. Some tags may have been hidden. 0.. 1 | Act | └─┬── -| Rs | └─┬── -| Rs | ├─┬── -| Rs | │ └─┬── -| RsC | │ └──── -| Rs | └──── +| Res | └─┬── +| Res | ├─┬── +| Res | │ └─┬── +| ResC| │ └──── +| Res | └──── ────────────────────────────────────────────────── [] Foreign Read: Res -> Res ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. 0.. 1 | Act | └─┬── -| Rs | └─┬── -| Rs | ├──── -| Rs | └──── +| Res | └─┬── +| Res | ├──── +| Res | └──── ────────────────────────────────────────────────── [] Foreign Write: Res -> Dis ────────────────────────────────────────────────── diff --git a/src/tools/miri/tests/pass/tree_borrows/unique.default.stderr b/src/tools/miri/tests/pass/tree_borrows/unique.default.stderr index 6e774e5014d..6098c855bde 100644 --- a/src/tools/miri/tests/pass/tree_borrows/unique.default.stderr +++ b/src/tools/miri/tests/pass/tree_borrows/unique.default.stderr @@ -2,8 +2,8 @@ Warning: this tree is indicative only. Some tags may have been hidden. 0.. 1 | Act | └─┬── -| Rs | └─┬── -| Rs | └──── +| Res | └─┬── +| Res | └──── ────────────────────────────────────────────────── ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. diff --git a/src/tools/miri/tests/pass/tree_borrows/unique.uniq.stderr b/src/tools/miri/tests/pass/tree_borrows/unique.uniq.stderr index 26d9ad2ad38..960c7e216e1 100644 --- a/src/tools/miri/tests/pass/tree_borrows/unique.uniq.stderr +++ b/src/tools/miri/tests/pass/tree_borrows/unique.uniq.stderr @@ -2,8 +2,8 @@ Warning: this tree is indicative only. Some tags may have been hidden. 0.. 1 | Act | └─┬── -| Rs | └─┬── -| Rs | └─┬── +| Res | └─┬── +| Res | └─┬── |-----| └──── ────────────────────────────────────────────────── ────────────────────────────────────────────────── diff --git a/src/tools/miri/tests/pass/tree_borrows/vec_unique.default.stderr b/src/tools/miri/tests/pass/tree_borrows/vec_unique.default.stderr index f63aa1f6834..254eba061f4 100644 --- a/src/tools/miri/tests/pass/tree_borrows/vec_unique.default.stderr +++ b/src/tools/miri/tests/pass/tree_borrows/vec_unique.default.stderr @@ -2,5 +2,5 @@ Warning: this tree is indicative only. Some tags may have been hidden. 0.. 2 | Act | └─┬── -| Rs | └──── +| Res | └──── ────────────────────────────────────────────────── diff --git a/src/tools/miri/tests/pass/tree_borrows/vec_unique.rs b/src/tools/miri/tests/pass/tree_borrows/vec_unique.rs index 9debe224d45..af4c3b06931 100644 --- a/src/tools/miri/tests/pass/tree_borrows/vec_unique.rs +++ b/src/tools/miri/tests/pass/tree_borrows/vec_unique.rs @@ -1,5 +1,3 @@ -// FIXME: This test is broken since https://github.com/rust-lang/rust/pull/126793, -// possibly related to the additional struct between Vec and Unique. //@revisions: default uniq // We disable the GC for this test because it would change what is printed. //@compile-flags: -Zmiri-tree-borrows -Zmiri-provenance-gc=0 @@ -32,20 +30,20 @@ fn main() { // whether we got the distance correct: // If the output shows // - // |- - // '- + // ├─ + // └─ // // then `nth_parent` is not big enough. // The correct value for `nth_parent` should be the minimum // integer for which the output shows // - // '- + // └─ // ) // // Ultimately we want pointers obtained through independent // calls of `as_ptr` to be able to alias, which will probably involve // a new permission that allows aliasing when there is no protector. - let nth_parent = if cfg!(uniq) { 2 } else { 0 }; + let nth_parent = if cfg!(uniq) { 9 } else { 0 }; name!(base.as_ptr()=>nth_parent); name!(base.as_ptr()=>nth_parent); diff --git a/src/tools/miri/tests/pass/tree_borrows/vec_unique.uniq.stderr b/src/tools/miri/tests/pass/tree_borrows/vec_unique.uniq.stderr index e3796a742e9..7942e9884f4 100644 --- a/src/tools/miri/tests/pass/tree_borrows/vec_unique.uniq.stderr +++ b/src/tools/miri/tests/pass/tree_borrows/vec_unique.uniq.stderr @@ -2,9 +2,7 @@ Warning: this tree is indicative only. Some tags may have been hidden. 0.. 2 | Act | └─┬── -|-----| ├──── -|-----| ├──── -|-----| └─┬── -|-----| ├──── -|-----| └──── +|-----| └─┬── +|-----| └─┬── +|-----| └──── ────────────────────────────────────────────────── diff --git a/src/tools/miri/tests/pass/weak_memory/weak.rs b/src/tools/miri/tests/pass/weak_memory/weak.rs index dac63eeeb0b..1b5c98cd518 100644 --- a/src/tools/miri/tests/pass/weak_memory/weak.rs +++ b/src/tools/miri/tests/pass/weak_memory/weak.rs @@ -18,11 +18,9 @@ struct EvilSend(pub T); unsafe impl Send for EvilSend {} unsafe impl Sync for EvilSend {} -// We can't create static items because we need to run each test -// multiple times +// We can't create static items because we need to run each test multiple times. fn static_atomic(val: usize) -> &'static AtomicUsize { - let ret = Box::leak(Box::new(AtomicUsize::new(val))); - ret + Box::leak(Box::new(AtomicUsize::new(val))) } // Spins until it reads the given value @@ -33,7 +31,7 @@ fn reads_value(loc: &AtomicUsize, val: usize) -> usize { val } -fn relaxed() -> bool { +fn relaxed(initial_read: bool) -> bool { let x = static_atomic(0); let j1 = spawn(move || { x.store(1, Relaxed); @@ -47,7 +45,9 @@ fn relaxed() -> bool { j1.join().unwrap(); let r2 = j2.join().unwrap(); - r2 == 1 + // There are three possible values here: 0 (from the initial read), 1 (from the first relaxed + // read), and 2 (the last read). The last case is boring and we cover the other two. + r2 == if initial_read { 0 } else { 1 } } // https://www.doc.ic.ac.uk/~afd/homepages/papers/pdfs/2017/POPL.pdf Figure 8 @@ -74,7 +74,6 @@ fn seq_cst() -> bool { fn initialization_write(add_fence: bool) -> bool { let x = static_atomic(11); - assert_eq!(x.load(Relaxed), 11); // work around https://github.com/rust-lang/miri/issues/2164 let wait = static_atomic(0); @@ -112,11 +111,8 @@ fn faa_replaced_by_load() -> bool { } let x = static_atomic(0); - assert_eq!(x.load(Relaxed), 0); // work around https://github.com/rust-lang/miri/issues/2164 let y = static_atomic(0); - assert_eq!(y.load(Relaxed), 0); // work around https://github.com/rust-lang/miri/issues/2164 let z = static_atomic(0); - assert_eq!(z.load(Relaxed), 0); // work around https://github.com/rust-lang/miri/issues/2164 // Since each thread is so short, we need to make sure that they truely run at the same time // Otherwise t1 will finish before t2 even starts @@ -146,7 +142,8 @@ fn assert_once(f: fn() -> bool) { } pub fn main() { - assert_once(relaxed); + assert_once(|| relaxed(false)); + assert_once(|| relaxed(true)); assert_once(seq_cst); assert_once(|| initialization_write(false)); assert_once(|| initialization_write(true)); diff --git a/src/tools/miri/tests/ui.rs b/src/tools/miri/tests/ui.rs index 95f8b054102..9cbcf6e42a7 100644 --- a/src/tools/miri/tests/ui.rs +++ b/src/tools/miri/tests/ui.rs @@ -13,7 +13,7 @@ use ui_test::{ }; fn miri_path() -> PathBuf { - PathBuf::from(option_env!("MIRI").unwrap_or(env!("CARGO_BIN_EXE_miri"))) + PathBuf::from(env::var("MIRI").unwrap_or_else(|_| env!("CARGO_BIN_EXE_miri").into())) } fn get_host() -> String { @@ -29,7 +29,7 @@ pub fn flagsplit(flags: &str) -> Vec { // Build the shared object file for testing native function calls. fn build_native_lib() -> PathBuf { - let cc = option_env!("CC").unwrap_or("cc"); + let cc = env::var("CC").unwrap_or_else(|_| "cc".into()); // Target directory that we can write to. let so_target_dir = Path::new(&env::var_os("CARGO_TARGET_DIR").unwrap()).join("miri-native-lib"); @@ -84,9 +84,11 @@ fn miri_config(target: &str, path: &str, mode: Mode, with_dependencies: bool) -> if with_dependencies { // Set the `cargo-miri` binary, which we expect to be in the same folder as the `miri` binary. // (It's a separate crate, so we don't get an env var from cargo.) - let mut prog = miri_path(); - prog.set_file_name("cargo-miri"); - config.dependency_builder.program = prog; + config.dependency_builder.program = { + let mut prog = miri_path(); + prog.set_file_name(format!("cargo-miri{}", env::consts::EXE_SUFFIX)); + prog + }; let builder_args = ["miri", "run"]; // There is no `cargo miri build` so we just use `cargo miri run`. config.dependency_builder.args = builder_args.into_iter().map(Into::into).collect(); config.dependencies_crate_manifest_path = diff --git a/src/tools/run-make-support/Cargo.toml b/src/tools/run-make-support/Cargo.toml index c4d5446a248..77df6e7beb5 100644 --- a/src/tools/run-make-support/Cargo.toml +++ b/src/tools/run-make-support/Cargo.toml @@ -7,7 +7,9 @@ edition = "2021" bstr = "1.6.0" object = "0.36.2" similar = "2.5.0" -wasmparser = { version = "0.214", default-features = false, features = ["std"] } +wasmparser = { version = "0.215", default-features = false, features = ["std"] } regex = "1.8" # 1.8 to avoid memchr 2.6.0, as 2.5.0 is pinned in the workspace gimli = "0.31.0" build_helper = { path = "../build_helper" } +serde_json = "1.0" +libc = "0.2" diff --git a/src/tools/run-make-support/src/assertion_helpers.rs b/src/tools/run-make-support/src/assertion_helpers.rs index 6d256fc594d..b4da65aff4a 100644 --- a/src/tools/run-make-support/src/assertion_helpers.rs +++ b/src/tools/run-make-support/src/assertion_helpers.rs @@ -77,6 +77,20 @@ pub fn assert_not_contains_regex, N: AsRef>(haystack: H, need } } +/// Assert that `haystack` contains `needle` a `count` number of times. +#[track_caller] +pub fn assert_count_is, N: AsRef>(count: usize, haystack: H, needle: N) { + let haystack = haystack.as_ref(); + let needle = needle.as_ref(); + if count != haystack.matches(needle).count() { + eprintln!("=== HAYSTACK ==="); + eprintln!("{}", haystack); + eprintln!("=== NEEDLE ==="); + eprintln!("{}", needle); + panic!("needle did not appear {count} times in haystack"); + } +} + /// Assert that all files in `dir1` exist and have the same content in `dir2` pub fn assert_dirs_are_equal(dir1: impl AsRef, dir2: impl AsRef) { let dir2 = dir2.as_ref(); diff --git a/src/tools/run-make-support/src/env.rs b/src/tools/run-make-support/src/env.rs index e6460fb93d3..9acbb16d73e 100644 --- a/src/tools/run-make-support/src/env.rs +++ b/src/tools/run-make-support/src/env.rs @@ -24,3 +24,11 @@ pub fn env_var_os(name: &str) -> OsString { pub fn no_debug_assertions() -> bool { std::env::var_os("NO_DEBUG_ASSERTIONS").is_some() } + +/// A wrapper around [`std::env::set_current_dir`] which includes the directory +/// path in the panic message. +#[track_caller] +pub fn set_current_dir>(dir: P) { + std::env::set_current_dir(dir.as_ref()) + .expect(&format!("could not set current directory to \"{}\"", dir.as_ref().display())); +} diff --git a/src/tools/run-make-support/src/external_deps/llvm.rs b/src/tools/run-make-support/src/external_deps/llvm.rs index dc651fdd820..e9315856cd7 100644 --- a/src/tools/run-make-support/src/external_deps/llvm.rs +++ b/src/tools/run-make-support/src/external_deps/llvm.rs @@ -48,6 +48,12 @@ pub fn llvm_bcanalyzer() -> LlvmBcanalyzer { LlvmBcanalyzer::new() } +/// Construct a new `llvm-dwarfdump` invocation. This assumes that `llvm-dwarfdump` is available +/// at `$LLVM_BIN_DIR/llvm-dwarfdump`. +pub fn llvm_dwarfdump() -> LlvmDwarfdump { + LlvmDwarfdump::new() +} + /// A `llvm-readobj` invocation builder. #[derive(Debug)] #[must_use] @@ -97,6 +103,13 @@ pub struct LlvmBcanalyzer { cmd: Command, } +/// A `llvm-dwarfdump` invocation builder. +#[derive(Debug)] +#[must_use] +pub struct LlvmDwarfdump { + cmd: Command, +} + crate::macros::impl_common_helpers!(LlvmReadobj); crate::macros::impl_common_helpers!(LlvmProfdata); crate::macros::impl_common_helpers!(LlvmFilecheck); @@ -104,6 +117,7 @@ crate::macros::impl_common_helpers!(LlvmObjdump); crate::macros::impl_common_helpers!(LlvmAr); crate::macros::impl_common_helpers!(LlvmNm); crate::macros::impl_common_helpers!(LlvmBcanalyzer); +crate::macros::impl_common_helpers!(LlvmDwarfdump); /// Generate the path to the bin directory of LLVM. #[must_use] @@ -271,12 +285,24 @@ impl LlvmAr { self } + /// Like `obj_to_ar` except creating a thin archive. + pub fn obj_to_thin_ar(&mut self) -> &mut Self { + self.cmd.arg("rcus").arg("--thin"); + self + } + /// Extract archive members back to files. pub fn extract(&mut self) -> &mut Self { self.cmd.arg("x"); self } + /// Print the table of contents. + pub fn table_of_contents(&mut self) -> &mut Self { + self.cmd.arg("t"); + self + } + /// Provide an output, then an input file. Bundled in one function, as llvm-ar has /// no "--output"-style flag. pub fn output_input(&mut self, out: impl AsRef, input: impl AsRef) -> &mut Self { @@ -317,3 +343,19 @@ impl LlvmBcanalyzer { self } } + +impl LlvmDwarfdump { + /// Construct a new `llvm-dwarfdump` invocation. This assumes that `llvm-dwarfdump` is available + /// at `$LLVM_BIN_DIR/llvm-dwarfdump`. + pub fn new() -> Self { + let llvm_dwarfdump = llvm_bin_dir().join("llvm-dwarfdump"); + let cmd = Command::new(llvm_dwarfdump); + Self { cmd } + } + + /// Provide an input file. + pub fn input>(&mut self, path: P) -> &mut Self { + self.cmd.arg(path.as_ref()); + self + } +} diff --git a/src/tools/run-make-support/src/external_deps/rustdoc.rs b/src/tools/run-make-support/src/external_deps/rustdoc.rs index 96c2218a563..96b1c719e2e 100644 --- a/src/tools/run-make-support/src/external_deps/rustdoc.rs +++ b/src/tools/run-make-support/src/external_deps/rustdoc.rs @@ -71,14 +71,8 @@ impl Rustdoc { self } - /// Specify path to the output folder. - pub fn output>(&mut self, path: P) -> &mut Self { - self.cmd.arg("-o"); - self.cmd.arg(path.as_ref()); - self - } - /// Specify output directory. + #[doc(alias = "output")] pub fn out_dir>(&mut self, path: P) -> &mut Self { self.cmd.arg("--out-dir").arg(path.as_ref()); self diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index a44dd00ad79..989d00d4c2f 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -36,8 +36,10 @@ pub mod rfs { // Re-exports of third-party library crates. pub use bstr; pub use gimli; +pub use libc; pub use object; pub use regex; +pub use serde_json; pub use wasmparser; // Re-exports of external dependencies. @@ -49,8 +51,9 @@ pub use c_build::{build_native_dynamic_lib, build_native_static_lib, build_nativ pub use clang::{clang, Clang}; pub use htmldocck::htmldocck; pub use llvm::{ - llvm_ar, llvm_bcanalyzer, llvm_filecheck, llvm_nm, llvm_objdump, llvm_profdata, llvm_readobj, - LlvmAr, LlvmBcanalyzer, LlvmFilecheck, LlvmNm, LlvmObjdump, LlvmProfdata, LlvmReadobj, + llvm_ar, llvm_bcanalyzer, llvm_dwarfdump, llvm_filecheck, llvm_nm, llvm_objdump, llvm_profdata, + llvm_readobj, LlvmAr, LlvmBcanalyzer, LlvmDwarfdump, LlvmFilecheck, LlvmNm, LlvmObjdump, + LlvmProfdata, LlvmReadobj, }; pub use python::python_command; pub use rustc::{aux_build, bare_rustc, rustc, Rustc}; @@ -62,7 +65,7 @@ pub use rustdoc::{bare_rustdoc, rustdoc, Rustdoc}; pub use diff::{diff, Diff}; /// Panic-on-fail [`std::env::var`] and [`std::env::var_os`] wrappers. -pub use env::{env_var, env_var_os}; +pub use env::{env_var, env_var_os, set_current_dir}; /// Convenience helpers for running binaries and other commands. pub use run::{cmd, run, run_fail, run_with_args}; @@ -86,7 +89,7 @@ pub use path_helpers::{ pub use scoped_run::{run_in_tmpdir, test_while_readonly}; pub use assertion_helpers::{ - assert_contains, assert_contains_regex, assert_dirs_are_equal, assert_equals, + assert_contains, assert_contains_regex, assert_count_is, assert_dirs_are_equal, assert_equals, assert_not_contains, assert_not_contains_regex, }; diff --git a/src/tools/run-make-support/src/path_helpers.rs b/src/tools/run-make-support/src/path_helpers.rs index b788bc6ef30..87901793a92 100644 --- a/src/tools/run-make-support/src/path_helpers.rs +++ b/src/tools/run-make-support/src/path_helpers.rs @@ -21,6 +21,7 @@ pub fn cwd() -> PathBuf { /// # Example /// /// ```rust +/// # use run_make_support::path; /// let p = path("support_file.txt"); /// ``` pub fn path>(p: P) -> PathBuf { @@ -84,3 +85,18 @@ pub fn has_suffix>(path: P, suffix: &str) -> bool { pub fn filename_contains>(path: P, needle: &str) -> bool { path.as_ref().file_name().is_some_and(|name| name.to_str().unwrap().contains(needle)) } + +/// Helper for reading entries in a given directory and its children. +pub fn read_dir_entries_recursive, F: FnMut(&Path)>(dir: P, mut callback: F) { + fn read_dir_entries_recursive_inner, F: FnMut(&Path)>(dir: P, callback: &mut F) { + for entry in rfs::read_dir(dir) { + let path = entry.unwrap().path(); + callback(&path); + if path.is_dir() { + read_dir_entries_recursive_inner(path, callback); + } + } + } + + read_dir_entries_recursive_inner(dir, &mut callback); +} diff --git a/src/tools/run-make-support/src/run.rs b/src/tools/run-make-support/src/run.rs index 12088e5d3b5..3eeba6fd526 100644 --- a/src/tools/run-make-support/src/run.rs +++ b/src/tools/run-make-support/src/run.rs @@ -29,6 +29,7 @@ fn run_common(name: &str, args: Option<&[&str]>) -> Command { } env::join_paths(paths.iter()).unwrap() }); + cmd.env("LC_ALL", "C"); // force english locale if is_windows() { let mut paths = vec![]; @@ -84,5 +85,6 @@ pub fn run_fail(name: &str) -> CompletedProcess { pub fn cmd>(program: S) -> Command { let mut command = Command::new(program); set_host_rpath(&mut command); + command.env("LC_ALL", "C"); // force english locale command } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs index 46611ae0de9..2f4e764f4ce 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs @@ -15,8 +15,10 @@ extern crate rustc_abi; #[cfg(not(feature = "in-rust-tree"))] extern crate ra_ap_rustc_abi as rustc_abi; -// Use the crates.io version unconditionally until the API settles enough that we can switch to -// using the in-tree one. +#[cfg(feature = "in-rust-tree")] +extern crate rustc_pattern_analysis; + +#[cfg(not(feature = "in-rust-tree"))] extern crate ra_ap_rustc_pattern_analysis as rustc_pattern_analysis; mod builder; diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock index df051ed447e..1394675a9dc 100644 --- a/src/tools/rustbook/Cargo.lock +++ b/src/tools/rustbook/Cargo.lock @@ -303,6 +303,12 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + [[package]] name = "elasticlunr-rs" version = "3.0.2" @@ -465,6 +471,21 @@ dependencies = [ "syn", ] +[[package]] +name = "html_parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f56db07b6612644f6f7719f8ef944f75fff9d6378fdf3d316fd32194184abd" +dependencies = [ + "doc-comment", + "pest", + "pest_derive", + "serde", + "serde_derive", + "serde_json", + "thiserror", +] + [[package]] name = "humantime" version = "2.1.0" @@ -669,6 +690,7 @@ dependencies = [ "mdbook", "once_cell", "pathdiff", + "pulldown-cmark", "regex", "semver", "serde_json", @@ -680,13 +702,13 @@ name = "mdbook-trpl-listing" version = "0.1.0" dependencies = [ "clap", + "html_parser", "mdbook", "pulldown-cmark", "pulldown-cmark-to-cmark", "serde_json", "thiserror", "toml 0.8.14", - "xmlparser", ] [[package]] @@ -1767,12 +1789,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "xmlparser" -version = "0.13.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4" - [[package]] name = "yaml-rust" version = "0.4.5" diff --git a/src/tools/rustfmt/src/parse/macros/mod.rs b/src/tools/rustfmt/src/parse/macros/mod.rs index 60c827fd03b..8d5f7f90958 100644 --- a/src/tools/rustfmt/src/parse/macros/mod.rs +++ b/src/tools/rustfmt/src/parse/macros/mod.rs @@ -84,9 +84,7 @@ pub(crate) struct ParsedMacroArgs { fn check_keyword<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { for &keyword in RUST_KW.iter() { if parser.token.is_keyword(keyword) - && parser.look_ahead(1, |t| { - t.kind == TokenKind::Eof || t.kind == TokenKind::Comma - }) + && parser.look_ahead(1, |t| *t == TokenKind::Eof || *t == TokenKind::Comma) { parser.bump(); return Some(MacroArg::Keyword( @@ -131,7 +129,7 @@ pub(crate) fn parse_macro_args( Some(arg) => { args.push(arg); parser.bump(); - if parser.token.kind == TokenKind::Eof && args.len() == 2 { + if parser.token == TokenKind::Eof && args.len() == 2 { vec_with_semi = true; break; } @@ -150,7 +148,7 @@ pub(crate) fn parse_macro_args( parser.bump(); - if parser.token.kind == TokenKind::Eof { + if parser.token == TokenKind::Eof { trailing_comma = true; break; } diff --git a/src/tools/rustfmt/tests/target/unsafe_attributes.rs b/src/tools/rustfmt/tests/target/unsafe_attributes.rs index a05bedc751a..d79c56f2147 100644 --- a/src/tools/rustfmt/tests/target/unsafe_attributes.rs +++ b/src/tools/rustfmt/tests/target/unsafe_attributes.rs @@ -1,4 +1,3 @@ -#![feature(unsafe_attributes)] // https://github.com/rust-lang/rust/issues/123757 // #![simple_ident] diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 14f0a9cd23d..22d1e93bf39 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -1,26 +1,12 @@ run-make/branch-protection-check-IBT/Makefile run-make/cat-and-grep-sanity-check/Makefile -run-make/dep-info-doesnt-run-much/Makefile -run-make/dep-info-spaces/Makefile -run-make/dep-info/Makefile run-make/emit-to-stdout/Makefile run-make/extern-fn-reachable/Makefile run-make/incr-add-rust-src-component/Makefile run-make/issue-84395-lto-embed-bitcode/Makefile run-make/jobserver-error/Makefile run-make/libs-through-symlinks/Makefile -run-make/libtest-json/Makefile -run-make/libtest-junit/Makefile -run-make/libtest-thread-limit/Makefile run-make/macos-deployment-target/Makefile -run-make/min-global-align/Makefile -run-make/native-link-modifier-bundle/Makefile -run-make/no-alloc-shim/Makefile -run-make/remap-path-prefix-dwarf/Makefile -run-make/reproducible-build/Makefile -run-make/rlib-format-packed-bundled-libs/Makefile run-make/split-debuginfo/Makefile run-make/symbol-mangling-hashed/Makefile -run-make/sysroot-crates-are-unstable/Makefile run-make/translation/Makefile -run-make/x86_64-fortanix-unknown-sgx-lvi/Makefile diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 89011bbb48f..28367f25267 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -98,13 +98,7 @@ const EXCEPTIONS: ExceptionList = &[ ("ryu", "Apache-2.0 OR BSL-1.0"), // BSL is not acceptble, but we use it under Apache-2.0 // cargo/... (because of serde) ("self_cell", "Apache-2.0"), // rustc (fluent translations) ("snap", "BSD-3-Clause"), // rustc - ("wasm-encoder", "Apache-2.0 WITH LLVM-exception"), // rustc - ("wasm-metadata", "Apache-2.0 WITH LLVM-exception"), // rustc - ("wasmparser", "Apache-2.0 WITH LLVM-exception"), // rustc - ("wast", "Apache-2.0 WITH LLVM-exception"), // rustc - ("wat", "Apache-2.0 WITH LLVM-exception"), // rustc - ("wit-component", "Apache-2.0 WITH LLVM-exception"), // rustc - ("wit-parser", "Apache-2.0 WITH LLVM-exception"), // rustc + ("wasi-preview1-component-adapter-provider", "Apache-2.0 WITH LLVM-exception"), // rustc // tidy-alphabetical-end ]; diff --git a/src/tools/tidy/src/edition.rs b/src/tools/tidy/src/edition.rs index 6a58d58dbde..08f6a3909f8 100644 --- a/src/tools/tidy/src/edition.rs +++ b/src/tools/tidy/src/edition.rs @@ -1,4 +1,4 @@ -//! Tidy check to ensure that crate `edition` is '2018' or '2021'. +//! Tidy check to ensure that crate `edition` is '2021' or '2024'. use std::path::Path; @@ -12,7 +12,9 @@ pub fn check(path: &Path, bad: &mut bool) { return; } - let is_2021 = contents.lines().any(|line| line.trim() == "edition = \"2021\""); + let is_current_edition = contents + .lines() + .any(|line| line.trim() == "edition = \"2021\"" || line.trim() == "edition = \"2024\""); let is_workspace = contents.lines().any(|line| line.trim() == "[workspace]"); let is_package = contents.lines().any(|line| line.trim() == "[package]"); @@ -20,10 +22,10 @@ pub fn check(path: &Path, bad: &mut bool) { // Check that all packages use the 2021 edition. Virtual workspaces don't allow setting an // edition, so these shouldn't be checked. - if is_package && !is_2021 { + if is_package && !is_current_edition { tidy_error!( bad, - "{} doesn't have `edition = \"2021\"` on a separate line", + "{} doesn't have `edition = \"2021\"` or `edition = \"2024\"` on a separate line", file.display() ); } diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index 57310977704..5205fa14294 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -1289,8 +1289,7 @@ ui/imports/auxiliary/issue-52891.rs ui/imports/auxiliary/issue-55811.rs ui/imports/auxiliary/issue-56125.rs ui/imports/auxiliary/issue-59764.rs -ui/imports/auxiliary/issue-85992-extern-1.rs -ui/imports/auxiliary/issue-85992-extern-2.rs +ui/imports/auxiliary/issue-85992-extern.rs ui/imports/issue-109148.rs ui/imports/issue-109343.rs ui/imports/issue-113953.rs diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs index b7ddf47186d..c650fd0eec6 100644 --- a/src/tools/tidy/src/pal.rs +++ b/src/tools/tidy/src/pal.rs @@ -36,6 +36,7 @@ use crate::walk::{filter_dirs, walk}; // Paths that may contain platform-specific code. const EXCEPTION_PATHS: &[&str] = &[ + "library/windows_targets", "library/panic_abort", "library/panic_unwind", "library/unwind", diff --git a/tests/assembly/asm/aarch64-types.rs b/tests/assembly/asm/aarch64-types.rs index 3e2a4773703..f36345670e3 100644 --- a/tests/assembly/asm/aarch64-types.rs +++ b/tests/assembly/asm/aarch64-types.rs @@ -5,10 +5,12 @@ //@ [arm64ec] compile-flags: --target arm64ec-pc-windows-msvc //@ [arm64ec] needs-llvm-components: aarch64 -#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)] +#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch, f16, f128)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register, non_camel_case_types)] +// FIXME(f16_f128): Only needed for FIXME in check! and check_reg! +#![feature(auto_traits)] #[rustc_builtin_macro] macro_rules! asm { @@ -39,6 +41,8 @@ pub struct i32x2(i32, i32); #[repr(simd)] pub struct i64x1(i64); #[repr(simd)] +pub struct f16x4(f16, f16, f16, f16); +#[repr(simd)] pub struct f32x2(f32, f32); #[repr(simd)] pub struct f64x1(f64); @@ -51,30 +55,42 @@ pub struct i32x4(i32, i32, i32, i32); #[repr(simd)] pub struct i64x2(i64, i64); #[repr(simd)] +pub struct f16x8(f16, f16, f16, f16, f16, f16, f16, f16); +#[repr(simd)] pub struct f32x4(f32, f32, f32, f32); #[repr(simd)] pub struct f64x2(f64, f64); impl Copy for i8 {} impl Copy for i16 {} +impl Copy for f16 {} impl Copy for i32 {} impl Copy for f32 {} impl Copy for i64 {} impl Copy for f64 {} +impl Copy for f128 {} impl Copy for ptr {} impl Copy for i8x8 {} impl Copy for i16x4 {} impl Copy for i32x2 {} impl Copy for i64x1 {} +impl Copy for f16x4 {} impl Copy for f32x2 {} impl Copy for f64x1 {} impl Copy for i8x16 {} impl Copy for i16x8 {} impl Copy for i32x4 {} impl Copy for i64x2 {} +impl Copy for f16x8 {} impl Copy for f32x4 {} impl Copy for f64x2 {} +// FIXME(f16_f128): Only needed for FIXME in check! and check_reg! +#[lang = "freeze"] +unsafe auto trait Freeze {} +#[lang = "unpin"] +auto trait Unpin {} + extern "C" { fn extern_func(); static extern_static: u8; @@ -111,38 +127,44 @@ pub unsafe fn issue_75761() { macro_rules! check { ($func:ident $ty:ident $class:ident $mov:literal $modifier:literal) => { + // FIXME(f16_f128): Change back to `$func(x: $ty) -> $ty` once arm64ec can pass and return + // `f16` and `f128` without LLVM erroring. + // LLVM issue: #[no_mangle] - pub unsafe fn $func(x: $ty) -> $ty { + pub unsafe fn $func(inp: &$ty, out: &mut $ty) { // Hack to avoid function merging extern "Rust" { fn dont_merge(s: &str); } dont_merge(stringify!($func)); + let x = *inp; let y; asm!( concat!($mov, " {:", $modifier, "}, {:", $modifier, "}"), out($class) y, in($class) x ); - y + *out = y; } }; } macro_rules! check_reg { ($func:ident $ty:ident $reg:tt $mov:literal) => { + // FIXME(f16_f128): See FIXME in `check!` #[no_mangle] - pub unsafe fn $func(x: $ty) -> $ty { + pub unsafe fn $func(inp: &$ty, out: &mut $ty) { // Hack to avoid function merging extern "Rust" { fn dont_merge(s: &str); } dont_merge(stringify!($func)); + let x = *inp; let y; asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x); - y + *out = y; } }; } @@ -159,6 +181,12 @@ check!(reg_i8 i8 reg "mov" ""); // CHECK: //NO_APP check!(reg_i16 i16 reg "mov" ""); +// CHECK-LABEL: {{("#)?}}reg_f16{{"?}} +// CHECK: //APP +// CHECK: mov x{{[0-9]+}}, x{{[0-9]+}} +// CHECK: //NO_APP +check!(reg_f16 f16 reg "mov" ""); + // CHECK-LABEL: {{("#)?}}reg_i32{{"?}} // CHECK: //APP // CHECK: mov x{{[0-9]+}}, x{{[0-9]+}} @@ -201,6 +229,12 @@ check!(vreg_i8 i8 vreg "fmov" "s"); // CHECK: //NO_APP check!(vreg_i16 i16 vreg "fmov" "s"); +// CHECK-LABEL: {{("#)?}}vreg_f16{{"?}} +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_f16 f16 vreg "fmov" "s"); + // CHECK-LABEL: {{("#)?}}vreg_i32{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} @@ -225,6 +259,12 @@ check!(vreg_i64 i64 vreg "fmov" "s"); // CHECK: //NO_APP check!(vreg_f64 f64 vreg "fmov" "s"); +// CHECK-LABEL: {{("#)?}}vreg_f128{{"?}} +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_f128 f128 vreg "fmov" "s"); + // CHECK-LABEL: {{("#)?}}vreg_ptr{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} @@ -255,6 +295,12 @@ check!(vreg_i32x2 i32x2 vreg "fmov" "s"); // CHECK: //NO_APP check!(vreg_i64x1 i64x1 vreg "fmov" "s"); +// CHECK-LABEL: {{("#)?}}vreg_f16x4{{"?}} +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_f16x4 f16x4 vreg "fmov" "s"); + // CHECK-LABEL: {{("#)?}}vreg_f32x2{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} @@ -291,6 +337,12 @@ check!(vreg_i32x4 i32x4 vreg "fmov" "s"); // CHECK: //NO_APP check!(vreg_i64x2 i64x2 vreg "fmov" "s"); +// CHECK-LABEL: {{("#)?}}vreg_f16x8{{"?}} +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_f16x8 f16x8 vreg "fmov" "s"); + // CHECK-LABEL: {{("#)?}}vreg_f32x4{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} @@ -315,6 +367,12 @@ check!(vreg_low16_i8 i8 vreg_low16 "fmov" "s"); // CHECK: //NO_APP check!(vreg_low16_i16 i16 vreg_low16 "fmov" "s"); +// CHECK-LABEL: {{("#)?}}vreg_low16_f16{{"?}} +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_low16_f16 f16 vreg_low16 "fmov" "s"); + // CHECK-LABEL: {{("#)?}}vreg_low16_f32{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} @@ -333,6 +391,12 @@ check!(vreg_low16_i64 i64 vreg_low16 "fmov" "s"); // CHECK: //NO_APP check!(vreg_low16_f64 f64 vreg_low16 "fmov" "s"); +// CHECK-LABEL: {{("#)?}}vreg_low16_f128{{"?}} +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_low16_f128 f128 vreg_low16 "fmov" "s"); + // CHECK-LABEL: {{("#)?}}vreg_low16_ptr{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} @@ -363,6 +427,12 @@ check!(vreg_low16_i32x2 i32x2 vreg_low16 "fmov" "s"); // CHECK: //NO_APP check!(vreg_low16_i64x1 i64x1 vreg_low16 "fmov" "s"); +// CHECK-LABEL: {{("#)?}}vreg_low16_f16x4{{"?}} +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_low16_f16x4 f16x4 vreg_low16 "fmov" "s"); + // CHECK-LABEL: {{("#)?}}vreg_low16_f32x2{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} @@ -399,6 +469,12 @@ check!(vreg_low16_i32x4 i32x4 vreg_low16 "fmov" "s"); // CHECK: //NO_APP check!(vreg_low16_i64x2 i64x2 vreg_low16 "fmov" "s"); +// CHECK-LABEL: {{("#)?}}vreg_low16_f16x8{{"?}} +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_low16_f16x8 f16x8 vreg_low16 "fmov" "s"); + // CHECK-LABEL: {{("#)?}}vreg_low16_f32x4{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} @@ -423,6 +499,12 @@ check_reg!(x0_i8 i8 "x0" "mov"); // CHECK: //NO_APP check_reg!(x0_i16 i16 "x0" "mov"); +// CHECK-LABEL: {{("#)?}}x0_f16{{"?}} +// CHECK: //APP +// CHECK: mov x{{[0-9]+}}, x{{[0-9]+}} +// CHECK: //NO_APP +check_reg!(x0_f16 f16 "x0" "mov"); + // CHECK-LABEL: {{("#)?}}x0_i32{{"?}} // CHECK: //APP // CHECK: mov x{{[0-9]+}}, x{{[0-9]+}} @@ -465,6 +547,12 @@ check_reg!(v0_i8 i8 "s0" "fmov"); // CHECK: //NO_APP check_reg!(v0_i16 i16 "s0" "fmov"); +// CHECK-LABEL: {{("#)?}}v0_f16{{"?}} +// CHECK: //APP +// CHECK: fmov s0, s0 +// CHECK: //NO_APP +check_reg!(v0_f16 f16 "s0" "fmov"); + // CHECK-LABEL: {{("#)?}}v0_i32{{"?}} // CHECK: //APP // CHECK: fmov s0, s0 @@ -489,6 +577,12 @@ check_reg!(v0_i64 i64 "s0" "fmov"); // CHECK: //NO_APP check_reg!(v0_f64 f64 "s0" "fmov"); +// CHECK-LABEL: {{("#)?}}v0_f128{{"?}} +// CHECK: //APP +// CHECK: fmov s0, s0 +// CHECK: //NO_APP +check_reg!(v0_f128 f128 "s0" "fmov"); + // CHECK-LABEL: {{("#)?}}v0_ptr{{"?}} // CHECK: //APP // CHECK: fmov s0, s0 @@ -519,6 +613,12 @@ check_reg!(v0_i32x2 i32x2 "s0" "fmov"); // CHECK: //NO_APP check_reg!(v0_i64x1 i64x1 "s0" "fmov"); +// CHECK-LABEL: {{("#)?}}v0_f16x4{{"?}} +// CHECK: //APP +// CHECK: fmov s0, s0 +// CHECK: //NO_APP +check_reg!(v0_f16x4 f16x4 "s0" "fmov"); + // CHECK-LABEL: {{("#)?}}v0_f32x2{{"?}} // CHECK: //APP // CHECK: fmov s0, s0 @@ -555,6 +655,12 @@ check_reg!(v0_i32x4 i32x4 "s0" "fmov"); // CHECK: //NO_APP check_reg!(v0_i64x2 i64x2 "s0" "fmov"); +// CHECK-LABEL: {{("#)?}}v0_f16x8{{"?}} +// CHECK: //APP +// CHECK: fmov s0, s0 +// CHECK: //NO_APP +check_reg!(v0_f16x8 f16x8 "s0" "fmov"); + // CHECK-LABEL: {{("#)?}}v0_f32x4{{"?}} // CHECK: //APP // CHECK: fmov s0, s0 diff --git a/tests/assembly/asm/global_asm.rs b/tests/assembly/asm/global_asm.rs index 22cf4bdb15b..8a4bf98c745 100644 --- a/tests/assembly/asm/global_asm.rs +++ b/tests/assembly/asm/global_asm.rs @@ -4,7 +4,6 @@ //@ compile-flags: -C llvm-args=--x86-asm-syntax=intel //@ compile-flags: -C symbol-mangling-version=v0 -#![feature(asm_const)] #![crate_type = "rlib"] use std::arch::global_asm; diff --git a/tests/assembly/asm/msp430-types.rs b/tests/assembly/asm/msp430-types.rs index 4f51d4020a6..ae09b8b070d 100644 --- a/tests/assembly/asm/msp430-types.rs +++ b/tests/assembly/asm/msp430-types.rs @@ -2,7 +2,7 @@ //@ compile-flags: --target msp430-none-elf //@ needs-llvm-components: msp430 -#![feature(no_core, lang_items, rustc_attrs, asm_experimental_arch, asm_const)] +#![feature(no_core, lang_items, rustc_attrs, asm_experimental_arch)] #![crate_type = "rlib"] #![no_core] #![allow(non_camel_case_types)] diff --git a/tests/assembly/struct-target-features.rs b/tests/assembly/struct-target-features.rs new file mode 100644 index 00000000000..cc86fbaa840 --- /dev/null +++ b/tests/assembly/struct-target-features.rs @@ -0,0 +1,37 @@ +//@ compile-flags: -O +//@ assembly-output: emit-asm +//@ only-x86_64 + +#![crate_type = "lib"] +#![feature(struct_target_features)] + +// Check that a struct_target_features type causes the compiler to effectively inline intrinsics. + +use std::arch::x86_64::*; + +#[target_feature(enable = "avx")] +struct Avx {} + +#[target_feature(enable = "fma")] +struct Fma {} + +pub fn add_simple(_: Avx, v: __m256) -> __m256 { + // CHECK-NOT: call + // CHECK: vaddps + unsafe { _mm256_add_ps(v, v) } +} + +pub fn add_complex_type(_: (&Avx, ()), v: __m256) -> __m256 { + // CHECK-NOT: call + // CHECK: vaddps + unsafe { _mm256_add_ps(v, v) } +} + +pub fn add_fma_combined(_: (&Avx, &Fma), v: __m256) -> (__m256, __m256) { + // CHECK-NOT: call + // CHECK-DAG: vaddps + let r1 = unsafe { _mm256_add_ps(v, v) }; + // CHECK-DAG: vfmadd213ps + let r2 = unsafe { _mm256_fmadd_ps(v, v, v) }; + (r1, r2) +} diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs index 762df40a44b..6f0a200a08c 100644 --- a/tests/assembly/targets/targets-elf.rs +++ b/tests/assembly/targets/targets-elf.rs @@ -66,6 +66,9 @@ //@ revisions: aarch64_unknown_teeos //@ [aarch64_unknown_teeos] compile-flags: --target aarch64-unknown-teeos //@ [aarch64_unknown_teeos] needs-llvm-components: aarch64 +//@ revisions: aarch64_unknown_trusty +//@ [aarch64_unknown_trusty] compile-flags: --target aarch64-unknown-trusty +//@ [aarch64_unknown_trusty] needs-llvm-components: aarch64 //@ revisions: aarch64_wrs_vxworks //@ [aarch64_wrs_vxworks] compile-flags: --target aarch64-wrs-vxworks //@ [aarch64_wrs_vxworks] needs-llvm-components: aarch64 @@ -153,6 +156,9 @@ //@ revisions: armv7_unknown_netbsd_eabihf //@ [armv7_unknown_netbsd_eabihf] compile-flags: --target armv7-unknown-netbsd-eabihf //@ [armv7_unknown_netbsd_eabihf] needs-llvm-components: arm +//@ revisions: armv7_unknown_trusty +//@ [armv7_unknown_trusty] compile-flags: --target armv7-unknown-trusty +//@ [armv7_unknown_trusty] needs-llvm-components: arm //@ revisions: armv7_wrs_vxworks_eabihf //@ [armv7_wrs_vxworks_eabihf] compile-flags: --target armv7-wrs-vxworks-eabihf //@ [armv7_wrs_vxworks_eabihf] needs-llvm-components: arm @@ -345,6 +351,9 @@ //@ revisions: powerpc_unknown_linux_musl //@ [powerpc_unknown_linux_musl] compile-flags: --target powerpc-unknown-linux-musl //@ [powerpc_unknown_linux_musl] needs-llvm-components: powerpc +//@ revisions: powerpc_unknown_linux_muslspe +//@ [powerpc_unknown_linux_muslspe] compile-flags: --target powerpc-unknown-linux-muslspe +//@ [powerpc_unknown_linux_muslspe] needs-llvm-components: powerpc //@ revisions: powerpc_unknown_netbsd //@ [powerpc_unknown_netbsd] compile-flags: --target powerpc-unknown-netbsd //@ [powerpc_unknown_netbsd] needs-llvm-components: powerpc diff --git a/tests/assembly/x86_64-cmp.rs b/tests/assembly/x86_64-cmp.rs index 31efdda1bfa..67b7ff99ae2 100644 --- a/tests/assembly/x86_64-cmp.rs +++ b/tests/assembly/x86_64-cmp.rs @@ -1,6 +1,9 @@ -//@ revisions: DEBUG OPTIM +//@ revisions: DEBUG LLVM-PRE-20-OPTIM LLVM-20-OPTIM //@ [DEBUG] compile-flags: -C opt-level=0 -//@ [OPTIM] compile-flags: -C opt-level=3 +//@ [LLVM-PRE-20-OPTIM] compile-flags: -C opt-level=3 +//@ [LLVM-PRE-20-OPTIM] ignore-llvm-version: 20 - 99 +//@ [LLVM-20-OPTIM] compile-flags: -C opt-level=3 +//@ [LLVM-20-OPTIM] min-llvm-version: 20 //@ assembly-output: emit-asm //@ compile-flags: --crate-type=lib -C llvm-args=-x86-asm-syntax=intel //@ only-x86_64 @@ -21,12 +24,18 @@ pub fn signed_cmp(a: i16, b: i16) -> std::cmp::Ordering { // DEBUG: and // DEBUG: sub - // OPTIM: xor - // OPTIM: cmp - // OPTIM: setne - // OPTIM: mov - // OPTIM: cmovge - // OPTIM: ret + // LLVM-PRE-20-OPTIM: xor + // LLVM-PRE-20-OPTIM: cmp + // LLVM-PRE-20-OPTIM: setne + // LLVM-PRE-20-OPTIM: mov + // LLVM-PRE-20-OPTIM: cmovge + // LLVM-PRE-20-OPTIM: ret + // + // LLVM-20-OPTIM: cmp + // LLVM-20-OPTIM: setl + // LLVM-20-OPTIM: setg + // LLVM-20-OPTIM: sub + // LLVM-20-OPTIM: ret three_way_compare(a, b) } @@ -41,11 +50,16 @@ pub fn unsigned_cmp(a: u16, b: u16) -> std::cmp::Ordering { // DEBUG: and // DEBUG: sub - // OPTIM: xor - // OPTIM: cmp - // OPTIM: setne - // OPTIM: mov - // OPTIM: cmovae - // OPTIM: ret + // LLVM-PRE-20-OPTIM: xor + // LLVM-PRE-20-OPTIM: cmp + // LLVM-PRE-20-OPTIM: setne + // LLVM-PRE-20-OPTIM: mov + // LLVM-PRE-20-OPTIM: cmovae + // LLVM-PRE-20-OPTIM: ret + // + // LLVM-20-OPTIM: cmp + // LLVM-20-OPTIM: seta + // LLVM-20-OPTIM: sbb + // LLVM-20-OPTIM: ret three_way_compare(a, b) } diff --git a/tests/codegen/debuginfo-inline-callsite-location.rs b/tests/codegen/debuginfo-inline-callsite-location.rs index aee07b4eb8c..c31788d82db 100644 --- a/tests/codegen/debuginfo-inline-callsite-location.rs +++ b/tests/codegen/debuginfo-inline-callsite-location.rs @@ -9,13 +9,12 @@ // CHECK: tail call void @{{[A-Za-z0-9_]+4core6option13unwrap_failed}} // CHECK-SAME: !dbg ![[#second_dbg:]] -// CHECK-DAG: ![[#func_dbg:]] = distinct !DISubprogram(name: "unwrap" -// CHECK-DAG: ![[#first_scope:]] = distinct !DILexicalBlock(scope: ![[#func_dbg]], -// CHECK: ![[#second_scope:]] = distinct !DILexicalBlock(scope: ![[#func_dbg]], +// CHECK-DAG: ![[#func_scope:]] = distinct !DISubprogram(name: "unwrap" +// CHECK-DAG: ![[#]] = !DILocalVariable(name: "self",{{( arg: 1,)?}} scope: ![[#func_scope]] // CHECK: ![[#first_dbg]] = !DILocation(line: [[#]] -// CHECK-SAME: scope: ![[#first_scope]], inlinedAt: ![[#]]) +// CHECK-SAME: scope: ![[#func_scope]], inlinedAt: ![[#]]) // CHECK: ![[#second_dbg]] = !DILocation(line: [[#]] -// CHECK-SAME: scope: ![[#second_scope]], inlinedAt: ![[#]]) +// CHECK-SAME: scope: ![[#func_scope]], inlinedAt: ![[#]]) #![crate_type = "lib"] diff --git a/tests/codegen/inline-function-args-debug-info.rs b/tests/codegen/inline-function-args-debug-info.rs index 7263374b22e..53a179160dc 100644 --- a/tests/codegen/inline-function-args-debug-info.rs +++ b/tests/codegen/inline-function-args-debug-info.rs @@ -15,6 +15,7 @@ pub fn outer_function(x: usize, y: usize) -> usize { fn inner_function(aaaa: usize, bbbb: usize) -> usize { // CHECK: !DILocalVariable(name: "aaaa", arg: 1 // CHECK-SAME: line: 15 + // CHECK-NOT: !DILexicalBlock( // CHECK: !DILocalVariable(name: "bbbb", arg: 2 // CHECK-SAME: line: 15 aaaa + bbbb diff --git a/tests/codegen/integer-cmp.rs b/tests/codegen/integer-cmp.rs index bba112b246f..8df68d8d490 100644 --- a/tests/codegen/integer-cmp.rs +++ b/tests/codegen/integer-cmp.rs @@ -1,6 +1,9 @@ // This is test for more optimal Ord implementation for integers. // See for more info. +//@ revisions: llvm-pre-20 llvm-20 +//@ [llvm-20] min-llvm-version: 20 +//@ [llvm-pre-20] ignore-llvm-version: 20 - 99 //@ compile-flags: -C opt-level=3 #![crate_type = "lib"] @@ -10,19 +13,21 @@ use std::cmp::Ordering; // CHECK-LABEL: @cmp_signed #[no_mangle] pub fn cmp_signed(a: i64, b: i64) -> Ordering { - // CHECK: icmp slt - // CHECK: icmp ne - // CHECK: zext i1 - // CHECK: select i1 + // llvm-20: @llvm.scmp.i8.i64 + // llvm-pre-20: icmp slt + // llvm-pre-20: icmp ne + // llvm-pre-20: zext i1 + // llvm-pre-20: select i1 a.cmp(&b) } // CHECK-LABEL: @cmp_unsigned #[no_mangle] pub fn cmp_unsigned(a: u32, b: u32) -> Ordering { - // CHECK: icmp ult - // CHECK: icmp ne - // CHECK: zext i1 - // CHECK: select i1 + // llvm-20: @llvm.ucmp.i8.i32 + // llvm-pre-20: icmp ult + // llvm-pre-20: icmp ne + // llvm-pre-20: zext i1 + // llvm-pre-20: select i1 a.cmp(&b) } diff --git a/tests/codegen/intrinsics/rustc_intrinsic_must_be_overridden.rs b/tests/codegen/intrinsics/rustc_intrinsic_must_be_overridden.rs new file mode 100644 index 00000000000..b41e441d309 --- /dev/null +++ b/tests/codegen/intrinsics/rustc_intrinsic_must_be_overridden.rs @@ -0,0 +1,14 @@ +//@ revisions: OPT0 OPT1 +//@ [OPT0] compile-flags: -Copt-level=0 +//@ [OPT1] compile-flags: -Copt-level=1 +//@ compile-flags: -Cno-prepopulate-passes + +#![crate_type = "lib"] +#![feature(core_intrinsics)] + +// CHECK-NOT: core::intrinsics::size_of_val + +#[no_mangle] +pub unsafe fn size_of_val(ptr: *const i32) -> usize { + core::intrinsics::size_of_val(ptr) +} diff --git a/tests/codegen/is_val_statically_known.rs b/tests/codegen/is_val_statically_known.rs index 6af4f353a48..fe432d3bcc4 100644 --- a/tests/codegen/is_val_statically_known.rs +++ b/tests/codegen/is_val_statically_known.rs @@ -1,6 +1,7 @@ //@ compile-flags: --crate-type=lib -Zmerge-functions=disabled -O #![feature(core_intrinsics)] +#![feature(f16, f128)] use std::intrinsics::is_val_statically_known; @@ -49,7 +50,7 @@ pub fn _bool_false(b: bool) -> i32 { #[inline] pub fn _iref(a: &u8) -> i32 { - if unsafe { is_val_statically_known(a) } { 5 } else { 4 } + if is_val_statically_known(a) { 5 } else { 4 } } // CHECK-LABEL: @_iref_borrow( @@ -68,7 +69,7 @@ pub fn _iref_arg(a: &u8) -> i32 { #[inline] pub fn _slice_ref(a: &[u8]) -> i32 { - if unsafe { is_val_statically_known(a) } { 7 } else { 6 } + if is_val_statically_known(a) { 7 } else { 6 } } // CHECK-LABEL: @_slice_ref_borrow( @@ -84,3 +85,79 @@ pub fn _slice_ref_arg(a: &[u8]) -> i32 { // CHECK: ret i32 6 _slice_ref(a) } + +#[inline] +pub fn _f16(a: f16) -> i32 { + if is_val_statically_known(a) { 1 } else { 0 } +} + +// CHECK-LABEL: @_f16_true( +#[no_mangle] +pub fn _f16_true() -> i32 { + // CHECK: ret i32 1 + _f16(1.0) +} + +// CHECK-LABEL: @_f16_false( +#[no_mangle] +pub fn _f16_false(a: f16) -> i32 { + // CHECK: ret i32 0 + _f16(a) +} + +#[inline] +pub fn _f32(a: f32) -> i32 { + if is_val_statically_known(a) { 1 } else { 0 } +} + +// CHECK-LABEL: @_f32_true( +#[no_mangle] +pub fn _f32_true() -> i32 { + // CHECK: ret i32 1 + _f32(1.0) +} + +// CHECK-LABEL: @_f32_false( +#[no_mangle] +pub fn _f32_false(a: f32) -> i32 { + // CHECK: ret i32 0 + _f32(a) +} + +#[inline] +pub fn _f64(a: f64) -> i32 { + if is_val_statically_known(a) { 1 } else { 0 } +} + +// CHECK-LABEL: @_f64_true( +#[no_mangle] +pub fn _f64_true() -> i32 { + // CHECK: ret i32 1 + _f64(1.0) +} + +// CHECK-LABEL: @_f64_false( +#[no_mangle] +pub fn _f64_false(a: f64) -> i32 { + // CHECK: ret i32 0 + _f64(a) +} + +#[inline] +pub fn _f128(a: f128) -> i32 { + if is_val_statically_known(a) { 1 } else { 0 } +} + +// CHECK-LABEL: @_f128_true( +#[no_mangle] +pub fn _f128_true() -> i32 { + // CHECK: ret i32 1 + _f128(1.0) +} + +// CHECK-LABEL: @_f128_false( +#[no_mangle] +pub fn _f128_false(a: f128) -> i32 { + // CHECK: ret i32 0 + _f128(a) +} diff --git a/tests/codegen/issues/str-to-string-128690.rs b/tests/codegen/issues/str-to-string-128690.rs new file mode 100644 index 00000000000..8b416306ba6 --- /dev/null +++ b/tests/codegen/issues/str-to-string-128690.rs @@ -0,0 +1,36 @@ +//@ compile-flags: -C opt-level=3 -Z merge-functions=disabled +#![crate_type = "lib"] + +//! Make sure str::to_string is specialized not to use fmt machinery. + +// CHECK-LABEL: define {{(dso_local )?}}void @one_ref +#[no_mangle] +pub fn one_ref(input: &str) -> String { + // CHECK-NOT: {{(call|invoke).*}}fmt + input.to_string() +} + +// CHECK-LABEL: define {{(dso_local )?}}void @two_ref +#[no_mangle] +pub fn two_ref(input: &&str) -> String { + // CHECK-NOT: {{(call|invoke).*}}fmt + input.to_string() +} + +// CHECK-LABEL: define {{(dso_local )?}}void @thirteen_ref +#[no_mangle] +pub fn thirteen_ref(input: &&&&&&&&&&&&&str) -> String { + // CHECK-NOT: {{(call|invoke).*}}fmt + input.to_string() +} + +// This is a known performance cliff because of the macro-generated +// specialized impl. If this test suddenly starts failing, +// consider removing the `to_string_str!` macro in `alloc/str/string.rs`. +// +// CHECK-LABEL: define {{(dso_local )?}}void @fourteen_ref +#[no_mangle] +pub fn fourteen_ref(input: &&&&&&&&&&&&&&str) -> String { + // CHECK: {{(call|invoke).*}}fmt + input.to_string() +} diff --git a/tests/codegen/naked-fn/aligned.rs b/tests/codegen/naked-fn/aligned.rs new file mode 100644 index 00000000000..d5faac44836 --- /dev/null +++ b/tests/codegen/naked-fn/aligned.rs @@ -0,0 +1,20 @@ +//@ compile-flags: -C no-prepopulate-passes -Copt-level=0 +//@ needs-asm-support +//@ ignore-arm no "ret" mnemonic + +#![crate_type = "lib"] +#![feature(naked_functions, fn_align)] +use std::arch::asm; + +// CHECK: Function Attrs: naked +// CHECK-NEXT: define{{.*}}void @naked_empty() +// CHECK: align 16 +#[repr(align(16))] +#[no_mangle] +#[naked] +pub unsafe extern "C" fn naked_empty() { + // CHECK-NEXT: start: + // CHECK-NEXT: call void asm + // CHECK-NEXT: unreachable + asm!("ret", options(noreturn)); +} diff --git a/tests/codegen/sanitizer/aarch64-shadow-call-stack-with-fixed-x18.rs b/tests/codegen/sanitizer/aarch64-shadow-call-stack-with-fixed-x18.rs new file mode 100644 index 00000000000..e2e14ab14a8 --- /dev/null +++ b/tests/codegen/sanitizer/aarch64-shadow-call-stack-with-fixed-x18.rs @@ -0,0 +1,19 @@ +//@ revisions: aarch64 android +//@[aarch64] compile-flags: --target aarch64-unknown-none -Zfixed-x18 -Zsanitizer=shadow-call-stack +//@[aarch64] needs-llvm-components: aarch64 +//@[android] compile-flags: --target aarch64-linux-android -Zsanitizer=shadow-call-stack +//@[android] needs-llvm-components: aarch64 + +#![allow(internal_features)] +#![crate_type = "rlib"] +#![feature(no_core, lang_items)] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +// CHECK: ; Function Attrs:{{.*}}shadowcallstack +#[no_mangle] +pub fn foo() {} + +// CHECK: attributes #0 = {{.*}}shadowcallstack{{.*}} diff --git a/tests/codegen/sanitizer/cfi/add-cfi-normalize-integers-flag.rs b/tests/codegen/sanitizer/cfi/add-cfi-normalize-integers-flag.rs new file mode 100644 index 00000000000..a54a6d84a80 --- /dev/null +++ b/tests/codegen/sanitizer/cfi/add-cfi-normalize-integers-flag.rs @@ -0,0 +1,10 @@ +// Verifies that "cfi-normalize-integers" module flag is added. +// +//@ needs-sanitizer-cfi +//@ compile-flags: -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers + +#![crate_type = "lib"] + +pub fn foo() {} + +// CHECK: !{{[0-9]+}} = !{i32 4, !"cfi-normalize-integers", i32 1} diff --git a/tests/codegen/sanitizer/kcfi/add-cfi-normalize-integers-flag.rs b/tests/codegen/sanitizer/kcfi/add-cfi-normalize-integers-flag.rs new file mode 100644 index 00000000000..d48e4016a16 --- /dev/null +++ b/tests/codegen/sanitizer/kcfi/add-cfi-normalize-integers-flag.rs @@ -0,0 +1,21 @@ +// Verifies that "cfi-normalize-integers" module flag is added. +// +//@ revisions: aarch64 x86_64 +//@ [aarch64] compile-flags: --target aarch64-unknown-none +//@ [aarch64] needs-llvm-components: aarch64 +//@ [x86_64] compile-flags: --target x86_64-unknown-none +//@ [x86_64] needs-llvm-components: x86 +//@ compile-flags: -Ctarget-feature=-crt-static -Zsanitizer=kcfi -Zsanitizer-cfi-normalize-integers + +#![feature(no_core, lang_items)] +#![crate_type = "lib"] +#![no_core] + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +pub fn foo() {} + +// CHECK: !{{[0-9]+}} = !{i32 4, !"cfi-normalize-integers", i32 1} diff --git a/tests/codegen/sanitizer/kcfi/add-kcfi-offset-flag.rs b/tests/codegen/sanitizer/kcfi/add-kcfi-offset-flag.rs new file mode 100644 index 00000000000..b4924719f4c --- /dev/null +++ b/tests/codegen/sanitizer/kcfi/add-kcfi-offset-flag.rs @@ -0,0 +1,21 @@ +// Verifies that "kcfi-offset" module flag is added. +// +//@ revisions: aarch64 x86_64 +//@ [aarch64] compile-flags: --target aarch64-unknown-none +//@ [aarch64] needs-llvm-components: aarch64 +//@ [x86_64] compile-flags: --target x86_64-unknown-none +//@ [x86_64] needs-llvm-components: x86 +//@ compile-flags: -Ctarget-feature=-crt-static -Zsanitizer=kcfi -Z patchable-function-entry=4,3 + +#![feature(no_core, lang_items, patchable_function_entry)] +#![crate_type = "lib"] +#![no_core] + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +pub fn foo() {} + +// CHECK: !{{[0-9]+}} = !{i32 4, !"kcfi-offset", i32 3} diff --git a/tests/codegen/tied-features-strength.rs b/tests/codegen/tied-features-strength.rs index 1b4596ae2cb..1b2b63c3d1a 100644 --- a/tests/codegen/tied-features-strength.rs +++ b/tests/codegen/tied-features-strength.rs @@ -3,21 +3,21 @@ //@ compile-flags: --crate-type=rlib --target=aarch64-unknown-linux-gnu //@ needs-llvm-components: aarch64 -// The "+v8a" feature is matched as optional as it isn't added when we -// are targeting older LLVM versions. Once the min supported version -// is LLVM-14 we can remove the optional regex matching for this feature. +// The "+fpmr" feature is matched as optional as it is only an explicit +// feature in LLVM 18. Once the min supported version is LLVM-19 the optional +// regex matching for this feature can be removed. //@ [ENABLE_SVE] compile-flags: -C target-feature=+sve -Copt-level=0 -// ENABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(\+sve,?)|(\+neon,?)|(\+fp-armv8,?))*}}" } +// ENABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(\+sve,?)|(\+neon,?)|(\+fp-armv8,?))*}}" } //@ [DISABLE_SVE] compile-flags: -C target-feature=-sve -Copt-level=0 -// DISABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(-sve,?)|(\+neon,?))*}}" } +// DISABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(-sve,?)|(\+neon,?))*}}" } //@ [DISABLE_NEON] compile-flags: -C target-feature=-neon -Copt-level=0 -// DISABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(-fp-armv8,?)|(-neon,?))*}}" } +// DISABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(-fp-armv8,?)|(-neon,?))*}}" } //@ [ENABLE_NEON] compile-flags: -C target-feature=+neon -Copt-level=0 -// ENABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(\+fp-armv8,?)|(\+neon,?))*}}" } +// ENABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(\+fp-armv8,?)|(\+neon,?))*}}" } #![feature(no_core, lang_items)] #![no_core] diff --git a/tests/crashes/123693.rs b/tests/crashes/123693.rs index c2e192092be..c3236322c6e 100644 --- a/tests/crashes/123693.rs +++ b/tests/crashes/123693.rs @@ -3,11 +3,11 @@ #![feature(transmutability)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable() where - Dst: BikeshedIntrinsicFrom, + Dst: TransmuteFrom, { } } diff --git a/tests/crashes/124207.rs b/tests/crashes/124207.rs index a4e1c551890..a11eedb140a 100644 --- a/tests/crashes/124207.rs +++ b/tests/crashes/124207.rs @@ -4,6 +4,6 @@ trait OpaqueTrait {} type OpaqueType = impl OpaqueTrait; trait AnotherTrait {} -impl> AnotherTrait for T {} +impl> AnotherTrait for T {} impl AnotherTrait for OpaqueType {} pub fn main() {} diff --git a/tests/crashes/125881.rs b/tests/crashes/125881.rs index 98331d3c974..a38f1891b61 100644 --- a/tests/crashes/125881.rs +++ b/tests/crashes/125881.rs @@ -3,6 +3,6 @@ #![feature(transmutability)] #![feature(unboxed_closures,effects)] -const fn test() -> impl std::mem::BikeshedIntrinsicFrom() { +const fn test() -> impl std::mem::TransmuteFrom() { || {} } diff --git a/tests/crashes/126267.rs b/tests/crashes/126267.rs index c0604b90a67..728578179ed 100644 --- a/tests/crashes/126267.rs +++ b/tests/crashes/126267.rs @@ -14,11 +14,11 @@ pub enum Error { } mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable() where - Dst: BikeshedIntrinsicFrom, // safety is NOT assumed + Dst: TransmuteFrom, // safety is NOT assumed { } } diff --git a/tests/crashes/126377.rs b/tests/crashes/126377.rs index f8b9b693b65..f6727bcc0a4 100644 --- a/tests/crashes/126377.rs +++ b/tests/crashes/126377.rs @@ -4,7 +4,7 @@ #![feature(generic_const_exprs)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable< Src, @@ -15,7 +15,7 @@ mod assert { const ASSUME_VALIDITY: bool, >() where - Dst: BikeshedIntrinsicFrom< + Dst: TransmuteFrom< Src, { } >, diff --git a/tests/crashes/126966.rs b/tests/crashes/126966.rs index edeedc68c40..2c9f1a70f4f 100644 --- a/tests/crashes/126966.rs +++ b/tests/crashes/126966.rs @@ -1,10 +1,10 @@ //@ known-bug: rust-lang/rust#126966 mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable() where - Dst: BikeshedIntrinsicFrom, + Dst: TransmuteFrom, { } } diff --git a/tests/crashes/127972.rs b/tests/crashes/127972.rs index d0764f875db..797dd7e6020 100644 --- a/tests/crashes/127972.rs +++ b/tests/crashes/127972.rs @@ -1,5 +1,5 @@ //@ known-bug: #127962 -#![feature(generic_const_exprs)] +#![feature(generic_const_exprs, const_arg_path)] fn zero_init() -> Substs1<{ (N) }> { Substs1([0; { (usize) }]) diff --git a/tests/crashes/128016.rs b/tests/crashes/128016.rs deleted file mode 100644 index d23721ae14e..00000000000 --- a/tests/crashes/128016.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ known-bug: #128016 -macro_rules! len { - () => { - target - }; -} - -fn main() { - let val: [str; len!()] = []; -} diff --git a/tests/crashes/128695.rs b/tests/crashes/128695.rs new file mode 100644 index 00000000000..661f427dc0e --- /dev/null +++ b/tests/crashes/128695.rs @@ -0,0 +1,11 @@ +//@ known-bug: rust-lang/rust#128695 +//@ edition: 2021 + +use core::pin::{pin, Pin}; + +fn main() { + let fut = pin!(async { + let async_drop_fut = pin!(core::future::async_drop(async {})); + (async_drop_fut).await; + }); +} diff --git a/tests/crashes/128848.rs b/tests/crashes/128848.rs new file mode 100644 index 00000000000..636811fc6b5 --- /dev/null +++ b/tests/crashes/128848.rs @@ -0,0 +1,5 @@ +//@ known-bug: rust-lang/rust#128848 + +fn f(a: T, b: T, c: T) { + f.call_once() +} diff --git a/tests/crashes/128870.rs b/tests/crashes/128870.rs new file mode 100644 index 00000000000..2b731962144 --- /dev/null +++ b/tests/crashes/128870.rs @@ -0,0 +1,18 @@ +//@ known-bug: rust-lang/rust#128870 +//@ compile-flags: -Zvalidate-mir + +#[repr(packed)] +#[repr(u32)] +enum E { + A, + B, + C, +} + +fn main() { + union InvalidTag { + int: u32, + e: E, + } + let _invalid_tag = InvalidTag { int: 4 }; +} diff --git a/tests/crashes/129075.rs b/tests/crashes/129075.rs new file mode 100644 index 00000000000..4a0e920914c --- /dev/null +++ b/tests/crashes/129075.rs @@ -0,0 +1,16 @@ +//@ known-bug: rust-lang/rust#129075 +//@ compile-flags: -Zvalidate-mir -Zinline-mir=yes + +struct Foo([T; 2]); + +impl Default for Foo { + fn default(&mut self) -> Self { + Foo([Default::default(); 2]) + } +} + +fn field_array() { + let a: i32; + let b; + Foo([a, b]) = Default::default(); +} diff --git a/tests/crashes/129095.rs b/tests/crashes/129095.rs new file mode 100644 index 00000000000..ea70c0565fc --- /dev/null +++ b/tests/crashes/129095.rs @@ -0,0 +1,10 @@ +//@ known-bug: rust-lang/rust#129095 +//@ compile-flags: -Zmir-opt-level=5 -Zvalidate-mir + +pub fn function_with_bytes() -> &'static [u8] { + BYTES +} + +pub fn main() { + assert_eq!(function_with_bytes::(), &[0x41, 0x41, 0x41, 0x41]); +} diff --git a/tests/crashes/129099.rs b/tests/crashes/129099.rs new file mode 100644 index 00000000000..9aaab756b5b --- /dev/null +++ b/tests/crashes/129099.rs @@ -0,0 +1,15 @@ +//@ known-bug: rust-lang/rust#129099 + +#![feature(type_alias_impl_trait)] + +fn dyn_hoops() -> dyn for<'a> Iterator> { + loop {} +} + +pub fn main() { + type Opaque = impl Sized; + fn define() -> Opaque { + let x: Opaque = dyn_hoops::<()>(0); + x + } +} diff --git a/tests/crashes/129109.rs b/tests/crashes/129109.rs new file mode 100644 index 00000000000..8b9ebdf03c7 --- /dev/null +++ b/tests/crashes/129109.rs @@ -0,0 +1,10 @@ +//@ known-bug: rust-lang/rust#129109 +//@ compile-flags: -Zmir-opt-level=5 -Zvalidate-mir + +extern "C" { + pub static mut symbol: [i8]; +} + +fn main() { + println!("C", unsafe { &symbol }); +} diff --git a/tests/crashes/129127.rs b/tests/crashes/129127.rs new file mode 100644 index 00000000000..8ec848dbd05 --- /dev/null +++ b/tests/crashes/129127.rs @@ -0,0 +1,21 @@ +//@ known-bug: rust-lang/rust#129127 +//@ compile-flags: -Zmir-opt-level=5 -Zvalidate-mir -Zcross-crate-inline-threshold=always + + + + +pub struct Rows<'a>(); + +impl<'a> Iterator for Rows<'a> { + type Item = (); + + fn next() -> Option { + let mut rows = Rows(); + rows.map(|row| row).next() + } +} + +fn main() { + let mut rows = Rows(); + rows.next(); +} diff --git a/tests/crashes/129150.rs b/tests/crashes/129150.rs new file mode 100644 index 00000000000..9f8c2ba1739 --- /dev/null +++ b/tests/crashes/129150.rs @@ -0,0 +1,7 @@ +//@ known-bug: rust-lang/rust#129150 +//@ only-x86_64 +use std::arch::x86_64::_mm_blend_ps; + +pub fn main() { + _mm_blend_ps(1, 2, &const {} ); +} diff --git a/tests/crashes/129166.rs b/tests/crashes/129166.rs new file mode 100644 index 00000000000..d3635d410db --- /dev/null +++ b/tests/crashes/129166.rs @@ -0,0 +1,7 @@ +//@ known-bug: rust-lang/rust#129166 + +fn main() { + #[cfg_eval] + #[cfg] + 0 +} diff --git a/tests/crashes/129209.rs b/tests/crashes/129209.rs new file mode 100644 index 00000000000..249fa41552e --- /dev/null +++ b/tests/crashes/129209.rs @@ -0,0 +1,11 @@ +//@ known-bug: rust-lang/rust#129209 + +impl< + const N: usize = { + static || { + Foo([0; X]); + } + }, + > PartialEq for True +{ +} diff --git a/tests/crashes/129214.rs b/tests/crashes/129214.rs new file mode 100644 index 00000000000..e14b9f379d6 --- /dev/null +++ b/tests/crashes/129214.rs @@ -0,0 +1,30 @@ +//@ known-bug: rust-lang/rust#129214 +//@ compile-flags: -Zvalidate-mir -Copt-level=3 --crate-type=lib + +trait to_str {} + +trait map { + fn map(&self, f: F) -> Vec + where + F: FnMut(&Box) -> U; +} +impl map for Vec { + fn map(&self, mut f: F) -> Vec + where + F: FnMut(&T) -> U, + { + let mut r = Vec::new(); + for i in self { + r.push(f(i)); + } + r + } +} + +fn foo>(x: T) -> Vec { + x.map(|_e| "hi".to_string()) +} + +pub fn main() { + assert_eq!(foo(vec![1]), ["hi".to_string()]); +} diff --git a/tests/crashes/129219.rs b/tests/crashes/129219.rs new file mode 100644 index 00000000000..effbfcd8b8e --- /dev/null +++ b/tests/crashes/129219.rs @@ -0,0 +1,26 @@ +//@ known-bug: rust-lang/rust#129219 +//@ compile-flags: -Zmir-opt-level=5 -Zvalidate-mir --edition=2018 + +use core::marker::Unsize; + +pub trait CastTo: Unsize {} + +impl CastTo for U {} + +impl Cast for T {} +pub trait Cast { + fn cast(&self) -> &T + where + Self: CastTo, + { + self + } +} + +pub trait Foo {} +impl Foo for [i32; 0] {} + +fn main() { + let x: &dyn Foo = &[]; + let x = x.cast::<[i32]>(); +} diff --git a/tests/debuginfo/associated-types.rs b/tests/debuginfo/associated-types.rs index d1d4e320b05..b20bd520936 100644 --- a/tests/debuginfo/associated-types.rs +++ b/tests/debuginfo/associated-types.rs @@ -1,15 +1,10 @@ -// Some versions of the non-rust-enabled LLDB print the wrong generic -// parameter type names in this test. -//@ needs-rust-lldb - //@ compile-flags:-g // === GDB TESTS =================================================================================== // gdb-command:run // gdb-command:print arg -// gdbg-check:$1 = {b = -1, b1 = 0} -// gdbr-check:$1 = associated_types::Struct {b: -1, b1: 0} +// gdb-check:$1 = associated_types::Struct {b: -1, b1: 0} // gdb-command:continue // gdb-command:print inferred @@ -23,8 +18,7 @@ // gdb-command:continue // gdb-command:print arg -// gdbg-check:$5 = {__0 = 4, __1 = 5} -// gdbr-check:$5 = (4, 5) +// gdb-check:$5 = (4, 5) // gdb-command:continue // gdb-command:print a @@ -43,42 +37,33 @@ // lldb-command:run // lldb-command:v arg -// lldbg-check:[...] { b = -1, b1 = 0 } -// lldbr-check:(associated_types::Struct) arg = { b = -1, b1 = 0 } +// lldb-check:[...] { b = -1 b1 = 0 } // lldb-command:continue // lldb-command:v inferred -// lldbg-check:[...] 1 -// lldbr-check:(i64) inferred = 1 +// lldb-check:[...] 1 // lldb-command:v explicitly -// lldbg-check:[...] 1 -// lldbr-check:(i64) explicitly = 1 +// lldb-check:[...] 1 // lldb-command:continue // lldb-command:v arg -// lldbg-check:[...] 2 -// lldbr-check:(i64) arg = 2 +// lldb-check:[...] 2 // lldb-command:continue // lldb-command:v arg -// lldbg-check:[...] (4, 5) -// lldbr-check:((i32, i64)) arg = { = 4 = 5 } +// lldb-check:[...] { 0 = 4 1 = 5 } // lldb-command:continue // lldb-command:v a -// lldbg-check:[...] 6 -// lldbr-check:(i32) a = 6 +// lldb-check:[...] 6 // lldb-command:v b -// lldbg-check:[...] 7 -// lldbr-check:(i64) b = 7 +// lldb-check:[...] 7 // lldb-command:continue // lldb-command:v a -// lldbg-check:[...] 8 -// lldbr-check:(i64) a = 8 +// lldb-check:[...] 8 // lldb-command:v b -// lldbg-check:[...] 9 -// lldbr-check:(i32) b = 9 +// lldb-check:[...] 9 // lldb-command:continue #![allow(unused_variables)] diff --git a/tests/debuginfo/basic-types-globals-metadata.rs b/tests/debuginfo/basic-types-globals-metadata.rs index d346b405555..53fc550a2dc 100644 --- a/tests/debuginfo/basic-types-globals-metadata.rs +++ b/tests/debuginfo/basic-types-globals-metadata.rs @@ -1,52 +1,35 @@ -//@ min-lldb-version: 310 -//@ ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 - //@ compile-flags:-g + // gdb-command:run -// gdbg-command:whatis 'basic_types_globals_metadata::B' -// gdbr-command:whatis basic_types_globals_metadata::B +// gdb-command:whatis basic_types_globals_metadata::B // gdb-check:type = bool -// gdbg-command:whatis 'basic_types_globals_metadata::I' -// gdbr-command:whatis basic_types_globals_metadata::I +// gdb-command:whatis basic_types_globals_metadata::I // gdb-check:type = isize -// gdbg-command:whatis 'basic_types_globals_metadata::C' -// gdbr-command:whatis basic_types_globals_metadata::C +// gdb-command:whatis basic_types_globals_metadata::C // gdb-check:type = char -// gdbg-command:whatis 'basic_types_globals_metadata::I8' -// gdbr-command:whatis basic_types_globals_metadata::I8 +// gdb-command:whatis basic_types_globals_metadata::I8 // gdb-check:type = i8 -// gdbg-command:whatis 'basic_types_globals_metadata::I16' -// gdbr-command:whatis basic_types_globals_metadata::I16 +// gdb-command:whatis basic_types_globals_metadata::I16 // gdb-check:type = i16 -// gdbg-command:whatis 'basic_types_globals_metadata::I32' -// gdbr-command:whatis basic_types_globals_metadata::I32 +// gdb-command:whatis basic_types_globals_metadata::I32 // gdb-check:type = i32 -// gdbg-command:whatis 'basic_types_globals_metadata::I64' -// gdbr-command:whatis basic_types_globals_metadata::I64 +// gdb-command:whatis basic_types_globals_metadata::I64 // gdb-check:type = i64 -// gdbg-command:whatis 'basic_types_globals_metadata::U' -// gdbr-command:whatis basic_types_globals_metadata::U +// gdb-command:whatis basic_types_globals_metadata::U // gdb-check:type = usize -// gdbg-command:whatis 'basic_types_globals_metadata::U8' -// gdbr-command:whatis basic_types_globals_metadata::U8 +// gdb-command:whatis basic_types_globals_metadata::U8 // gdb-check:type = u8 -// gdbg-command:whatis 'basic_types_globals_metadata::U16' -// gdbr-command:whatis basic_types_globals_metadata::U16 +// gdb-command:whatis basic_types_globals_metadata::U16 // gdb-check:type = u16 -// gdbg-command:whatis 'basic_types_globals_metadata::U32' -// gdbr-command:whatis basic_types_globals_metadata::U32 +// gdb-command:whatis basic_types_globals_metadata::U32 // gdb-check:type = u32 -// gdbg-command:whatis 'basic_types_globals_metadata::U64' -// gdbr-command:whatis basic_types_globals_metadata::U64 +// gdb-command:whatis basic_types_globals_metadata::U64 // gdb-check:type = u64 -// gdbg-command:whatis 'basic_types_globals_metadata::F16' -// gdbr-command:whatis basic_types_globals_metadata::F16 +// gdb-command:whatis basic_types_globals_metadata::F16 // gdb-check:type = f16 -// gdbg-command:whatis 'basic_types_globals_metadata::F32' -// gdbr-command:whatis basic_types_globals_metadata::F32 +// gdb-command:whatis basic_types_globals_metadata::F32 // gdb-check:type = f32 -// gdbg-command:whatis 'basic_types_globals_metadata::F64' -// gdbr-command:whatis basic_types_globals_metadata::F64 +// gdb-command:whatis basic_types_globals_metadata::F64 // gdb-check:type = f64 // gdb-command:continue diff --git a/tests/debuginfo/basic-types-globals.rs b/tests/debuginfo/basic-types-globals.rs index 0425d14fa5a..41b69939650 100644 --- a/tests/debuginfo/basic-types-globals.rs +++ b/tests/debuginfo/basic-types-globals.rs @@ -1,9 +1,3 @@ -// Caveat - gdb doesn't know about UTF-32 character encoding and will print a -// rust char as only its numerical value. - -//@ min-lldb-version: 310 -//@ min-gdb-version: 8.0 - //@ revisions: lto no-lto //@ compile-flags:-g @@ -12,51 +6,35 @@ //@ [lto] no-prefer-dynamic // gdb-command:run -// gdbg-command:print 'basic_types_globals::B' -// gdbr-command:print B +// gdb-command:print B // gdb-check:$1 = false -// gdbg-command:print 'basic_types_globals::I' -// gdbr-command:print I +// gdb-command:print I // gdb-check:$2 = -1 -// gdbg-command:print 'basic_types_globals::C' -// gdbr-command:print/d C -// gdbg-check:$3 = 97 -// gdbr-check:$3 = 97 -// gdbg-command:print/d 'basic_types_globals::I8' -// gdbr-command:print I8 +// gdb-command:print/d C +// gdb-check:$3 = 97 +// gdb-command:print I8 // gdb-check:$4 = 68 -// gdbg-command:print 'basic_types_globals::I16' -// gdbr-command:print I16 +// gdb-command:print I16 // gdb-check:$5 = -16 -// gdbg-command:print 'basic_types_globals::I32' -// gdbr-command:print I32 +// gdb-command:print I32 // gdb-check:$6 = -32 -// gdbg-command:print 'basic_types_globals::I64' -// gdbr-command:print I64 +// gdb-command:print I64 // gdb-check:$7 = -64 -// gdbg-command:print 'basic_types_globals::U' -// gdbr-command:print U +// gdb-command:print U // gdb-check:$8 = 1 -// gdbg-command:print/d 'basic_types_globals::U8' -// gdbr-command:print U8 +// gdb-command:print U8 // gdb-check:$9 = 100 -// gdbg-command:print 'basic_types_globals::U16' -// gdbr-command:print U16 +// gdb-command:print U16 // gdb-check:$10 = 16 -// gdbg-command:print 'basic_types_globals::U32' -// gdbr-command:print U32 +// gdb-command:print U32 // gdb-check:$11 = 32 -// gdbg-command:print 'basic_types_globals::U64' -// gdbr-command:print U64 +// gdb-command:print U64 // gdb-check:$12 = 64 -// gdbg-command:print 'basic_types_globals::F16' -// gdbr-command:print F16 +// gdb-command:print F16 // gdb-check:$13 = 1.5 -// gdbg-command:print 'basic_types_globals::F32' -// gdbr-command:print F32 +// gdb-command:print F32 // gdb-check:$14 = 2.5 -// gdbg-command:print 'basic_types_globals::F64' -// gdbr-command:print F64 +// gdb-command:print F64 // gdb-check:$15 = 3.5 // gdb-command:continue diff --git a/tests/debuginfo/basic-types-metadata.rs b/tests/debuginfo/basic-types-metadata.rs index 5f953c81a13..6b7cfbdebca 100644 --- a/tests/debuginfo/basic-types-metadata.rs +++ b/tests/debuginfo/basic-types-metadata.rs @@ -1,7 +1,5 @@ -//@ min-lldb-version: 310 -//@ ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 - //@ compile-flags:-g + // gdb-command:run // gdb-command:whatis unit // gdb-check:type = () @@ -36,31 +34,20 @@ // gdb-command:whatis f64 // gdb-check:type = f64 // gdb-command:whatis fnptr -// gdb-check:type = [...] (*)([...]) +// gdb-check:type = *mut fn () // gdb-command:info functions _yyy -// gdbg-check:[...]![...]_yyy([...]); -// gdbr-check:static fn basic_types_metadata::_yyy() -> !; +// gdb-check:static fn basic_types_metadata::_yyy(); // gdb-command:ptype closure_0 -// gdbr-check: type = struct closure -// gdbg-check: type = struct closure { -// gdbg-check: -// gdbg-check: } +// gdb-check: type = struct basic_types_metadata::main::{closure_env#0} // gdb-command:ptype closure_1 -// gdbg-check: type = struct closure { -// gdbg-check: bool *__0; -// gdbg-check: } -// gdbr-check: type = struct closure ( -// gdbr-check: bool *, -// gdbr-check: ) +// gdb-check: type = struct basic_types_metadata::main::{closure_env#1} { +// gdb-check: *mut bool, +// gdb-check: } // gdb-command:ptype closure_2 -// gdbg-check: type = struct closure { -// gdbg-check: bool *__0; -// gdbg-check: isize *__1; -// gdbg-check: } -// gdbr-check: type = struct closure ( -// gdbr-check: bool *, -// gdbr-check: isize *, -// gdbr-check: ) +// gdb-check: type = struct basic_types_metadata::main::{closure_env#2} { +// gdb-check: *mut bool, +// gdb-check: *mut isize, +// gdb-check: } // // gdb-command:continue diff --git a/tests/debuginfo/basic-types-mut-globals.rs b/tests/debuginfo/basic-types-mut-globals.rs index c676fd73771..f6a2399d230 100644 --- a/tests/debuginfo/basic-types-mut-globals.rs +++ b/tests/debuginfo/basic-types-mut-globals.rs @@ -4,107 +4,73 @@ // about UTF-32 character encoding and will print a rust char as only // its numerical value. -//@ min-lldb-version: 310 - //@ compile-flags:-g // gdb-command:run // Check initializers -// gdbg-command:print 'basic_types_mut_globals::B' -// gdbr-command:print B +// gdb-command:print B // gdb-check:$1 = false -// gdbg-command:print 'basic_types_mut_globals::I' -// gdbr-command:print I +// gdb-command:print I // gdb-check:$2 = -1 -// gdbg-command:print/d 'basic_types_mut_globals::C' -// gdbr-command:print C -// gdbg-check:$3 = 97 -// gdbr-check:$3 = 97 'a' -// gdbg-command:print/d 'basic_types_mut_globals::I8' -// gdbr-command:print I8 +// gdb-command:print C +// gdb-check:$3 = 97 'a' +// gdb-command:print I8 // gdb-check:$4 = 68 -// gdbg-command:print 'basic_types_mut_globals::I16' -// gdbr-command:print I16 +// gdb-command:print I16 // gdb-check:$5 = -16 -// gdbg-command:print 'basic_types_mut_globals::I32' -// gdbr-command:print I32 +// gdb-command:print I32 // gdb-check:$6 = -32 -// gdbg-command:print 'basic_types_mut_globals::I64' -// gdbr-command:print I64 +// gdb-command:print I64 // gdb-check:$7 = -64 -// gdbg-command:print 'basic_types_mut_globals::U' -// gdbr-command:print U +// gdb-command:print U // gdb-check:$8 = 1 -// gdbg-command:print/d 'basic_types_mut_globals::U8' -// gdbr-command:print U8 +// gdb-command:print U8 // gdb-check:$9 = 100 -// gdbg-command:print 'basic_types_mut_globals::U16' -// gdbr-command:print U16 +// gdb-command:print U16 // gdb-check:$10 = 16 -// gdbg-command:print 'basic_types_mut_globals::U32' -// gdbr-command:print U32 +// gdb-command:print U32 // gdb-check:$11 = 32 -// gdbg-command:print 'basic_types_mut_globals::U64' -// gdbr-command:print U64 +// gdb-command:print U64 // gdb-check:$12 = 64 -// gdbg-command:print 'basic_types_mut_globals::F16' -// gdbr-command:print F16 +// gdb-command:print F16 // gdb-check:$13 = 1.5 -// gdbg-command:print 'basic_types_mut_globals::F32' -// gdbr-command:print F32 +// gdb-command:print F32 // gdb-check:$14 = 2.5 -// gdbg-command:print 'basic_types_mut_globals::F64' -// gdbr-command:print F64 +// gdb-command:print F64 // gdb-check:$15 = 3.5 // gdb-command:continue // Check new values -// gdbg-command:print 'basic_types_mut_globals'::B -// gdbr-command:print B +// gdb-command:print B // gdb-check:$16 = true -// gdbg-command:print 'basic_types_mut_globals'::I -// gdbr-command:print I +// gdb-command:print I // gdb-check:$17 = 2 -// gdbg-command:print/d 'basic_types_mut_globals'::C -// gdbr-command:print C -// gdbg-check:$18 = 102 -// gdbr-check:$18 = 102 'f' -// gdbg-command:print/d 'basic_types_mut_globals'::I8 -// gdbr-command:print/d I8 +// gdb-command:print C +// gdb-check:$18 = 102 'f' +// gdb-command:print/d I8 // gdb-check:$19 = 78 -// gdbg-command:print 'basic_types_mut_globals'::I16 -// gdbr-command:print I16 +// gdb-command:print I16 // gdb-check:$20 = -26 -// gdbg-command:print 'basic_types_mut_globals'::I32 -// gdbr-command:print I32 +// gdb-command:print I32 // gdb-check:$21 = -12 -// gdbg-command:print 'basic_types_mut_globals'::I64 -// gdbr-command:print I64 +// gdb-command:print I64 // gdb-check:$22 = -54 -// gdbg-command:print 'basic_types_mut_globals'::U -// gdbr-command:print U +// gdb-command:print U // gdb-check:$23 = 5 -// gdbg-command:print/d 'basic_types_mut_globals'::U8 -// gdbr-command:print/d U8 +// gdb-command:print/d U8 // gdb-check:$24 = 20 -// gdbg-command:print 'basic_types_mut_globals'::U16 -// gdbr-command:print U16 +// gdb-command:print U16 // gdb-check:$25 = 32 -// gdbg-command:print 'basic_types_mut_globals'::U32 -// gdbr-command:print U32 +// gdb-command:print U32 // gdb-check:$26 = 16 -// gdbg-command:print 'basic_types_mut_globals'::U64 -// gdbr-command:print U64 +// gdb-command:print U64 // gdb-check:$27 = 128 -// gdbg-command:print 'basic_types_mut_globals'::F16 -// gdbr-command:print F16 +// gdb-command:print F16 // gdb-check:$28 = 2.25 -// gdbg-command:print 'basic_types_mut_globals'::F32 -// gdbr-command:print F32 +// gdb-command:print F32 // gdb-check:$29 = 5.75 -// gdbg-command:print 'basic_types_mut_globals'::F64 -// gdbr-command:print F64 +// gdb-command:print F64 // gdb-check:$30 = 9.25 #![allow(unused_variables)] diff --git a/tests/debuginfo/basic-types.rs b/tests/debuginfo/basic-types.rs index 10ffd74d3e9..fea5262bc41 100644 --- a/tests/debuginfo/basic-types.rs +++ b/tests/debuginfo/basic-types.rs @@ -4,11 +4,6 @@ // about UTF-32 character encoding and will print a rust char as only // its numerical value. -//@ min-lldb-version: 310 - -// This fails on lldb 6.0.1 on x86-64 Fedora 28; so ignore Linux for now. -//@ ignore-linux - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -19,8 +14,7 @@ // gdb-command:print i // gdb-check:$2 = -1 // gdb-command:print c -// gdbg-check:$3 = 97 -// gdbr-check:$3 = 97 'a' +// gdb-check:$3 = 97 'a' // gdb-command:print/d i8 // gdb-check:$4 = 68 // gdb-command:print i16 @@ -46,56 +40,38 @@ // gdb-command:print f64 // gdb-check:$15 = 3.5 // gdb-command:print s -// gdbg-check:$16 = {data_ptr = [...] "Hello, World!", length = 13} -// gdbr-check:$16 = "Hello, World!" +// gdb-check:$16 = "Hello, World!" // === LLDB TESTS ================================================================================== // lldb-command:run // lldb-command:v b -// lldbg-check:[...] false -// lldbr-check:(bool) b = false +// lldb-check:[...] false // lldb-command:v i -// lldbg-check:[...] -1 -// lldbr-check:(isize) i = -1 - -// NOTE: only rust-enabled lldb supports 32bit chars -// lldbr-command:print c -// lldbr-check:(char) c = 'a' +// lldb-check:[...] -1 // lldb-command:v i8 -// lldbg-check:[...] 'D' -// lldbr-check:(i8) i8 = 68 +// lldb-check:[...] 'D' // lldb-command:v i16 -// lldbg-check:[...] -16 -// lldbr-check:(i16) i16 = -16 +// lldb-check:[...] -16 // lldb-command:v i32 -// lldbg-check:[...] -32 -// lldbr-check:(i32) i32 = -32 +// lldb-check:[...] -32 // lldb-command:v i64 -// lldbg-check:[...] -64 -// lldbr-check:(i64) i64 = -64 +// lldb-check:[...] -64 // lldb-command:v u -// lldbg-check:[...] 1 -// lldbr-check:(usize) u = 1 +// lldb-check:[...] 1 // lldb-command:v u8 -// lldbg-check:[...] 'd' -// lldbr-check:(u8) u8 = 100 +// lldb-check:[...] 'd' // lldb-command:v u16 -// lldbg-check:[...] 16 -// lldbr-check:(u16) u16 = 16 +// lldb-check:[...] 16 // lldb-command:v u32 -// lldbg-check:[...] 32 -// lldbr-check:(u32) u32 = 32 +// lldb-check:[...] 32 // lldb-command:v u64 -// lldbg-check:[...] 64 -// lldbr-check:(u64) u64 = 64 +// lldb-check:[...] 64 // lldb-command:v f32 -// lldbg-check:[...] 2.5 -// lldbr-check:(f32) f32 = 2.5 +// lldb-check:[...] 2.5 // lldb-command:v f64 -// lldbg-check:[...] 3.5 -// lldbr-check:(f64) f64 = 3.5 +// lldb-check:[...] 3.5 // === CDB TESTS =================================================================================== diff --git a/tests/debuginfo/borrowed-basic.rs b/tests/debuginfo/borrowed-basic.rs index e3cf74dab1e..91de691e78e 100644 --- a/tests/debuginfo/borrowed-basic.rs +++ b/tests/debuginfo/borrowed-basic.rs @@ -1,5 +1,4 @@ //@ compile-flags:-g -//@ min-lldb-version: 310 // === GDB TESTS =================================================================================== @@ -14,8 +13,7 @@ // gdb-check:$3 = 97 // gdb-command:print *i8_ref -// gdbg-check:$4 = 68 'D' -// gdbr-check:$4 = 68 +// gdb-check:$4 = 68 // gdb-command:print *i16_ref // gdb-check:$5 = -16 @@ -30,8 +28,7 @@ // gdb-check:$8 = 1 // gdb-command:print *u8_ref -// gdbg-check:$9 = 100 'd' -// gdbr-check:$9 = 100 +// gdb-check:$9 = 100 // gdb-command:print *u16_ref // gdb-check:$10 = 16 @@ -56,64 +53,47 @@ // lldb-command:run // lldb-command:v *bool_ref -// lldbg-check:[...] true -// lldbr-check:(bool) *bool_ref = true +// lldb-check:[...] true // lldb-command:v *int_ref -// lldbg-check:[...] -1 -// lldbr-check:(isize) *int_ref = -1 +// lldb-check:[...] -1 -// NOTE: only rust-enabled lldb supports 32bit chars -// lldbr-command:print *char_ref -// lldbr-check:(char) *char_ref = 'a' // lldb-command:v *i8_ref -// lldbg-check:[...] 'D' -// lldbr-check:(i8) *i8_ref = 68 +// lldb-check:[...] 'D' // lldb-command:v *i16_ref -// lldbg-check:[...] -16 -// lldbr-check:(i16) *i16_ref = -16 +// lldb-check:[...] -16 // lldb-command:v *i32_ref -// lldbg-check:[...] -32 -// lldbr-check:(i32) *i32_ref = -32 +// lldb-check:[...] -32 // lldb-command:v *i64_ref -// lldbg-check:[...] -64 -// lldbr-check:(i64) *i64_ref = -64 +// lldb-check:[...] -64 // lldb-command:v *uint_ref -// lldbg-check:[...] 1 -// lldbr-check:(usize) *uint_ref = 1 +// lldb-check:[...] 1 // lldb-command:v *u8_ref -// lldbg-check:[...] 'd' -// lldbr-check:(u8) *u8_ref = 100 +// lldb-check:[...] 'd' // lldb-command:v *u16_ref -// lldbg-check:[...] 16 -// lldbr-check:(u16) *u16_ref = 16 +// lldb-check:[...] 16 // lldb-command:v *u32_ref -// lldbg-check:[...] 32 -// lldbr-check:(u32) *u32_ref = 32 +// lldb-check:[...] 32 // lldb-command:v *u64_ref -// lldbg-check:[...] 64 -// lldbr-check:(u64) *u64_ref = 64 +// lldb-check:[...] 64 // lldb-command:v *f16_ref -// lldbg-check:[...] 1.5 -// lldbr-check:(f16) *f16_ref = 1.5 +// lldb-check:[...] 1.5 // lldb-command:v *f32_ref -// lldbg-check:[...] 2.5 -// lldbr-check:(f32) *f32_ref = 2.5 +// lldb-check:[...] 2.5 // lldb-command:v *f64_ref -// lldbg-check:[...] 3.5 -// lldbr-check:(f64) *f64_ref = 3.5 +// lldb-check:[...] 3.5 #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/borrowed-c-style-enum.rs b/tests/debuginfo/borrowed-c-style-enum.rs index 1a582e8a6d9..6a91d4f9650 100644 --- a/tests/debuginfo/borrowed-c-style-enum.rs +++ b/tests/debuginfo/borrowed-c-style-enum.rs @@ -1,21 +1,17 @@ //@ compile-flags:-g -//@ min-lldb-version: 310 // === GDB TESTS =================================================================================== // gdb-command:run // gdb-command:print *the_a_ref -// gdbg-check:$1 = TheA -// gdbr-check:$1 = borrowed_c_style_enum::ABC::TheA +// gdb-check:$1 = borrowed_c_style_enum::ABC::TheA // gdb-command:print *the_b_ref -// gdbg-check:$2 = TheB -// gdbr-check:$2 = borrowed_c_style_enum::ABC::TheB +// gdb-check:$2 = borrowed_c_style_enum::ABC::TheB // gdb-command:print *the_c_ref -// gdbg-check:$3 = TheC -// gdbr-check:$3 = borrowed_c_style_enum::ABC::TheC +// gdb-check:$3 = borrowed_c_style_enum::ABC::TheC // === LLDB TESTS ================================================================================== @@ -23,16 +19,13 @@ // lldb-command:run // lldb-command:v *the_a_ref -// lldbg-check:[...] TheA -// lldbr-check:(borrowed_c_style_enum::ABC) *the_a_ref = borrowed_c_style_enum::ABC::TheA +// lldb-check:[...] TheA // lldb-command:v *the_b_ref -// lldbg-check:[...] TheB -// lldbr-check:(borrowed_c_style_enum::ABC) *the_b_ref = borrowed_c_style_enum::ABC::TheB +// lldb-check:[...] TheB // lldb-command:v *the_c_ref -// lldbg-check:[...] TheC -// lldbr-check:(borrowed_c_style_enum::ABC) *the_c_ref = borrowed_c_style_enum::ABC::TheC +// lldb-check:[...] TheC #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/borrowed-enum.rs b/tests/debuginfo/borrowed-enum.rs index fc2ab62a21c..c5a795fdede 100644 --- a/tests/debuginfo/borrowed-enum.rs +++ b/tests/debuginfo/borrowed-enum.rs @@ -1,5 +1,3 @@ -// Require a gdb or lldb that can read DW_TAG_variant_part. -//@ min-gdb-version: 8.2 //@ min-lldb-version: 1800 //@ compile-flags:-g @@ -9,13 +7,13 @@ // gdb-command:run // gdb-command:print *the_a_ref -// gdbr-check:$1 = borrowed_enum::ABC::TheA{x: 0, y: 8970181431921507452} +// gdb-check:$1 = borrowed_enum::ABC::TheA{x: 0, y: 8970181431921507452} // gdb-command:print *the_b_ref -// gdbr-check:$2 = borrowed_enum::ABC::TheB(0, 286331153, 286331153) +// gdb-check:$2 = borrowed_enum::ABC::TheB(0, 286331153, 286331153) // gdb-command:print *univariant_ref -// gdbr-check:$3 = borrowed_enum::Univariant::TheOnlyCase(4820353753753434) +// gdb-check:$3 = borrowed_enum::Univariant::TheOnlyCase(4820353753753434) // === LLDB TESTS ================================================================================== @@ -23,14 +21,11 @@ // lldb-command:run // lldb-command:v *the_a_ref -// lldbg-check:(borrowed_enum::ABC) *the_a_ref = { value = { x = 0 y = 8970181431921507452 } $discr$ = 0 } -// lldbr-check:(borrowed_enum::ABC::TheA) *the_a_ref = TheA { TheA: 0, TheB: 8970181431921507452 } +// lldb-check:(borrowed_enum::ABC) *the_a_ref = { value = { x = 0 y = 8970181431921507452 } $discr$ = 0 } // lldb-command:v *the_b_ref -// lldbg-check:(borrowed_enum::ABC) *the_b_ref = { value = { 0 = 0 1 = 286331153 2 = 286331153 } $discr$ = 1 } -// lldbr-check:(borrowed_enum::ABC::TheB) *the_b_ref = { = 0 = 286331153 = 286331153 } +// lldb-check:(borrowed_enum::ABC) *the_b_ref = { value = { 0 = 0 1 = 286331153 2 = 286331153 } $discr$ = 1 } // lldb-command:v *univariant_ref -// lldbg-check:(borrowed_enum::Univariant) *univariant_ref = { value = { 0 = 4820353753753434 } } -// lldbr-check:(borrowed_enum::Univariant) *univariant_ref = { TheOnlyCase = { = 4820353753753434 } } +// lldb-check:(borrowed_enum::Univariant) *univariant_ref = { value = { 0 = 4820353753753434 } } #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/borrowed-struct.rs b/tests/debuginfo/borrowed-struct.rs index d108a29592b..245af35f505 100644 --- a/tests/debuginfo/borrowed-struct.rs +++ b/tests/debuginfo/borrowed-struct.rs @@ -1,13 +1,11 @@ //@ compile-flags:-g -//@ min-lldb-version: 310 // === GDB TESTS =================================================================================== // gdb-command:run // gdb-command:print *stack_val_ref -// gdbg-check:$1 = {x = 10, y = 23.5} -// gdbr-check:$1 = borrowed_struct::SomeStruct {x: 10, y: 23.5} +// gdb-check:$1 = borrowed_struct::SomeStruct {x: 10, y: 23.5} // gdb-command:print *stack_val_interior_ref_1 // gdb-check:$2 = 10 @@ -16,12 +14,10 @@ // gdb-check:$3 = 23.5 // gdb-command:print *ref_to_unnamed -// gdbg-check:$4 = {x = 11, y = 24.5} -// gdbr-check:$4 = borrowed_struct::SomeStruct {x: 11, y: 24.5} +// gdb-check:$4 = borrowed_struct::SomeStruct {x: 11, y: 24.5} // gdb-command:print *unique_val_ref -// gdbg-check:$5 = {x = 13, y = 26.5} -// gdbr-check:$5 = borrowed_struct::SomeStruct {x: 13, y: 26.5} +// gdb-check:$5 = borrowed_struct::SomeStruct {x: 13, y: 26.5} // gdb-command:print *unique_val_interior_ref_1 // gdb-check:$6 = 13 @@ -35,32 +31,25 @@ // lldb-command:run // lldb-command:v *stack_val_ref -// lldbg-check:[...] { x = 10 y = 23.5 } -// lldbr-check:(borrowed_struct::SomeStruct) *stack_val_ref = (x = 10, y = 23.5) +// lldb-check:[...] { x = 10 y = 23.5 } // lldb-command:v *stack_val_interior_ref_1 -// lldbg-check:[...] 10 -// lldbr-check:(isize) *stack_val_interior_ref_1 = 10 +// lldb-check:[...] 10 // lldb-command:v *stack_val_interior_ref_2 -// lldbg-check:[...] 23.5 -// lldbr-check:(f64) *stack_val_interior_ref_2 = 23.5 +// lldb-check:[...] 23.5 // lldb-command:v *ref_to_unnamed -// lldbg-check:[...] { x = 11 y = 24.5 } -// lldbr-check:(borrowed_struct::SomeStruct) *ref_to_unnamed = (x = 11, y = 24.5) +// lldb-check:[...] { x = 11 y = 24.5 } // lldb-command:v *unique_val_ref -// lldbg-check:[...] { x = 13 y = 26.5 } -// lldbr-check:(borrowed_struct::SomeStruct) *unique_val_ref = (x = 13, y = 26.5) +// lldb-check:[...] { x = 13 y = 26.5 } // lldb-command:v *unique_val_interior_ref_1 -// lldbg-check:[...] 13 -// lldbr-check:(isize) *unique_val_interior_ref_1 = 13 +// lldb-check:[...] 13 // lldb-command:v *unique_val_interior_ref_2 -// lldbg-check:[...] 26.5 -// lldbr-check:(f64) *unique_val_interior_ref_2 = 26.5 +// lldb-check:[...] 26.5 #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/borrowed-tuple.rs b/tests/debuginfo/borrowed-tuple.rs index 4c5643deb9d..9e4ceec033e 100644 --- a/tests/debuginfo/borrowed-tuple.rs +++ b/tests/debuginfo/borrowed-tuple.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -7,16 +5,13 @@ // gdb-command:run // gdb-command:print *stack_val_ref -// gdbg-check:$1 = {__0 = -14, __1 = -19} -// gdbr-check:$1 = (-14, -19) +// gdb-check:$1 = (-14, -19) // gdb-command:print *ref_to_unnamed -// gdbg-check:$2 = {__0 = -15, __1 = -20} -// gdbr-check:$2 = (-15, -20) +// gdb-check:$2 = (-15, -20) // gdb-command:print *unique_val_ref -// gdbg-check:$3 = {__0 = -17, __1 = -22} -// gdbr-check:$3 = (-17, -22) +// gdb-check:$3 = (-17, -22) // === LLDB TESTS ================================================================================== @@ -24,16 +19,13 @@ // lldb-command:run // lldb-command:v *stack_val_ref -// lldbg-check:[...] { 0 = -14 1 = -19 } -// lldbr-check:((i16, f32)) *stack_val_ref = { 0 = -14 1 = -19 } +// lldb-check:[...] { 0 = -14 1 = -19 } // lldb-command:v *ref_to_unnamed -// lldbg-check:[...] { 0 = -15 1 = -20 } -// lldbr-check:((i16, f32)) *ref_to_unnamed = { 0 = -15 1 = -20 } +// lldb-check:[...] { 0 = -15 1 = -20 } // lldb-command:v *unique_val_ref -// lldbg-check:[...] { 0 = -17 1 = -22 } -// lldbr-check:((i16, f32)) *unique_val_ref = { 0 = -17 1 = -22 } +// lldb-check:[...] { 0 = -17 1 = -22 } #![allow(unused_variables)] diff --git a/tests/debuginfo/borrowed-unique-basic.rs b/tests/debuginfo/borrowed-unique-basic.rs index e952ec8cebb..7a9b4d1df82 100644 --- a/tests/debuginfo/borrowed-unique-basic.rs +++ b/tests/debuginfo/borrowed-unique-basic.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -59,64 +57,47 @@ // lldb-command:run // lldb-command:v *bool_ref -// lldbg-check:[...] true -// lldbr-check:(bool) *bool_ref = true +// lldb-check:[...] true // lldb-command:v *int_ref -// lldbg-check:[...] -1 -// lldbr-check:(isize) *int_ref = -1 +// lldb-check:[...] -1 -// NOTE: only rust-enabled lldb supports 32bit chars -// lldbr-command:print *char_ref -// lldbr-check:(char) *char_ref = 97 // lldb-command:v *i8_ref -// lldbg-check:[...] 68 -// lldbr-check:(i8) *i8_ref = 68 +// lldb-check:[...] 68 // lldb-command:v *i16_ref -// lldbg-check:[...] -16 -// lldbr-check:(i16) *i16_ref = -16 +// lldb-check:[...] -16 // lldb-command:v *i32_ref -// lldbg-check:[...] -32 -// lldbr-check:(i32) *i32_ref = -32 +// lldb-check:[...] -32 // lldb-command:v *i64_ref -// lldbg-check:[...] -64 -// lldbr-check:(i64) *i64_ref = -64 +// lldb-check:[...] -64 // lldb-command:v *uint_ref -// lldbg-check:[...] 1 -// lldbr-check:(usize) *uint_ref = 1 +// lldb-check:[...] 1 // lldb-command:v *u8_ref -// lldbg-check:[...] 100 -// lldbr-check:(u8) *u8_ref = 100 +// lldb-check:[...] 100 // lldb-command:v *u16_ref -// lldbg-check:[...] 16 -// lldbr-check:(u16) *u16_ref = 16 +// lldb-check:[...] 16 // lldb-command:v *u32_ref -// lldbg-check:[...] 32 -// lldbr-check:(u32) *u32_ref = 32 +// lldb-check:[...] 32 // lldb-command:v *u64_ref -// lldbg-check:[...] 64 -// lldbr-check:(u64) *u64_ref = 64 +// lldb-check:[...] 64 // lldb-command:v *f16_ref -// lldbg-check:[...] 1.5 -// lldbr-check:(f16) *f16_ref = 1.5 +// lldb-check:[...] 1.5 // lldb-command:v *f32_ref -// lldbg-check:[...] 2.5 -// lldbr-check:(f32) *f32_ref = 2.5 +// lldb-check:[...] 2.5 // lldb-command:v *f64_ref -// lldbg-check:[...] 3.5 -// lldbr-check:(f64) *f64_ref = 3.5 +// lldb-check:[...] 3.5 #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/box.rs b/tests/debuginfo/box.rs index 46019bcb1a7..d22566c0b17 100644 --- a/tests/debuginfo/box.rs +++ b/tests/debuginfo/box.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -9,19 +7,16 @@ // gdb-command:print *a // gdb-check:$1 = 1 // gdb-command:print *b -// gdbg-check:$2 = {__0 = 2, __1 = 3.5} -// gdbr-check:$2 = (2, 3.5) +// gdb-check:$2 = (2, 3.5) // === LLDB TESTS ================================================================================== // lldb-command:run // lldb-command:v *a -// lldbg-check:[...] 1 -// lldbr-check:(i32) *a = 1 +// lldb-check:[...] 1 // lldb-command:v *b -// lldbg-check:[...] { 0 = 2 1 = 3.5 } -// lldbr-check:((i32, f64)) *b = { 0 = 2 1 = 3.5 } +// lldb-check:[...] { 0 = 2 1 = 3.5 } #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/boxed-struct.rs b/tests/debuginfo/boxed-struct.rs index 1ee639690ea..158609fb2ed 100644 --- a/tests/debuginfo/boxed-struct.rs +++ b/tests/debuginfo/boxed-struct.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -7,12 +5,10 @@ // gdb-command:run // gdb-command:print *boxed_with_padding -// gdbg-check:$1 = {x = 99, y = 999, z = 9999, w = 99999} -// gdbr-check:$1 = boxed_struct::StructWithSomePadding {x: 99, y: 999, z: 9999, w: 99999} +// gdb-check:$1 = boxed_struct::StructWithSomePadding {x: 99, y: 999, z: 9999, w: 99999} // gdb-command:print *boxed_with_dtor -// gdbg-check:$2 = {x = 77, y = 777, z = 7777, w = 77777} -// gdbr-check:$2 = boxed_struct::StructWithDestructor {x: 77, y: 777, z: 7777, w: 77777} +// gdb-check:$2 = boxed_struct::StructWithDestructor {x: 77, y: 777, z: 7777, w: 77777} // === LLDB TESTS ================================================================================== @@ -20,12 +16,10 @@ // lldb-command:run // lldb-command:v *boxed_with_padding -// lldbg-check:[...] { x = 99 y = 999 z = 9999 w = 99999 } -// lldbr-check:(boxed_struct::StructWithSomePadding) *boxed_with_padding = { x = 99 y = 999 z = 9999 w = 99999 } +// lldb-check:[...] { x = 99 y = 999 z = 9999 w = 99999 } // lldb-command:v *boxed_with_dtor -// lldbg-check:[...] { x = 77 y = 777 z = 7777 w = 77777 } -// lldbr-check:(boxed_struct::StructWithDestructor) *boxed_with_dtor = { x = 77 y = 777 z = 7777 w = 77777 } +// lldb-check:[...] { x = 77 y = 777 z = 7777 w = 77777 } #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/by-value-non-immediate-argument.rs b/tests/debuginfo/by-value-non-immediate-argument.rs index e0ae4458d03..f0a39a45195 100644 --- a/tests/debuginfo/by-value-non-immediate-argument.rs +++ b/tests/debuginfo/by-value-non-immediate-argument.rs @@ -1,6 +1,5 @@ -//@ ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 -//@ min-lldb-version: 310 - +//@ min-lldb-version: 1800 +//@ min-gdb-version: 13.0 //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -8,13 +7,11 @@ // gdb-command:run // gdb-command:print s -// gdbg-check:$1 = {a = 1, b = 2.5} -// gdbr-check:$1 = by_value_non_immediate_argument::Struct {a: 1, b: 2.5} +// gdb-check:$1 = by_value_non_immediate_argument::Struct {a: 1, b: 2.5} // gdb-command:continue // gdb-command:print x -// gdbg-check:$2 = {a = 3, b = 4.5} -// gdbr-check:$2 = by_value_non_immediate_argument::Struct {a: 3, b: 4.5} +// gdb-check:$2 = by_value_non_immediate_argument::Struct {a: 3, b: 4.5} // gdb-command:print y // gdb-check:$3 = 5 // gdb-command:print z @@ -22,18 +19,15 @@ // gdb-command:continue // gdb-command:print a -// gdbg-check:$5 = {__0 = 7, __1 = 8, __2 = 9.5, __3 = 10.5} -// gdbr-check:$5 = (7, 8, 9.5, 10.5) +// gdb-check:$5 = (7, 8, 9.5, 10.5) // gdb-command:continue // gdb-command:print a -// gdbg-check:$6 = {__0 = 11.5, __1 = 12.5, __2 = 13, __3 = 14} -// gdbr-check:$6 = by_value_non_immediate_argument::Newtype (11.5, 12.5, 13, 14) +// gdb-check:$6 = by_value_non_immediate_argument::Newtype (11.5, 12.5, 13, 14) // gdb-command:continue // gdb-command:print x -// gdbg-check:$7 = {{RUST$ENUM$DISR = Case1, x = 0, y = 8970181431921507452}, {RUST$ENUM$DISR = Case1, [...]}} -// gdbr-check:$7 = by_value_non_immediate_argument::Enum::Case1{x: 0, y: 8970181431921507452} +// gdb-check:$7 = by_value_non_immediate_argument::Enum::Case1{x: 0, y: 8970181431921507452} // gdb-command:continue @@ -42,11 +36,11 @@ // lldb-command:run // lldb-command:v s -// lldb-check:[...] Struct { a: 1, b: 2.5 } +// lldb-check:[...] Struct { a = 1 b = 2.5 } // lldb-command:continue // lldb-command:v x -// lldb-check:[...] Struct { a: 3, b: 4.5 } +// lldb-check:[...] Struct { a = 3 b = 4.5 } // lldb-command:v y // lldb-check:[...] 5 // lldb-command:v z diff --git a/tests/debuginfo/by-value-self-argument-in-trait-impl.rs b/tests/debuginfo/by-value-self-argument-in-trait-impl.rs index 5276ec82733..6981fdfc9e1 100644 --- a/tests/debuginfo/by-value-self-argument-in-trait-impl.rs +++ b/tests/debuginfo/by-value-self-argument-in-trait-impl.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -11,13 +9,11 @@ // gdb-command:continue // gdb-command:print self -// gdbg-check:$2 = {x = 2222, y = 3333} -// gdbr-check:$2 = by_value_self_argument_in_trait_impl::Struct {x: 2222, y: 3333} +// gdb-check:$2 = by_value_self_argument_in_trait_impl::Struct {x: 2222, y: 3333} // gdb-command:continue // gdb-command:print self -// gdbg-check:$3 = {__0 = 4444.5, __1 = 5555, __2 = 6666, __3 = 7777.5} -// gdbr-check:$3 = (4444.5, 5555, 6666, 7777.5) +// gdb-check:$3 = (4444.5, 5555, 6666, 7777.5) // gdb-command:continue @@ -26,18 +22,15 @@ // lldb-command:run // lldb-command:v self -// lldbg-check:[...] 1111 -// lldbr-check:(isize) self = 1111 +// lldb-check:[...] 1111 // lldb-command:continue // lldb-command:v self -// lldbg-check:[...] { x = 2222 y = 3333 } -// lldbr-check:(by_value_self_argument_in_trait_impl::Struct) self = { x = 2222 y = 3333 } +// lldb-check:[...] { x = 2222 y = 3333 } // lldb-command:continue // lldb-command:v self -// lldbg-check:[...] { 0 = 4444.5 1 = 5555 2 = 6666 3 = 7777.5 } -// lldbr-check:((f64, isize, isize, f64)) self = { 0 = 4444.5 1 = 5555 2 = 6666 3 = 7777.5 } +// lldb-check:[...] { 0 = 4444.5 1 = 5555 2 = 6666 3 = 7777.5 } // lldb-command:continue #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/c-style-enum-in-composite.rs b/tests/debuginfo/c-style-enum-in-composite.rs index ec11d5f4655..642879cf3b6 100644 --- a/tests/debuginfo/c-style-enum-in-composite.rs +++ b/tests/debuginfo/c-style-enum-in-composite.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -7,64 +5,50 @@ // gdb-command:run // gdb-command:print tuple_interior_padding -// gdbg-check:$1 = {__0 = 0, __1 = OneHundred} -// gdbr-check:$1 = (0, c_style_enum_in_composite::AnEnum::OneHundred) +// gdb-check:$1 = (0, c_style_enum_in_composite::AnEnum::OneHundred) // gdb-command:print tuple_padding_at_end -// gdbg-check:$2 = {__0 = {__0 = 1, __1 = OneThousand}, __1 = 2} -// gdbr-check:$2 = ((1, c_style_enum_in_composite::AnEnum::OneThousand), 2) +// gdb-check:$2 = ((1, c_style_enum_in_composite::AnEnum::OneThousand), 2) // gdb-command:print tuple_different_enums -// gdbg-check:$3 = {__0 = OneThousand, __1 = MountainView, __2 = OneMillion, __3 = Vienna} -// gdbr-check:$3 = (c_style_enum_in_composite::AnEnum::OneThousand, c_style_enum_in_composite::AnotherEnum::MountainView, c_style_enum_in_composite::AnEnum::OneMillion, c_style_enum_in_composite::AnotherEnum::Vienna) +// gdb-check:$3 = (c_style_enum_in_composite::AnEnum::OneThousand, c_style_enum_in_composite::AnotherEnum::MountainView, c_style_enum_in_composite::AnEnum::OneMillion, c_style_enum_in_composite::AnotherEnum::Vienna) // gdb-command:print padded_struct -// gdbg-check:$4 = {a = 3, b = OneMillion, c = 4, d = Toronto, e = 5} -// gdbr-check:$4 = c_style_enum_in_composite::PaddedStruct {a: 3, b: c_style_enum_in_composite::AnEnum::OneMillion, c: 4, d: c_style_enum_in_composite::AnotherEnum::Toronto, e: 5} +// gdb-check:$4 = c_style_enum_in_composite::PaddedStruct {a: 3, b: c_style_enum_in_composite::AnEnum::OneMillion, c: 4, d: c_style_enum_in_composite::AnotherEnum::Toronto, e: 5} // gdb-command:print packed_struct -// gdbg-check:$5 = {a = 6, b = OneHundred, c = 7, d = Vienna, e = 8} -// gdbr-check:$5 = c_style_enum_in_composite::PackedStruct {a: 6, b: c_style_enum_in_composite::AnEnum::OneHundred, c: 7, d: c_style_enum_in_composite::AnotherEnum::Vienna, e: 8} +// gdb-check:$5 = c_style_enum_in_composite::PackedStruct {a: 6, b: c_style_enum_in_composite::AnEnum::OneHundred, c: 7, d: c_style_enum_in_composite::AnotherEnum::Vienna, e: 8} // gdb-command:print non_padded_struct -// gdbg-check:$6 = {a = OneMillion, b = MountainView, c = OneThousand, d = Toronto} -// gdbr-check:$6 = c_style_enum_in_composite::NonPaddedStruct {a: c_style_enum_in_composite::AnEnum::OneMillion, b: c_style_enum_in_composite::AnotherEnum::MountainView, c: c_style_enum_in_composite::AnEnum::OneThousand, d: c_style_enum_in_composite::AnotherEnum::Toronto} +// gdb-check:$6 = c_style_enum_in_composite::NonPaddedStruct {a: c_style_enum_in_composite::AnEnum::OneMillion, b: c_style_enum_in_composite::AnotherEnum::MountainView, c: c_style_enum_in_composite::AnEnum::OneThousand, d: c_style_enum_in_composite::AnotherEnum::Toronto} // gdb-command:print struct_with_drop -// gdbg-check:$7 = {__0 = {a = OneHundred, b = Vienna}, __1 = 9} -// gdbr-check:$7 = (c_style_enum_in_composite::StructWithDrop {a: c_style_enum_in_composite::AnEnum::OneHundred, b: c_style_enum_in_composite::AnotherEnum::Vienna}, 9) +// gdb-check:$7 = (c_style_enum_in_composite::StructWithDrop {a: c_style_enum_in_composite::AnEnum::OneHundred, b: c_style_enum_in_composite::AnotherEnum::Vienna}, 9) // === LLDB TESTS ================================================================================== // lldb-command:run // lldb-command:v tuple_interior_padding -// lldbg-check:[...] { 0 = 0 1 = OneHundred } -// lldbr-check:((i16, c_style_enum_in_composite::AnEnum)) tuple_interior_padding = { 0 = 0 1 = OneHundred } +// lldb-check:[...] { 0 = 0 1 = OneHundred } // lldb-command:v tuple_padding_at_end -// lldbg-check:[...] { 0 = { 0 = 1 1 = OneThousand } 1 = 2 } -// lldbr-check:(((u64, c_style_enum_in_composite::AnEnum), u64)) tuple_padding_at_end = { 0 = { 0 = 1 1 = OneThousand } 1 = 2 } +// lldb-check:[...] { 0 = { 0 = 1 1 = OneThousand } 1 = 2 } // lldb-command:v tuple_different_enums -// lldbg-check:[...] { 0 = OneThousand 1 = MountainView 2 = OneMillion 3 = Vienna } -// lldbr-check:((c_style_enum_in_composite::AnEnum, c_style_enum_in_composite::AnotherEnum, c_style_enum_in_composite::AnEnum, c_style_enum_in_composite::AnotherEnum)) tuple_different_enums = { 0 = c_style_enum_in_composite::AnEnum::OneThousand 1 = c_style_enum_in_composite::AnotherEnum::MountainView 2 = c_style_enum_in_composite::AnEnum::OneMillion 3 = c_style_enum_in_composite::AnotherEnum::Vienna } +// lldb-check:[...] { 0 = OneThousand 1 = MountainView 2 = OneMillion 3 = Vienna } // lldb-command:v padded_struct -// lldbg-check:[...] { a = 3 b = OneMillion c = 4 d = Toronto e = 5 } -// lldbr-check:(c_style_enum_in_composite::PaddedStruct) padded_struct = { a = 3 b = c_style_enum_in_composite::AnEnum::OneMillion c = 4 d = Toronto e = 5 } +// lldb-check:[...] { a = 3 b = OneMillion c = 4 d = Toronto e = 5 } // lldb-command:v packed_struct -// lldbg-check:[...] { a = 6 b = OneHundred c = 7 d = Vienna e = 8 } -// lldbr-check:(c_style_enum_in_composite::PackedStruct) packed_struct = { a = 6 b = c_style_enum_in_composite::AnEnum::OneHundred c = 7 d = Vienna e = 8 } +// lldb-check:[...] { a = 6 b = OneHundred c = 7 d = Vienna e = 8 } // lldb-command:v non_padded_struct -// lldbg-check:[...] { a = OneMillion b = MountainView c = OneThousand d = Toronto } -// lldbr-check:(c_style_enum_in_composite::NonPaddedStruct) non_padded_struct = { a = c_style_enum_in_composite::AnEnum::OneMillion, b = c_style_enum_in_composite::AnotherEnum::MountainView, c = c_style_enum_in_composite::AnEnum::OneThousand, d = c_style_enum_in_composite::AnotherEnum::Toronto } +// lldb-check:[...] { a = OneMillion b = MountainView c = OneThousand d = Toronto } // lldb-command:v struct_with_drop -// lldbg-check:[...] { 0 = { a = OneHundred b = Vienna } 1 = 9 } -// lldbr-check:((c_style_enum_in_composite::StructWithDrop, i64)) struct_with_drop = { 0 = { a = c_style_enum_in_composite::AnEnum::OneHundred b = c_style_enum_in_composite::AnotherEnum::Vienna } 1 = 9 } +// lldb-check:[...] { 0 = { a = OneHundred b = Vienna } 1 = 9 } #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/c-style-enum.rs b/tests/debuginfo/c-style-enum.rs index 395b94c59a4..08378f7af18 100644 --- a/tests/debuginfo/c-style-enum.rs +++ b/tests/debuginfo/c-style-enum.rs @@ -1,95 +1,64 @@ //@ ignore-aarch64 -//@ ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 -//@ min-lldb-version: 310 //@ compile-flags:-g // === GDB TESTS =================================================================================== -// gdbg-command:print 'c_style_enum::SINGLE_VARIANT' -// gdbr-command:print c_style_enum::SINGLE_VARIANT -// gdbg-check:$1 = TheOnlyVariant -// gdbr-check:$1 = c_style_enum::SingleVariant::TheOnlyVariant +// gdb-command:print c_style_enum::SINGLE_VARIANT +// gdb-check:$1 = c_style_enum::SingleVariant::TheOnlyVariant -// gdbg-command:print 'c_style_enum::AUTO_ONE' -// gdbr-command:print c_style_enum::AUTO_ONE -// gdbg-check:$2 = One -// gdbr-check:$2 = c_style_enum::AutoDiscriminant::One +// gdb-command:print c_style_enum::AUTO_ONE +// gdb-check:$2 = c_style_enum::AutoDiscriminant::One -// gdbg-command:print 'c_style_enum::AUTO_TWO' -// gdbr-command:print c_style_enum::AUTO_TWO -// gdbg-check:$3 = One -// gdbr-check:$3 = c_style_enum::AutoDiscriminant::One +// gdb-command:print c_style_enum::AUTO_TWO +// gdb-check:$3 = c_style_enum::AutoDiscriminant::One -// gdbg-command:print 'c_style_enum::AUTO_THREE' -// gdbr-command:print c_style_enum::AUTO_THREE -// gdbg-check:$4 = One -// gdbr-check:$4 = c_style_enum::AutoDiscriminant::One +// gdb-command:print c_style_enum::AUTO_THREE +// gdb-check:$4 = c_style_enum::AutoDiscriminant::One -// gdbg-command:print 'c_style_enum::MANUAL_ONE' -// gdbr-command:print c_style_enum::MANUAL_ONE -// gdbg-check:$5 = OneHundred -// gdbr-check:$5 = c_style_enum::ManualDiscriminant::OneHundred +// gdb-command:print c_style_enum::MANUAL_ONE +// gdb-check:$5 = c_style_enum::ManualDiscriminant::OneHundred -// gdbg-command:print 'c_style_enum::MANUAL_TWO' -// gdbr-command:print c_style_enum::MANUAL_TWO -// gdbg-check:$6 = OneHundred -// gdbr-check:$6 = c_style_enum::ManualDiscriminant::OneHundred +// gdb-command:print c_style_enum::MANUAL_TWO +// gdb-check:$6 = c_style_enum::ManualDiscriminant::OneHundred -// gdbg-command:print 'c_style_enum::MANUAL_THREE' -// gdbr-command:print c_style_enum::MANUAL_THREE -// gdbg-check:$7 = OneHundred -// gdbr-check:$7 = c_style_enum::ManualDiscriminant::OneHundred +// gdb-command:print c_style_enum::MANUAL_THREE +// gdb-check:$7 = c_style_enum::ManualDiscriminant::OneHundred // gdb-command:run // gdb-command:print auto_one -// gdbg-check:$8 = One -// gdbr-check:$8 = c_style_enum::AutoDiscriminant::One +// gdb-check:$8 = c_style_enum::AutoDiscriminant::One // gdb-command:print auto_two -// gdbg-check:$9 = Two -// gdbr-check:$9 = c_style_enum::AutoDiscriminant::Two +// gdb-check:$9 = c_style_enum::AutoDiscriminant::Two // gdb-command:print auto_three -// gdbg-check:$10 = Three -// gdbr-check:$10 = c_style_enum::AutoDiscriminant::Three +// gdb-check:$10 = c_style_enum::AutoDiscriminant::Three // gdb-command:print manual_one_hundred -// gdbg-check:$11 = OneHundred -// gdbr-check:$11 = c_style_enum::ManualDiscriminant::OneHundred +// gdb-check:$11 = c_style_enum::ManualDiscriminant::OneHundred // gdb-command:print manual_one_thousand -// gdbg-check:$12 = OneThousand -// gdbr-check:$12 = c_style_enum::ManualDiscriminant::OneThousand +// gdb-check:$12 = c_style_enum::ManualDiscriminant::OneThousand // gdb-command:print manual_one_million -// gdbg-check:$13 = OneMillion -// gdbr-check:$13 = c_style_enum::ManualDiscriminant::OneMillion +// gdb-check:$13 = c_style_enum::ManualDiscriminant::OneMillion // gdb-command:print single_variant -// gdbg-check:$14 = TheOnlyVariant -// gdbr-check:$14 = c_style_enum::SingleVariant::TheOnlyVariant +// gdb-check:$14 = c_style_enum::SingleVariant::TheOnlyVariant -// gdbg-command:print 'c_style_enum::AUTO_TWO' -// gdbr-command:print AUTO_TWO -// gdbg-check:$15 = Two -// gdbr-check:$15 = c_style_enum::AutoDiscriminant::Two +// gdb-command:print AUTO_TWO +// gdb-check:$15 = c_style_enum::AutoDiscriminant::Two -// gdbg-command:print 'c_style_enum::AUTO_THREE' -// gdbr-command:print AUTO_THREE -// gdbg-check:$16 = Three -// gdbr-check:$16 = c_style_enum::AutoDiscriminant::Three +// gdb-command:print AUTO_THREE +// gdb-check:$16 = c_style_enum::AutoDiscriminant::Three -// gdbg-command:print 'c_style_enum::MANUAL_TWO' -// gdbr-command:print MANUAL_TWO -// gdbg-check:$17 = OneThousand -// gdbr-check:$17 = c_style_enum::ManualDiscriminant::OneThousand +// gdb-command:print MANUAL_TWO +// gdb-check:$17 = c_style_enum::ManualDiscriminant::OneThousand -// gdbg-command:print 'c_style_enum::MANUAL_THREE' -// gdbr-command:print MANUAL_THREE -// gdbg-check:$18 = OneMillion -// gdbr-check:$18 = c_style_enum::ManualDiscriminant::OneMillion +// gdb-command:print MANUAL_THREE +// gdb-check:$18 = c_style_enum::ManualDiscriminant::OneMillion // === LLDB TESTS ================================================================================== @@ -97,32 +66,25 @@ // lldb-command:run // lldb-command:v auto_one -// lldbg-check:[...] One -// lldbr-check:(c_style_enum::AutoDiscriminant) auto_one = c_style_enum::AutoDiscriminant::One +// lldb-check:[...] One // lldb-command:v auto_two -// lldbg-check:[...] Two -// lldbr-check:(c_style_enum::AutoDiscriminant) auto_two = c_style_enum::AutoDiscriminant::Two +// lldb-check:[...] Two // lldb-command:v auto_three -// lldbg-check:[...] Three -// lldbr-check:(c_style_enum::AutoDiscriminant) auto_three = c_style_enum::AutoDiscriminant::Three +// lldb-check:[...] Three // lldb-command:v manual_one_hundred -// lldbg-check:[...] OneHundred -// lldbr-check:(c_style_enum::ManualDiscriminant) manual_one_hundred = c_style_enum::ManualDiscriminant::OneHundred +// lldb-check:[...] OneHundred // lldb-command:v manual_one_thousand -// lldbg-check:[...] OneThousand -// lldbr-check:(c_style_enum::ManualDiscriminant) manual_one_thousand = c_style_enum::ManualDiscriminant::OneThousand +// lldb-check:[...] OneThousand // lldb-command:v manual_one_million -// lldbg-check:[...] OneMillion -// lldbr-check:(c_style_enum::ManualDiscriminant) manual_one_million = c_style_enum::ManualDiscriminant::OneMillion +// lldb-check:[...] OneMillion // lldb-command:v single_variant -// lldbg-check:[...] TheOnlyVariant -// lldbr-check:(c_style_enum::SingleVariant) single_variant = c_style_enum::SingleVariant::TheOnlyVariant +// lldb-check:[...] TheOnlyVariant #![allow(unused_variables)] #![allow(dead_code)] diff --git a/tests/debuginfo/captured-fields-1.rs b/tests/debuginfo/captured-fields-1.rs index d96f2590570..69ca3ecd812 100644 --- a/tests/debuginfo/captured-fields-1.rs +++ b/tests/debuginfo/captured-fields-1.rs @@ -4,44 +4,44 @@ // gdb-command:run // gdb-command:print test -// gdbr-check:$1 = captured_fields_1::main::{closure_env#0} {_ref__my_ref__my_field1: 0x[...]} +// gdb-check:$1 = captured_fields_1::main::{closure_env#0} {_ref__my_ref__my_field1: 0x[...]} // gdb-command:continue // gdb-command:print test -// gdbr-check:$2 = captured_fields_1::main::{closure_env#1} {_ref__my_ref__my_field2: 0x[...]} +// gdb-check:$2 = captured_fields_1::main::{closure_env#1} {_ref__my_ref__my_field2: 0x[...]} // gdb-command:continue // gdb-command:print test -// gdbr-check:$3 = captured_fields_1::main::{closure_env#2} {_ref__my_ref: 0x[...]} +// gdb-check:$3 = captured_fields_1::main::{closure_env#2} {_ref__my_ref: 0x[...]} // gdb-command:continue // gdb-command:print test -// gdbr-check:$4 = captured_fields_1::main::{closure_env#3} {my_ref: 0x[...]} +// gdb-check:$4 = captured_fields_1::main::{closure_env#3} {my_ref: 0x[...]} // gdb-command:continue // gdb-command:print test -// gdbr-check:$5 = captured_fields_1::main::{closure_env#4} {my_var__my_field2: 22} +// gdb-check:$5 = captured_fields_1::main::{closure_env#4} {my_var__my_field2: 22} // gdb-command:continue // gdb-command:print test -// gdbr-check:$6 = captured_fields_1::main::{closure_env#5} {my_var: captured_fields_1::MyStruct {my_field1: 11, my_field2: 22}} +// gdb-check:$6 = captured_fields_1::main::{closure_env#5} {my_var: captured_fields_1::MyStruct {my_field1: 11, my_field2: 22}} // gdb-command:continue // === LLDB TESTS ================================================================================== // lldb-command:run // lldb-command:v test -// lldbg-check:(captured_fields_1::main::{closure_env#0}) test = { _ref__my_ref__my_field1 = 0x[...] } +// lldb-check:(captured_fields_1::main::{closure_env#0}) test = { _ref__my_ref__my_field1 = 0x[...] } // lldb-command:continue // lldb-command:v test -// lldbg-check:(captured_fields_1::main::{closure_env#1}) test = { _ref__my_ref__my_field2 = 0x[...] } +// lldb-check:(captured_fields_1::main::{closure_env#1}) test = { _ref__my_ref__my_field2 = 0x[...] } // lldb-command:continue // lldb-command:v test -// lldbg-check:(captured_fields_1::main::{closure_env#2}) test = { _ref__my_ref = 0x[...] } +// lldb-check:(captured_fields_1::main::{closure_env#2}) test = { _ref__my_ref = 0x[...] } // lldb-command:continue // lldb-command:v test -// lldbg-check:(captured_fields_1::main::{closure_env#3}) test = { my_ref = 0x[...] } +// lldb-check:(captured_fields_1::main::{closure_env#3}) test = { my_ref = 0x[...] } // lldb-command:continue // lldb-command:v test -// lldbg-check:(captured_fields_1::main::{closure_env#4}) test = { my_var__my_field2 = 22 } +// lldb-check:(captured_fields_1::main::{closure_env#4}) test = { my_var__my_field2 = 22 } // lldb-command:continue // lldb-command:v test -// lldbg-check:(captured_fields_1::main::{closure_env#5}) test = { my_var = { my_field1 = 11 my_field2 = 22 } } +// lldb-check:(captured_fields_1::main::{closure_env#5}) test = { my_var = { my_field1 = 11 my_field2 = 22 } } // lldb-command:continue #![allow(unused)] diff --git a/tests/debuginfo/captured-fields-2.rs b/tests/debuginfo/captured-fields-2.rs index 446c5c70fef..24bff1d3f35 100644 --- a/tests/debuginfo/captured-fields-2.rs +++ b/tests/debuginfo/captured-fields-2.rs @@ -4,20 +4,20 @@ // gdb-command:run // gdb-command:print my_ref__my_field1 -// gdbr-check:$1 = 11 +// gdb-check:$1 = 11 // gdb-command:continue // gdb-command:print my_var__my_field2 -// gdbr-check:$2 = 22 +// gdb-check:$2 = 22 // gdb-command:continue // === LLDB TESTS ================================================================================== // lldb-command:run // lldb-command:v my_ref__my_field1 -// lldbg-check:(unsigned int) my_ref__my_field1 = 11 +// lldb-check:(unsigned int) my_ref__my_field1 = 11 // lldb-command:continue // lldb-command:v my_var__my_field2 -// lldbg-check:(unsigned int) my_var__my_field2 = 22 +// lldb-check:(unsigned int) my_var__my_field2 = 22 // lldb-command:continue #![allow(unused)] diff --git a/tests/debuginfo/closure-in-generic-function.rs b/tests/debuginfo/closure-in-generic-function.rs index ef0f2b0b464..0c6a6fdfca1 100644 --- a/tests/debuginfo/closure-in-generic-function.rs +++ b/tests/debuginfo/closure-in-generic-function.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -24,19 +22,15 @@ // lldb-command:run // lldb-command:v x -// lldbg-check:[...] 0.5 -// lldbr-check:(f64) x = 0.5 +// lldb-check:[...] 0.5 // lldb-command:v y -// lldbg-check:[...] 10 -// lldbr-check:(i32) y = 10 +// lldb-check:[...] 10 // lldb-command:continue // lldb-command:v *x -// lldbg-check:[...] 29 -// lldbr-check:(i32) *x = 29 +// lldb-check:[...] 29 // lldb-command:v *y -// lldbg-check:[...] 110 -// lldbr-check:(i32) *y = 110 +// lldb-check:[...] 110 // lldb-command:continue #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/constant-debug-locs.rs b/tests/debuginfo/constant-debug-locs.rs index d834d990985..81115fc3c38 100644 --- a/tests/debuginfo/constant-debug-locs.rs +++ b/tests/debuginfo/constant-debug-locs.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g #![allow(dead_code, unused_variables)] diff --git a/tests/debuginfo/constant-in-match-pattern.rs b/tests/debuginfo/constant-in-match-pattern.rs index f34284be164..952db216deb 100644 --- a/tests/debuginfo/constant-in-match-pattern.rs +++ b/tests/debuginfo/constant-in-match-pattern.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g #![allow(dead_code, unused_variables)] diff --git a/tests/debuginfo/coroutine-locals.rs b/tests/debuginfo/coroutine-locals.rs index c019998040b..f3593adc945 100644 --- a/tests/debuginfo/coroutine-locals.rs +++ b/tests/debuginfo/coroutine-locals.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== diff --git a/tests/debuginfo/coroutine-objects.rs b/tests/debuginfo/coroutine-objects.rs index 746b7e40eda..242c76c2989 100644 --- a/tests/debuginfo/coroutine-objects.rs +++ b/tests/debuginfo/coroutine-objects.rs @@ -1,5 +1,3 @@ -// Require a gdb that can read DW_TAG_variant_part. -//@ min-gdb-version: 8.2 //@ min-lldb-version: 1800 // LLDB (18.1+) now supports DW_TAG_variant_part, but there is some bug in either compiler or LLDB diff --git a/tests/debuginfo/cross-crate-spans.rs b/tests/debuginfo/cross-crate-spans.rs index cf3f8e1eadf..e337aaf5a6c 100644 --- a/tests/debuginfo/cross-crate-spans.rs +++ b/tests/debuginfo/cross-crate-spans.rs @@ -1,12 +1,6 @@ #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] -//@ min-lldb-version: 310 - -// This fails on lldb 6.0.1 on x86-64 Fedora 28; so mark it macOS-only -// for now. -//@ only-macos - //@ aux-build:cross_crate_spans.rs extern crate cross_crate_spans; @@ -19,8 +13,7 @@ extern crate cross_crate_spans; // gdb-command:run // gdb-command:print result -// gdbg-check:$1 = {__0 = 17, __1 = 17} -// gdbr-check:$1 = (17, 17) +// gdb-check:$1 = (17, 17) // gdb-command:print a_variable // gdb-check:$2 = 123456789 // gdb-command:print another_variable @@ -28,8 +21,7 @@ extern crate cross_crate_spans; // gdb-command:continue // gdb-command:print result -// gdbg-check:$4 = {__0 = 1212, __1 = 1212} -// gdbr-check:$4 = (1212, 1212) +// gdb-check:$4 = (1212, 1212) // gdb-command:print a_variable // gdb-check:$5 = 123456789 // gdb-command:print another_variable @@ -44,25 +36,19 @@ extern crate cross_crate_spans; // lldb-command:run // lldb-command:v result -// lldbg-check:[...] { 0 = 17 1 = 17 } -// lldbr-check:((u32, u32)) result = { 0 = 17 1 = 17 } +// lldb-check:[...] { 0 = 17 1 = 17 } // lldb-command:v a_variable -// lldbg-check:[...] 123456789 -// lldbr-check:(u32) a_variable = 123456789 +// lldb-check:[...] 123456789 // lldb-command:v another_variable -// lldbg-check:[...] 123456789.5 -// lldbr-check:(f64) another_variable = 123456789.5 +// lldb-check:[...] 123456789.5 // lldb-command:continue // lldb-command:v result -// lldbg-check:[...] { 0 = 1212 1 = 1212 } -// lldbr-check:((i16, i16)) result = { 0 = 1212 1 = 1212 } +// lldb-check:[...] { 0 = 1212 1 = 1212 } // lldb-command:v a_variable -// lldbg-check:[...] 123456789 -// lldbr-check:(u32) a_variable = 123456789 +// lldb-check:[...] 123456789 // lldb-command:v another_variable -// lldbg-check:[...] 123456789.5 -// lldbr-check:(f64) another_variable = 123456789.5 +// lldb-check:[...] 123456789.5 // lldb-command:continue diff --git a/tests/debuginfo/cross-crate-type-uniquing.rs b/tests/debuginfo/cross-crate-type-uniquing.rs index 88f8bac5d6f..28ebc343884 100644 --- a/tests/debuginfo/cross-crate-type-uniquing.rs +++ b/tests/debuginfo/cross-crate-type-uniquing.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ aux-build:cross_crate_debuginfo_type_uniquing.rs extern crate cross_crate_debuginfo_type_uniquing; diff --git a/tests/debuginfo/destructured-fn-argument.rs b/tests/debuginfo/destructured-fn-argument.rs index 74e18a594d7..37a7bb2b778 100644 --- a/tests/debuginfo/destructured-fn-argument.rs +++ b/tests/debuginfo/destructured-fn-argument.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -23,15 +21,13 @@ // gdb-command:print a // gdb-check:$6 = 5 // gdb-command:print b -// gdbg-check:$7 = {__0 = 6, __1 = 7} -// gdbr-check:$7 = (6, 7) +// gdb-check:$7 = (6, 7) // gdb-command:continue // gdb-command:print h // gdb-check:$8 = 8 // gdb-command:print i -// gdbg-check:$9 = {a = 9, b = 10} -// gdbr-check:$9 = destructured_fn_argument::Struct {a: 9, b: 10} +// gdb-check:$9 = destructured_fn_argument::Struct {a: 9, b: 10} // gdb-command:print j // gdb-check:$10 = 11 // gdb-command:continue @@ -57,8 +53,7 @@ // gdb-command:print q // gdb-check:$17 = 20 // gdb-command:print r -// gdbg-check:$18 = {a = 21, b = 22} -// gdbr-check:$18 = destructured_fn_argument::Struct {a: 21, b: 22} +// gdb-check:$18 = destructured_fn_argument::Struct {a: 21, b: 22} // gdb-command:continue // gdb-command:print s @@ -88,13 +83,11 @@ // gdb-command:continue // gdb-command:print aa -// gdbg-check:$30 = {__0 = 34, __1 = 35} -// gdbr-check:$30 = (34, 35) +// gdb-check:$30 = (34, 35) // gdb-command:continue // gdb-command:print bb -// gdbg-check:$31 = {__0 = 36, __1 = 37} -// gdbr-check:$31 = (36, 37) +// gdb-check:$31 = (36, 37) // gdb-command:continue // gdb-command:print cc @@ -102,20 +95,17 @@ // gdb-command:continue // gdb-command:print dd -// gdbg-check:$33 = {__0 = 40, __1 = 41, __2 = 42} -// gdbr-check:$33 = (40, 41, 42) +// gdb-check:$33 = (40, 41, 42) // gdb-command:continue // gdb-command:print *ee -// gdbg-check:$34 = {__0 = 43, __1 = 44, __2 = 45} -// gdbr-check:$34 = (43, 44, 45) +// gdb-check:$34 = (43, 44, 45) // gdb-command:continue // gdb-command:print *ff // gdb-check:$35 = 46 // gdb-command:print gg -// gdbg-check:$36 = {__0 = 47, __1 = 48} -// gdbr-check:$36 = (47, 48) +// gdb-check:$36 = (47, 48) // gdb-command:continue // gdb-command:print *hh @@ -164,196 +154,147 @@ // lldb-command:run // lldb-command:v a -// lldbg-check:[...] 1 -// lldbr-check:(isize) a = 1 +// lldb-check:[...] 1 // lldb-command:v b -// lldbg-check:[...] false -// lldbr-check:(bool) b = false +// lldb-check:[...] false // lldb-command:continue // lldb-command:v a -// lldbg-check:[...] 2 -// lldbr-check:(isize) a = 2 +// lldb-check:[...] 2 // lldb-command:v b -// lldbg-check:[...] 3 -// lldbr-check:(u16) b = 3 +// lldb-check:[...] 3 // lldb-command:v c -// lldbg-check:[...] 4 -// lldbr-check:(u16) c = 4 +// lldb-check:[...] 4 // lldb-command:continue // lldb-command:v a -// lldbg-check:[...] 5 -// lldbr-check:(isize) a = 5 +// lldb-check:[...] 5 // lldb-command:v b -// lldbg-check:[...] { 0 = 6 1 = 7 } -// lldbr-check:((u32, u32)) b = { 0 = 6 1 = 7 } +// lldb-check:[...] { 0 = 6 1 = 7 } // lldb-command:continue // lldb-command:v h -// lldbg-check:[...] 8 -// lldbr-check:(i16) h = 8 +// lldb-check:[...] 8 // lldb-command:v i -// lldbg-check:[...] { a = 9 b = 10 } -// lldbr-check:(destructured_fn_argument::Struct) i = { a = 9 b = 10 } +// lldb-check:[...] { a = 9 b = 10 } // lldb-command:v j -// lldbg-check:[...] 11 -// lldbr-check:(i16) j = 11 +// lldb-check:[...] 11 // lldb-command:continue // lldb-command:v k -// lldbg-check:[...] 12 -// lldbr-check:(i64) k = 12 +// lldb-check:[...] 12 // lldb-command:v l -// lldbg-check:[...] 13 -// lldbr-check:(i32) l = 13 +// lldb-check:[...] 13 // lldb-command:continue // lldb-command:v m -// lldbg-check:[...] 14 -// lldbr-check:(isize) m = 14 +// lldb-check:[...] 14 // lldb-command:v n -// lldbg-check:[...] 16 -// lldbr-check:(i32) n = 16 +// lldb-check:[...] 16 // lldb-command:continue // lldb-command:v o -// lldbg-check:[...] 18 -// lldbr-check:(i32) o = 18 +// lldb-check:[...] 18 // lldb-command:continue // lldb-command:v p -// lldbg-check:[...] 19 -// lldbr-check:(i64) p = 19 +// lldb-check:[...] 19 // lldb-command:v q -// lldbg-check:[...] 20 -// lldbr-check:(i32) q = 20 +// lldb-check:[...] 20 // lldb-command:v r -// lldbg-check:[...] { a = 21 b = 22 } -// lldbr-check:(destructured_fn_argument::Struct) r = { a = 21, b = 22 } +// lldb-check:[...] { a = 21 b = 22 } // lldb-command:continue // lldb-command:v s -// lldbg-check:[...] 24 -// lldbr-check:(i32) s = 24 +// lldb-check:[...] 24 // lldb-command:v t -// lldbg-check:[...] 23 -// lldbr-check:(i64) t = 23 +// lldb-check:[...] 23 // lldb-command:continue // lldb-command:v u -// lldbg-check:[...] 25 -// lldbr-check:(i16) u = 25 +// lldb-check:[...] 25 // lldb-command:v v -// lldbg-check:[...] 26 -// lldbr-check:(i32) v = 26 +// lldb-check:[...] 26 // lldb-command:v w -// lldbg-check:[...] 27 -// lldbr-check:(i64) w = 27 +// lldb-check:[...] 27 // lldb-command:v x -// lldbg-check:[...] 28 -// lldbr-check:(i32) x = 28 +// lldb-check:[...] 28 // lldb-command:v y -// lldbg-check:[...] 29 -// lldbr-check:(i64) y = 29 +// lldb-check:[...] 29 // lldb-command:v z -// lldbg-check:[...] 30 -// lldbr-check:(i32) z = 30 +// lldb-check:[...] 30 // lldb-command:v ae -// lldbg-check:[...] 31 -// lldbr-check:(i64) ae = 31 +// lldb-check:[...] 31 // lldb-command:v oe -// lldbg-check:[...] 32 -// lldbr-check:(i32) oe = 32 +// lldb-check:[...] 32 // lldb-command:v ue -// lldbg-check:[...] 33 -// lldbr-check:(u16) ue = 33 +// lldb-check:[...] 33 // lldb-command:continue // lldb-command:v aa -// lldbg-check:[...] { 0 = 34 1 = 35 } -// lldbr-check:((isize, isize)) aa = { 0 = 34 1 = 35 } +// lldb-check:[...] { 0 = 34 1 = 35 } // lldb-command:continue // lldb-command:v bb -// lldbg-check:[...] { 0 = 36 1 = 37 } -// lldbr-check:((isize, isize)) bb = { 0 = 36 1 = 37 } +// lldb-check:[...] { 0 = 36 1 = 37 } // lldb-command:continue // lldb-command:v cc -// lldbg-check:[...] 38 -// lldbr-check:(isize) cc = 38 +// lldb-check:[...] 38 // lldb-command:continue // lldb-command:v dd -// lldbg-check:[...] { 0 = 40 1 = 41 2 = 42 } -// lldbr-check:((isize, isize, isize)) dd = { 0 = 40 1 = 41 2 = 42 } +// lldb-check:[...] { 0 = 40 1 = 41 2 = 42 } // lldb-command:continue // lldb-command:v *ee -// lldbg-check:[...] { 0 = 43 1 = 44 2 = 45 } -// lldbr-check:((isize, isize, isize)) *ee = { 0 = 43 1 = 44 2 = 45 } +// lldb-check:[...] { 0 = 43 1 = 44 2 = 45 } // lldb-command:continue // lldb-command:v *ff -// lldbg-check:[...] 46 -// lldbr-check:(isize) *ff = 46 +// lldb-check:[...] 46 // lldb-command:v gg -// lldbg-check:[...] { 0 = 47 1 = 48 } -// lldbr-check:((isize, isize)) gg = { 0 = 47 1 = 48 } +// lldb-check:[...] { 0 = 47 1 = 48 } // lldb-command:continue // lldb-command:v *hh -// lldbg-check:[...] 50 -// lldbr-check:(i32) *hh = 50 +// lldb-check:[...] 50 // lldb-command:continue // lldb-command:v ii -// lldbg-check:[...] 51 -// lldbr-check:(i32) ii = 51 +// lldb-check:[...] 51 // lldb-command:continue // lldb-command:v *jj -// lldbg-check:[...] 52 -// lldbr-check:(i32) *jj = 52 +// lldb-check:[...] 52 // lldb-command:continue // lldb-command:v kk -// lldbg-check:[...] 53 -// lldbr-check:(f64) kk = 53 +// lldb-check:[...] 53 // lldb-command:v ll -// lldbg-check:[...] 54 -// lldbr-check:(isize) ll = 54 +// lldb-check:[...] 54 // lldb-command:continue // lldb-command:v mm -// lldbg-check:[...] 55 -// lldbr-check:(f64) mm = 55 +// lldb-check:[...] 55 // lldb-command:v *nn -// lldbg-check:[...] 56 -// lldbr-check:(isize) *nn = 56 +// lldb-check:[...] 56 // lldb-command:continue // lldb-command:v oo -// lldbg-check:[...] 57 -// lldbr-check:(isize) oo = 57 +// lldb-check:[...] 57 // lldb-command:v pp -// lldbg-check:[...] 58 -// lldbr-check:(isize) pp = 58 +// lldb-check:[...] 58 // lldb-command:v qq -// lldbg-check:[...] 59 -// lldbr-check:(isize) qq = 59 +// lldb-check:[...] 59 // lldb-command:continue // lldb-command:v rr -// lldbg-check:[...] 60 -// lldbr-check:(isize) rr = 60 +// lldb-check:[...] 60 // lldb-command:v ss -// lldbg-check:[...] 61 -// lldbr-check:(isize) ss = 61 +// lldb-check:[...] 61 // lldb-command:v tt -// lldbg-check:[...] 62 -// lldbr-check:(isize) tt = 62 +// lldb-check:[...] 62 // lldb-command:continue #![allow(unused_variables)] diff --git a/tests/debuginfo/destructured-for-loop-variable.rs b/tests/debuginfo/destructured-for-loop-variable.rs index 1cad8bcfacb..cc16be1268a 100644 --- a/tests/debuginfo/destructured-for-loop-variable.rs +++ b/tests/debuginfo/destructured-for-loop-variable.rs @@ -1,9 +1,3 @@ -//@ min-lldb-version: 310 - -// This fails on lldb 6.0.1 on x86-64 Fedora 28; so mark it macOS-only -// for now. -//@ only-macos - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -67,13 +61,11 @@ // gdb-command:continue // gdb-command:print simple_struct_ident -// gdbg-check:$23 = {x = 3537, y = 35437.5, z = true} -// gdbr-check:$23 = destructured_for_loop_variable::Struct {x: 3537, y: 35437.5, z: true} +// gdb-check:$23 = destructured_for_loop_variable::Struct {x: 3537, y: 35437.5, z: true} // gdb-command:continue // gdb-command:print simple_tuple_ident -// gdbg-check:$24 = {__0 = 34903493, __1 = 232323} -// gdbr-check:$24 = (34903493, 232323) +// gdb-check:$24 = (34903493, 232323) // gdb-command:continue // === LLDB TESTS ================================================================================== @@ -85,90 +77,66 @@ // DESTRUCTURED STRUCT // lldb-command:v x -// lldbg-check:[...] 400 -// lldbr-check:(i16) x = 400 +// lldb-check:[...] 400 // lldb-command:v y -// lldbg-check:[...] 401.5 -// lldbr-check:(f32) y = 401.5 +// lldb-check:[...] 401.5 // lldb-command:v z -// lldbg-check:[...] true -// lldbr-check:(bool) z = true +// lldb-check:[...] true // lldb-command:continue // DESTRUCTURED TUPLE // lldb-command:v _i8 -// lldbg-check:[...] 0x6f -// lldbr-check:(i8) _i8 = 111 +// lldb-check:[...] 0x6f // lldb-command:v _u8 -// lldbg-check:[...] 0x70 -// lldbr-check:(u8) _u8 = 112 +// lldb-check:[...] 0x70 // lldb-command:v _i16 -// lldbg-check:[...] -113 -// lldbr-check:(i16) _i16 = -113 +// lldb-check:[...] -113 // lldb-command:v _u16 -// lldbg-check:[...] 114 -// lldbr-check:(u16) _u16 = 114 +// lldb-check:[...] 114 // lldb-command:v _i32 -// lldbg-check:[...] -115 -// lldbr-check:(i32) _i32 = -115 +// lldb-check:[...] -115 // lldb-command:v _u32 -// lldbg-check:[...] 116 -// lldbr-check:(u32) _u32 = 116 +// lldb-check:[...] 116 // lldb-command:v _i64 -// lldbg-check:[...] -117 -// lldbr-check:(i64) _i64 = -117 +// lldb-check:[...] -117 // lldb-command:v _u64 -// lldbg-check:[...] 118 -// lldbr-check:(u64) _u64 = 118 +// lldb-check:[...] 118 // lldb-command:v _f32 -// lldbg-check:[...] 119.5 -// lldbr-check:(f32) _f32 = 119.5 +// lldb-check:[...] 119.5 // lldb-command:v _f64 -// lldbg-check:[...] 120.5 -// lldbr-check:(f64) _f64 = 120.5 +// lldb-check:[...] 120.5 // lldb-command:continue // MORE COMPLEX CASE // lldb-command:v v1 -// lldbg-check:[...] 80000 -// lldbr-check:(i32) v1 = 80000 +// lldb-check:[...] 80000 // lldb-command:v x1 -// lldbg-check:[...] 8000 -// lldbr-check:(i16) x1 = 8000 +// lldb-check:[...] 8000 // lldb-command:v *y1 -// lldbg-check:[...] 80001.5 -// lldbr-check:(f32) *y1 = 80001.5 +// lldb-check:[...] 80001.5 // lldb-command:v z1 -// lldbg-check:[...] false -// lldbr-check:(bool) z1 = false +// lldb-check:[...] false // lldb-command:v *x2 -// lldbg-check:[...] -30000 -// lldbr-check:(i16) *x2 = -30000 +// lldb-check:[...] -30000 // lldb-command:v y2 -// lldbg-check:[...] -300001.5 -// lldbr-check:(f32) y2 = -300001.5 +// lldb-check:[...] -300001.5 // lldb-command:v *z2 -// lldbg-check:[...] true -// lldbr-check:(bool) *z2 = true +// lldb-check:[...] true // lldb-command:v v2 -// lldbg-check:[...] 854237.5 -// lldbr-check:(f64) v2 = 854237.5 +// lldb-check:[...] 854237.5 // lldb-command:continue // SIMPLE IDENTIFIER // lldb-command:v i -// lldbg-check:[...] 1234 -// lldbr-check:(i32) i = 1234 +// lldb-check:[...] 1234 // lldb-command:continue // lldb-command:v simple_struct_ident -// lldbg-check:[...] { x = 3537 y = 35437.5 z = true } -// lldbr-check:(destructured_for_loop_variable::Struct) simple_struct_ident = { x = 3537 y = 35437.5 z = true } +// lldb-check:[...] { x = 3537 y = 35437.5 z = true } // lldb-command:continue // lldb-command:v simple_tuple_ident -// lldbg-check:[...] { 0 = 34903493 1 = 232323 } -// lldbr-check:((u32, i64)) simple_tuple_ident = { 0 = 34903493 1 = 232323 } +// lldb-check:[...] { 0 = 34903493 1 = 232323 } // lldb-command:continue #![allow(unused_variables)] diff --git a/tests/debuginfo/destructured-local.rs b/tests/debuginfo/destructured-local.rs index 8d62fe5db03..fad96ca7d4b 100644 --- a/tests/debuginfo/destructured-local.rs +++ b/tests/debuginfo/destructured-local.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -21,14 +19,12 @@ // gdb-command:print f // gdb-check:$6 = 5 // gdb-command:print g -// gdbg-check:$7 = {__0 = 6, __1 = 7} -// gdbr-check:$7 = (6, 7) +// gdb-check:$7 = (6, 7) // gdb-command:print h // gdb-check:$8 = 8 // gdb-command:print i -// gdbg-check:$9 = {a = 9, b = 10} -// gdbr-check:$9 = destructured_local::Struct {a: 9, b: 10} +// gdb-check:$9 = destructured_local::Struct {a: 9, b: 10} // gdb-command:print j // gdb-check:$10 = 11 @@ -50,8 +46,7 @@ // gdb-command:print q // gdb-check:$17 = 20 // gdb-command:print r -// gdbg-check:$18 = {a = 21, b = 22} -// gdbr-check:$18 = destructured_local::Struct {a: 21, b: 22} +// gdb-check:$18 = destructured_local::Struct {a: 21, b: 22} // gdb-command:print s // gdb-check:$19 = 24 @@ -78,30 +73,25 @@ // gdb-check:$29 = 33 // gdb-command:print aa -// gdbg-check:$30 = {__0 = 34, __1 = 35} -// gdbr-check:$30 = (34, 35) +// gdb-check:$30 = (34, 35) // gdb-command:print bb -// gdbg-check:$31 = {__0 = 36, __1 = 37} -// gdbr-check:$31 = (36, 37) +// gdb-check:$31 = (36, 37) // gdb-command:print cc // gdb-check:$32 = 38 // gdb-command:print dd -// gdbg-check:$33 = {__0 = 40, __1 = 41, __2 = 42} -// gdbr-check:$33 = (40, 41, 42) +// gdb-check:$33 = (40, 41, 42) // gdb-command:print *ee -// gdbg-check:$34 = {__0 = 43, __1 = 44, __2 = 45} -// gdbr-check:$34 = (43, 44, 45) +// gdb-check:$34 = (43, 44, 45) // gdb-command:print *ff // gdb-check:$35 = 46 // gdb-command:print gg -// gdbg-check:$36 = {__0 = 47, __1 = 48} -// gdbr-check:$36 = (47, 48) +// gdb-check:$36 = (47, 48) // gdb-command:print *hh // gdb-check:$37 = 50 @@ -130,157 +120,114 @@ // lldb-command:run // lldb-command:v a -// lldbg-check:[...] 1 -// lldbr-check:(isize) a = 1 +// lldb-check:[...] 1 // lldb-command:v b -// lldbg-check:[...] false -// lldbr-check:(bool) b = false +// lldb-check:[...] false // lldb-command:v c -// lldbg-check:[...] 2 -// lldbr-check:(isize) c = 2 +// lldb-check:[...] 2 // lldb-command:v d -// lldbg-check:[...] 3 -// lldbr-check:(u16) d = 3 +// lldb-check:[...] 3 // lldb-command:v e -// lldbg-check:[...] 4 -// lldbr-check:(u16) e = 4 +// lldb-check:[...] 4 // lldb-command:v f -// lldbg-check:[...] 5 -// lldbr-check:(isize) f = 5 +// lldb-check:[...] 5 // lldb-command:v g -// lldbg-check:[...] { 0 = 6 1 = 7 } -// lldbr-check:((u32, u32)) g = { 0 = 6 1 = 7 } +// lldb-check:[...] { 0 = 6 1 = 7 } // lldb-command:v h -// lldbg-check:[...] 8 -// lldbr-check:(i16) h = 8 +// lldb-check:[...] 8 // lldb-command:v i -// lldbg-check:[...] { a = 9 b = 10 } -// lldbr-check:(destructured_local::Struct) i = { a = 9 b = 10 } +// lldb-check:[...] { a = 9 b = 10 } // lldb-command:v j -// lldbg-check:[...] 11 -// lldbr-check:(i16) j = 11 +// lldb-check:[...] 11 // lldb-command:v k -// lldbg-check:[...] 12 -// lldbr-check:(i64) k = 12 +// lldb-check:[...] 12 // lldb-command:v l -// lldbg-check:[...] 13 -// lldbr-check:(i32) l = 13 +// lldb-check:[...] 13 // lldb-command:v m -// lldbg-check:[...] 14 -// lldbr-check:(i32) m = 14 +// lldb-check:[...] 14 // lldb-command:v n -// lldbg-check:[...] 16 -// lldbr-check:(i32) n = 16 +// lldb-check:[...] 16 // lldb-command:v o -// lldbg-check:[...] 18 -// lldbr-check:(i32) o = 18 +// lldb-check:[...] 18 // lldb-command:v p -// lldbg-check:[...] 19 -// lldbr-check:(i64) p = 19 +// lldb-check:[...] 19 // lldb-command:v q -// lldbg-check:[...] 20 -// lldbr-check:(i32) q = 20 +// lldb-check:[...] 20 // lldb-command:v r -// lldbg-check:[...] { a = 21 b = 22 } -// lldbr-check:(destructured_local::Struct) r = { a = 21 b = 22 } +// lldb-check:[...] { a = 21 b = 22 } // lldb-command:v s -// lldbg-check:[...] 24 -// lldbr-check:(i32) s = 24 +// lldb-check:[...] 24 // lldb-command:v t -// lldbg-check:[...] 23 -// lldbr-check:(i64) t = 23 +// lldb-check:[...] 23 // lldb-command:v u -// lldbg-check:[...] 25 -// lldbr-check:(i32) u = 25 +// lldb-check:[...] 25 // lldb-command:v v -// lldbg-check:[...] 26 -// lldbr-check:(i32) v = 26 +// lldb-check:[...] 26 // lldb-command:v w -// lldbg-check:[...] 27 -// lldbr-check:(i32) w = 27 +// lldb-check:[...] 27 // lldb-command:v x -// lldbg-check:[...] 28 -// lldbr-check:(i32) x = 28 +// lldb-check:[...] 28 // lldb-command:v y -// lldbg-check:[...] 29 -// lldbr-check:(i64) y = 29 +// lldb-check:[...] 29 // lldb-command:v z -// lldbg-check:[...] 30 -// lldbr-check:(i32) z = 30 +// lldb-check:[...] 30 // lldb-command:v ae -// lldbg-check:[...] 31 -// lldbr-check:(i64) ae = 31 +// lldb-check:[...] 31 // lldb-command:v oe -// lldbg-check:[...] 32 -// lldbr-check:(i32) oe = 32 +// lldb-check:[...] 32 // lldb-command:v ue -// lldbg-check:[...] 33 -// lldbr-check:(i32) ue = 33 +// lldb-check:[...] 33 // lldb-command:v aa -// lldbg-check:[...] { 0 = 34 1 = 35 } -// lldbr-check:((i32, i32)) aa = { 0 = 34 1 = 35 } +// lldb-check:[...] { 0 = 34 1 = 35 } // lldb-command:v bb -// lldbg-check:[...] { 0 = 36 1 = 37 } -// lldbr-check:((i32, i32)) bb = { 0 = 36 1 = 37 } +// lldb-check:[...] { 0 = 36 1 = 37 } // lldb-command:v cc -// lldbg-check:[...] 38 -// lldbr-check:(i32) cc = 38 +// lldb-check:[...] 38 // lldb-command:v dd -// lldbg-check:[...] { 0 = 40 1 = 41 2 = 42 } -// lldbr-check:((i32, i32, i32)) dd = { 0 = 40 1 = 41 2 = 42} +// lldb-check:[...] { 0 = 40 1 = 41 2 = 42 } // lldb-command:v *ee -// lldbg-check:[...] { 0 = 43 1 = 44 2 = 45 } -// lldbr-check:((i32, i32, i32)) *ee = { 0 = 43 1 = 44 2 = 45} +// lldb-check:[...] { 0 = 43 1 = 44 2 = 45 } // lldb-command:v *ff -// lldbg-check:[...] 46 -// lldbr-check:(i32) *ff = 46 +// lldb-check:[...] 46 // lldb-command:v gg -// lldbg-check:[...] { 0 = 47 1 = 48 } -// lldbr-check:((i32, i32)) gg = { 0 = 47 1 = 48 } +// lldb-check:[...] { 0 = 47 1 = 48 } // lldb-command:v *hh -// lldbg-check:[...] 50 -// lldbr-check:(i32) *hh = 50 +// lldb-check:[...] 50 // lldb-command:v ii -// lldbg-check:[...] 51 -// lldbr-check:(i32) ii = 51 +// lldb-check:[...] 51 // lldb-command:v *jj -// lldbg-check:[...] 52 -// lldbr-check:(i32) *jj = 52 +// lldb-check:[...] 52 // lldb-command:v kk -// lldbg-check:[...] 53 -// lldbr-check:(f64) kk = 53 +// lldb-check:[...] 53 // lldb-command:v ll -// lldbg-check:[...] 54 -// lldbr-check:(isize) ll = 54 +// lldb-check:[...] 54 // lldb-command:v mm -// lldbg-check:[...] 55 -// lldbr-check:(f64) mm = 55 +// lldb-check:[...] 55 // lldb-command:v *nn -// lldbg-check:[...] 56 -// lldbr-check:(isize) *nn = 56 +// lldb-check:[...] 56 #![allow(unused_variables)] diff --git a/tests/debuginfo/drop-locations.rs b/tests/debuginfo/drop-locations.rs index 15b2d0de7fe..a55cf7b50a8 100644 --- a/tests/debuginfo/drop-locations.rs +++ b/tests/debuginfo/drop-locations.rs @@ -1,12 +1,9 @@ -//@ ignore-windows //@ ignore-android -//@ ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 -//@ min-lldb-version: 310 +//@ ignore-test: #128971 #![allow(unused)] -//@ compile-flags:-g -O -C no-prepopulate-passes -// -O -C no-prepopulate-passes added to work around https://bugs.llvm.org/show_bug.cgi?id=32123 +//@ compile-flags:-g // This test checks that drop glue code gets attributed to scope's closing brace, // and function epilogues - to function's closing brace. diff --git a/tests/debuginfo/dummy_span.rs b/tests/debuginfo/dummy_span.rs new file mode 100644 index 00000000000..d02eead470f --- /dev/null +++ b/tests/debuginfo/dummy_span.rs @@ -0,0 +1,45 @@ +//@ min-lldb-version: 310 + +//@ compile-flags:-g + +// === GDB TESTS =================================================================================== + +// gdb-command:run 7 + +// gdb-command:next +// gdb-command:next +// gdb-check:[...]#loc1[...] +// gdb-command:next +// gdb-check:[...]#loc2[...] + +// === LLDB TESTS ================================================================================== + +// lldb-command:run 7 + +// lldb-command:next +// lldb-command:next +// lldb-command:frame select +// lldb-check:[...]#loc1[...] +// lldb-command:next +// lldb-command:frame select +// lldb-check:[...]#loc2[...] + +use std::env; +use std::num::ParseIntError; + +fn main() -> Result<(), ParseIntError> { + let args = env::args(); + let number_str = args.skip(1).next().unwrap(); + let number = number_str.parse::()?; + zzz(); // #break + if number % 7 == 0 { + // This generates code with a dummy span for + // some reason. If that ever changes this + // test will not test what it wants to test. + return Ok(()); // #loc1 + } + println!("{}", number); + Ok(()) +} // #loc2 + +fn zzz() { () } diff --git a/tests/debuginfo/embedded-visualizer.rs b/tests/debuginfo/embedded-visualizer.rs index 69afd273f77..cbd8691394d 100644 --- a/tests/debuginfo/embedded-visualizer.rs +++ b/tests/debuginfo/embedded-visualizer.rs @@ -1,7 +1,6 @@ //@ compile-flags:-g -//@ min-gdb-version: 8.1 //@ ignore-lldb -//@ ignore-windows-gnu // emit_debug_gdb_scripts is disabled on Windows +//@ ignore-windows-gnu: #128981 // === CDB TESTS ================================================================================== diff --git a/tests/debuginfo/empty-string.rs b/tests/debuginfo/empty-string.rs index 35b68ed91c0..014465c27ca 100644 --- a/tests/debuginfo/empty-string.rs +++ b/tests/debuginfo/empty-string.rs @@ -1,9 +1,6 @@ -//@ ignore-windows failing on win32 bot +//@ ignore-windows-gnu: #128981 //@ ignore-android: FIXME(#10381) //@ compile-flags:-g -//@ min-gdb-version: 8.1 -//@ ignore-gdb-version: 7.11.90 - 8.0.9 -//@ min-lldb-version: 310 // === GDB TESTS =================================================================================== diff --git a/tests/debuginfo/enum-thinlto.rs b/tests/debuginfo/enum-thinlto.rs index 42a0d1e28f8..af77145c312 100644 --- a/tests/debuginfo/enum-thinlto.rs +++ b/tests/debuginfo/enum-thinlto.rs @@ -1,5 +1,3 @@ -// Require a gdb that can read DW_TAG_variant_part. -//@ min-gdb-version: 8.2 //@ min-lldb-version: 1800 //@ compile-flags:-g -Z thinlto @@ -8,15 +6,14 @@ // gdb-command:run // gdb-command:print *abc -// gdbr-check:$1 = enum_thinlto::ABC::TheA{x: 0, y: 8970181431921507452} +// gdb-check:$1 = enum_thinlto::ABC::TheA{x: 0, y: 8970181431921507452} // === LLDB TESTS ================================================================================== // lldb-command:run // lldb-command:v *abc -// lldbg-check:(enum_thinlto::ABC) *abc = { value = { x = 0 y = 8970181431921507452 } $discr$ = 0 } -// lldbr-check:(enum_thinlto::ABC) *abc = (x = 0, y = 8970181431921507452) +// lldb-check:(enum_thinlto::ABC) *abc = { value = { x = 0 y = 8970181431921507452 } $discr$ = 0 } #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/evec-in-struct.rs b/tests/debuginfo/evec-in-struct.rs index 2283e96c0ad..303669cf06c 100644 --- a/tests/debuginfo/evec-in-struct.rs +++ b/tests/debuginfo/evec-in-struct.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -7,23 +5,18 @@ // gdb-command:run // gdb-command:print no_padding1 -// gdbg-check:$1 = {x = {0, 1, 2}, y = -3, z = {4.5, 5.5}} -// gdbr-check:$1 = evec_in_struct::NoPadding1 {x: [0, 1, 2], y: -3, z: [4.5, 5.5]} +// gdb-check:$1 = evec_in_struct::NoPadding1 {x: [0, 1, 2], y: -3, z: [4.5, 5.5]} // gdb-command:print no_padding2 -// gdbg-check:$2 = {x = {6, 7, 8}, y = {{9, 10}, {11, 12}}} -// gdbr-check:$2 = evec_in_struct::NoPadding2 {x: [6, 7, 8], y: [[9, 10], [11, 12]]} +// gdb-check:$2 = evec_in_struct::NoPadding2 {x: [6, 7, 8], y: [[9, 10], [11, 12]]} // gdb-command:print struct_internal_padding -// gdbg-check:$3 = {x = {13, 14}, y = {15, 16}} -// gdbr-check:$3 = evec_in_struct::StructInternalPadding {x: [13, 14], y: [15, 16]} +// gdb-check:$3 = evec_in_struct::StructInternalPadding {x: [13, 14], y: [15, 16]} // gdb-command:print single_vec -// gdbg-check:$4 = {x = {17, 18, 19, 20, 21}} -// gdbr-check:$4 = evec_in_struct::SingleVec {x: [17, 18, 19, 20, 21]} +// gdb-check:$4 = evec_in_struct::SingleVec {x: [17, 18, 19, 20, 21]} // gdb-command:print struct_padded_at_end -// gdbg-check:$5 = {x = {22, 23}, y = {24, 25}} -// gdbr-check:$5 = evec_in_struct::StructPaddedAtEnd {x: [22, 23], y: [24, 25]} +// gdb-check:$5 = evec_in_struct::StructPaddedAtEnd {x: [22, 23], y: [24, 25]} // === LLDB TESTS ================================================================================== @@ -31,23 +24,18 @@ // lldb-command:run // lldb-command:v no_padding1 -// lldbg-check:[...] { x = { [0] = 0 [1] = 1 [2] = 2 } y = -3 z = { [0] = 4.5 [1] = 5.5 } } -// lldbr-check:(evec_in_struct::NoPadding1) no_padding1 = { x = { [0] = 0 [1] = 1 [2] = 2 } y = -3 z = { [0] = 4.5 [1] = 5.5 } } +// lldb-check:[...] { x = { [0] = 0 [1] = 1 [2] = 2 } y = -3 z = { [0] = 4.5 [1] = 5.5 } } // lldb-command:v no_padding2 -// lldbg-check:[...] { x = { [0] = 6 [1] = 7 [2] = 8 } y = { [0] = { [0] = 9 [1] = 10 } [1] = { [0] = 11 [1] = 12 } } } -// lldbr-check:(evec_in_struct::NoPadding2) no_padding2 = { x = { [0] = 6 [1] = 7 [2] = 8 } y = { [0] = { [0] = 9 [1] = 10 } [1] = { [0] = 11 [1] = 12 } } } +// lldb-check:[...] { x = { [0] = 6 [1] = 7 [2] = 8 } y = { [0] = { [0] = 9 [1] = 10 } [1] = { [0] = 11 [1] = 12 } } } // lldb-command:v struct_internal_padding -// lldbg-check:[...] { x = { [0] = 13 [1] = 14 } y = { [0] = 15 [1] = 16 } } -// lldbr-check:(evec_in_struct::StructInternalPadding) struct_internal_padding = { x = { [0] = 13 [1] = 14 } y = { [0] = 15 [1] = 16 } } +// lldb-check:[...] { x = { [0] = 13 [1] = 14 } y = { [0] = 15 [1] = 16 } } // lldb-command:v single_vec -// lldbg-check:[...] { x = { [0] = 17 [1] = 18 [2] = 19 [3] = 20 [4] = 21 } } -// lldbr-check:(evec_in_struct::SingleVec) single_vec = { x = { [0] = 17 [1] = 18 [2] = 19 [3] = 20 [4] = 21 } } +// lldb-check:[...] { x = { [0] = 17 [1] = 18 [2] = 19 [3] = 20 [4] = 21 } } // lldb-command:v struct_padded_at_end -// lldbg-check:[...] { x = { [0] = 22 [1] = 23 } y = { [0] = 24 [1] = 25 } } -// lldbr-check:(evec_in_struct::StructPaddedAtEnd) struct_padded_at_end = { x = { [0] = 22 [1] = 23 } y = { [0] = 24 [1] = 25 } } +// lldb-check:[...] { x = { [0] = 22 [1] = 23 } y = { [0] = 24 [1] = 25 } } #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/extern-c-fn.rs b/tests/debuginfo/extern-c-fn.rs index b45a073ed05..4642073faab 100644 --- a/tests/debuginfo/extern-c-fn.rs +++ b/tests/debuginfo/extern-c-fn.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -22,17 +20,13 @@ // lldb-command:run // lldb-command:v len -// lldbg-check:[...] 20 -// lldbr-check:(i32) len = 20 +// lldb-check:[...] 20 // lldb-command:v local0 -// lldbg-check:[...] 19 -// lldbr-check:(i32) local0 = 19 +// lldb-check:[...] 19 // lldb-command:v local1 -// lldbg-check:[...] true -// lldbr-check:(bool) local1 = true +// lldb-check:[...] true // lldb-command:v local2 -// lldbg-check:[...] 20.5 -// lldbr-check:(f64) local2 = 20.5 +// lldb-check:[...] 20.5 // lldb-command:continue diff --git a/tests/debuginfo/function-arg-initialization.rs b/tests/debuginfo/function-arg-initialization.rs index 05935c30bea..ae54d56623c 100644 --- a/tests/debuginfo/function-arg-initialization.rs +++ b/tests/debuginfo/function-arg-initialization.rs @@ -1,6 +1,3 @@ -//@ ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 -//@ min-lldb-version: 310 - // This test case checks if function arguments already have the correct value // when breaking at the first line of the function, that is if the function // prologue has already been executed at the first line. Note that because of @@ -8,7 +5,9 @@ // arguments have been properly loaded when setting the breakpoint via the // function name. -//@ compile-flags:-g +//@ min-lldb-version: 1800 +//@ compile-flags:-g -Zmir-enable-passes=-SingleUseConsts +// SingleUseConsts shouldn't need to be disabled, see #128945 // === GDB TESTS =================================================================================== @@ -25,10 +24,8 @@ // NON IMMEDIATE ARGS // gdb-command:print a -// gdbg-check:$4 = {a = 3, b = 4, c = 5, d = 6, e = 7, f = 8, g = 9, h = 10} // gdbt-check:$4 = function_arg_initialization::BigStruct {a: 3, b: 4, c: 5, d: 6, e: 7, f: 8, g: 9, h: 10} // gdb-command:print b -// gdbg-check:$5 = {a = 11, b = 12, c = 13, d = 14, e = 15, f = 16, g = 17, h = 18} // gdbt-check:$5 = function_arg_initialization::BigStruct {a: 11, b: 12, c: 13, d: 14, e: 15, f: 16, g: 17, h: 18} // gdb-command:continue diff --git a/tests/debuginfo/function-arguments.rs b/tests/debuginfo/function-arguments.rs index b0afa1d0772..21c0c7d859c 100644 --- a/tests/debuginfo/function-arguments.rs +++ b/tests/debuginfo/function-arguments.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -23,19 +21,15 @@ // lldb-command:run // lldb-command:v x -// lldbg-check:[...] 111102 -// lldbr-check:(isize) x = 111102 +// lldb-check:[...] 111102 // lldb-command:v y -// lldbg-check:[...] true -// lldbr-check:(bool) y = true +// lldb-check:[...] true // lldb-command:continue // lldb-command:v a -// lldbg-check:[...] 2000 -// lldbr-check:(i32) a = 2000 +// lldb-check:[...] 2000 // lldb-command:v b -// lldbg-check:[...] 3000 -// lldbr-check:(i64) b = 3000 +// lldb-check:[...] 3000 // lldb-command:continue diff --git a/tests/debuginfo/function-prologue-stepping-regular.rs b/tests/debuginfo/function-prologue-stepping-regular.rs index a1f44105bb9..07b9356fb50 100644 --- a/tests/debuginfo/function-prologue-stepping-regular.rs +++ b/tests/debuginfo/function-prologue-stepping-regular.rs @@ -1,9 +1,8 @@ // This test case checks if function arguments already have the correct value when breaking at the // beginning of a function. -//@ min-lldb-version: 310 +//@ min-lldb-version: 1800 //@ ignore-gdb -//@ ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 //@ compile-flags:-g // lldb-command:breakpoint set --name immediate_args diff --git a/tests/debuginfo/gdb-pretty-struct-and-enums.rs b/tests/debuginfo/gdb-pretty-struct-and-enums.rs index 235295e887c..08e01333a37 100644 --- a/tests/debuginfo/gdb-pretty-struct-and-enums.rs +++ b/tests/debuginfo/gdb-pretty-struct-and-enums.rs @@ -1,30 +1,24 @@ //@ ignore-lldb //@ ignore-android: FIXME(#10381) -//@ min-gdb-version: 8.1 //@ compile-flags:-g // gdb-command: run // gdb-command: print regular_struct -// gdbg-check:$1 = {the_first_field = 101, the_second_field = 102.5, the_third_field = false} -// gdbr-check:$1 = gdb_pretty_struct_and_enums::RegularStruct {the_first_field: 101, the_second_field: 102.5, the_third_field: false} +// gdb-check:$1 = gdb_pretty_struct_and_enums::RegularStruct {the_first_field: 101, the_second_field: 102.5, the_third_field: false} // gdb-command: print empty_struct -// gdbg-check:$2 = EmptyStruct -// gdbr-check:$2 = gdb_pretty_struct_and_enums::EmptyStruct +// gdb-check:$2 = gdb_pretty_struct_and_enums::EmptyStruct // gdb-command: print c_style_enum1 -// gdbg-check:$3 = CStyleEnumVar1 -// gdbr-check:$3 = gdb_pretty_struct_and_enums::CStyleEnum::CStyleEnumVar1 +// gdb-check:$3 = gdb_pretty_struct_and_enums::CStyleEnum::CStyleEnumVar1 // gdb-command: print c_style_enum2 -// gdbg-check:$4 = CStyleEnumVar2 -// gdbr-check:$4 = gdb_pretty_struct_and_enums::CStyleEnum::CStyleEnumVar2 +// gdb-check:$4 = gdb_pretty_struct_and_enums::CStyleEnum::CStyleEnumVar2 // gdb-command: print c_style_enum3 -// gdbg-check:$5 = CStyleEnumVar3 -// gdbr-check:$5 = gdb_pretty_struct_and_enums::CStyleEnum::CStyleEnumVar3 +// gdb-check:$5 = gdb_pretty_struct_and_enums::CStyleEnum::CStyleEnumVar3 #![allow(dead_code, unused_variables)] diff --git a/tests/debuginfo/generic-enum-with-different-disr-sizes.rs b/tests/debuginfo/generic-enum-with-different-disr-sizes.rs index 7b23221213a..e723543a37b 100644 --- a/tests/debuginfo/generic-enum-with-different-disr-sizes.rs +++ b/tests/debuginfo/generic-enum-with-different-disr-sizes.rs @@ -1,8 +1,4 @@ //@ ignore-lldb: FIXME(#27089) -//@ min-lldb-version: 310 - -// Require a gdb that can read DW_TAG_variant_part. -//@ min-gdb-version: 8.2 //@ compile-flags:-g @@ -10,29 +6,29 @@ // gdb-command:run // gdb-command:print eight_bytes1 -// gdbr-check:$1 = generic_enum_with_different_disr_sizes::Enum::Variant1(100) +// gdb-check:$1 = generic_enum_with_different_disr_sizes::Enum::Variant1(100) // gdb-command:print four_bytes1 -// gdbr-check:$2 = generic_enum_with_different_disr_sizes::Enum::Variant1(101) +// gdb-check:$2 = generic_enum_with_different_disr_sizes::Enum::Variant1(101) // gdb-command:print two_bytes1 -// gdbr-check:$3 = generic_enum_with_different_disr_sizes::Enum::Variant1(102) +// gdb-check:$3 = generic_enum_with_different_disr_sizes::Enum::Variant1(102) // gdb-command:print one_byte1 -// gdbr-check:$4 = generic_enum_with_different_disr_sizes::Enum::Variant1(65) +// gdb-check:$4 = generic_enum_with_different_disr_sizes::Enum::Variant1(65) // gdb-command:print eight_bytes2 -// gdbr-check:$5 = generic_enum_with_different_disr_sizes::Enum::Variant2(100) +// gdb-check:$5 = generic_enum_with_different_disr_sizes::Enum::Variant2(100) // gdb-command:print four_bytes2 -// gdbr-check:$6 = generic_enum_with_different_disr_sizes::Enum::Variant2(101) +// gdb-check:$6 = generic_enum_with_different_disr_sizes::Enum::Variant2(101) // gdb-command:print two_bytes2 -// gdbr-check:$7 = generic_enum_with_different_disr_sizes::Enum::Variant2(102) +// gdb-check:$7 = generic_enum_with_different_disr_sizes::Enum::Variant2(102) // gdb-command:print one_byte2 -// gdbr-check:$8 = generic_enum_with_different_disr_sizes::Enum::Variant2(65) +// gdb-check:$8 = generic_enum_with_different_disr_sizes::Enum::Variant2(65) // gdb-command:continue diff --git a/tests/debuginfo/generic-function.rs b/tests/debuginfo/generic-function.rs index e131ebfa306..4be8d5ad45a 100644 --- a/tests/debuginfo/generic-function.rs +++ b/tests/debuginfo/generic-function.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -21,8 +19,7 @@ // gdb-command:print *t0 // gdb-check:$5 = 5 // gdb-command:print *t1 -// gdbg-check:$6 = {a = 6, b = 7.5} -// gdbr-check:$6 = generic_function::Struct {a: 6, b: 7.5} +// gdb-check:$6 = generic_function::Struct {a: 6, b: 7.5} // gdb-command:continue // === LLDB TESTS ================================================================================== @@ -30,27 +27,21 @@ // lldb-command:run // lldb-command:v *t0 -// lldbg-check:[...] 1 -// lldbr-check:(i32) *t0 = 1 +// lldb-check:[...] 1 // lldb-command:v *t1 -// lldbg-check:[...] 2.5 -// lldbr-check:(f64) *t1 = 2.5 +// lldb-check:[...] 2.5 // lldb-command:continue // lldb-command:v *t0 -// lldbg-check:[...] 3.5 -// lldbr-check:(f64) *t0 = 3.5 +// lldb-check:[...] 3.5 // lldb-command:v *t1 -// lldbg-check:[...] 4 -// lldbr-check:(u16) *t1 = 4 +// lldb-check:[...] 4 // lldb-command:continue // lldb-command:v *t0 -// lldbg-check:[...] 5 -// lldbr-check:(i32) *t0 = 5 +// lldb-check:[...] 5 // lldb-command:v *t1 -// lldbg-check:[...] { a = 6 b = 7.5 } -// lldbr-check:(generic_function::Struct) *t1 = { a = 6 b = 7.5 } +// lldb-check:[...] { a = 6 b = 7.5 } // lldb-command:continue #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/generic-functions-nested.rs b/tests/debuginfo/generic-functions-nested.rs index eee0c151182..7e0c20f8903 100644 --- a/tests/debuginfo/generic-functions-nested.rs +++ b/tests/debuginfo/generic-functions-nested.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -36,35 +34,27 @@ // lldb-command:run // lldb-command:v x -// lldbg-check:[...] -1 -// lldbr-check:(i32) x = -1 +// lldb-check:[...] -1 // lldb-command:v y -// lldbg-check:[...] 1 -// lldbr-check:(i32) y = 1 +// lldb-check:[...] 1 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] -1 -// lldbr-check:(i32) x = -1 +// lldb-check:[...] -1 // lldb-command:v y -// lldbg-check:[...] 2.5 -// lldbr-check:(f64) y = 2.5 +// lldb-check:[...] 2.5 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] -2.5 -// lldbr-check:(f64) x = -2.5 +// lldb-check:[...] -2.5 // lldb-command:v y -// lldbg-check:[...] 1 -// lldbr-check:(i32) y = 1 +// lldb-check:[...] 1 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] -2.5 -// lldbr-check:(f64) x = -2.5 +// lldb-check:[...] -2.5 // lldb-command:v y -// lldbg-check:[...] 2.5 -// lldbr-check:(f64) y = 2.5 +// lldb-check:[...] 2.5 // lldb-command:continue diff --git a/tests/debuginfo/generic-method-on-generic-struct.rs b/tests/debuginfo/generic-method-on-generic-struct.rs index 0f706740410..9c587ca2839 100644 --- a/tests/debuginfo/generic-method-on-generic-struct.rs +++ b/tests/debuginfo/generic-method-on-generic-struct.rs @@ -1,17 +1,12 @@ //@ compile-flags:-g -// Some versions of the non-rust-enabled LLDB print the wrong generic -// parameter type names in this test. -//@ needs-rust-lldb - // === GDB TESTS =================================================================================== // gdb-command:run // STACK BY REF // gdb-command:print *self -// gdbg-check:$1 = {x = {__0 = 8888, __1 = -8888}} -// gdbr-check:$1 = generic_method_on_generic_struct::Struct<(u32, i32)> {x: (8888, -8888)} +// gdb-check:$1 = generic_method_on_generic_struct::Struct<(u32, i32)> {x: (8888, -8888)} // gdb-command:print arg1 // gdb-check:$2 = -1 // gdb-command:print arg2 @@ -20,8 +15,7 @@ // STACK BY VAL // gdb-command:print self -// gdbg-check:$4 = {x = {__0 = 8888, __1 = -8888}} -// gdbr-check:$4 = generic_method_on_generic_struct::Struct<(u32, i32)> {x: (8888, -8888)} +// gdb-check:$4 = generic_method_on_generic_struct::Struct<(u32, i32)> {x: (8888, -8888)} // gdb-command:print arg1 // gdb-check:$5 = -3 // gdb-command:print arg2 @@ -30,8 +24,7 @@ // OWNED BY REF // gdb-command:print *self -// gdbg-check:$7 = {x = 1234.5} -// gdbr-check:$7 = generic_method_on_generic_struct::Struct {x: 1234.5} +// gdb-check:$7 = generic_method_on_generic_struct::Struct {x: 1234.5} // gdb-command:print arg1 // gdb-check:$8 = -5 // gdb-command:print arg2 @@ -40,8 +33,7 @@ // OWNED BY VAL // gdb-command:print self -// gdbg-check:$10 = {x = 1234.5} -// gdbr-check:$10 = generic_method_on_generic_struct::Struct {x: 1234.5} +// gdb-check:$10 = generic_method_on_generic_struct::Struct {x: 1234.5} // gdb-command:print arg1 // gdb-check:$11 = -7 // gdb-command:print arg2 @@ -50,8 +42,7 @@ // OWNED MOVED // gdb-command:print *self -// gdbg-check:$13 = {x = 1234.5} -// gdbr-check:$13 = generic_method_on_generic_struct::Struct {x: 1234.5} +// gdb-check:$13 = generic_method_on_generic_struct::Struct {x: 1234.5} // gdb-command:print arg1 // gdb-check:$14 = -9 // gdb-command:print arg2 @@ -65,62 +56,47 @@ // STACK BY REF // lldb-command:v *self -// lldbg-check:[...] { x = { 0 = 8888, 1 = -8888 } } -// lldbr-check:(generic_method_on_generic_struct::Struct<(u32, i32)>) *self = { x = { 0 = 8888 1 = -8888 } } +// lldb-check:[...] { x = { 0 = 8888 1 = -8888 } } // lldb-command:v arg1 -// lldbg-check:[...] -1 -// lldbr-check:(isize) arg1 = -1 +// lldb-check:[...] -1 // lldb-command:v arg2 -// lldbg-check:[...] 2 -// lldbr-check:(u16) arg2 = 2 +// lldb-check:[...] 2 // lldb-command:continue // STACK BY VAL // lldb-command:v self -// lldbg-check:[...] { x = { 0 = 8888, 1 = -8888 } } -// lldbr-check:(generic_method_on_generic_struct::Struct<(u32, i32)>) self = { x = { 0 = 8888, 1 = -8888 } } +// lldb-check:[...] { x = { 0 = 8888 1 = -8888 } } // lldb-command:v arg1 -// lldbg-check:[...] -3 -// lldbr-check:(isize) arg1 = -3 +// lldb-check:[...] -3 // lldb-command:v arg2 -// lldbg-check:[...] -4 -// lldbr-check:(i16) arg2 = -4 +// lldb-check:[...] -4 // lldb-command:continue // OWNED BY REF // lldb-command:v *self -// lldbg-check:[...] { x = 1234.5 } -// lldbr-check:(generic_method_on_generic_struct::Struct) *self = { x = 1234.5 } +// lldb-check:[...] { x = 1234.5 } // lldb-command:v arg1 -// lldbg-check:[...] -5 -// lldbr-check:(isize) arg1 = -5 +// lldb-check:[...] -5 // lldb-command:v arg2 -// lldbg-check:[...] -6 -// lldbr-check:(i32) arg2 = -6 +// lldb-check:[...] -6 // lldb-command:continue // OWNED BY VAL // lldb-command:v self -// lldbg-check:[...] { x = 1234.5 } -// lldbr-check:(generic_method_on_generic_struct::Struct) self = { x = 1234.5 } +// lldb-check:[...] { x = 1234.5 } // lldb-command:v arg1 -// lldbg-check:[...] -7 -// lldbr-check:(isize) arg1 = -7 +// lldb-check:[...] -7 // lldb-command:v arg2 -// lldbg-check:[...] -8 -// lldbr-check:(i64) arg2 = -8 +// lldb-check:[...] -8 // lldb-command:continue // OWNED MOVED // lldb-command:v *self -// lldbg-check:[...] { x = 1234.5 } -// lldbr-check:(generic_method_on_generic_struct::Struct) *self = { x = 1234.5 } +// lldb-check:[...] { x = 1234.5 } // lldb-command:v arg1 -// lldbg-check:[...] -9 -// lldbr-check:(isize) arg1 = -9 +// lldb-check:[...] -9 // lldb-command:v arg2 -// lldbg-check:[...] -10.5 -// lldbr-check:(f32) arg2 = -10.5 +// lldb-check:[...] -10.5 // lldb-command:continue #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/generic-static-method-on-struct-and-enum.rs b/tests/debuginfo/generic-static-method-on-struct-and-enum.rs index 98608e32914..79fe2144cf4 100644 --- a/tests/debuginfo/generic-static-method-on-struct-and-enum.rs +++ b/tests/debuginfo/generic-static-method-on-struct-and-enum.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // gdb-command:run diff --git a/tests/debuginfo/generic-struct-style-enum.rs b/tests/debuginfo/generic-struct-style-enum.rs index 7d929b91064..a5529ab8027 100644 --- a/tests/debuginfo/generic-struct-style-enum.rs +++ b/tests/debuginfo/generic-struct-style-enum.rs @@ -1,24 +1,19 @@ -//@ min-lldb-version: 310 - -// Require a gdb that can read DW_TAG_variant_part. -//@ min-gdb-version: 8.2 - //@ compile-flags:-g // gdb-command:set print union on // gdb-command:run // gdb-command:print case1 -// gdbr-check:$1 = generic_struct_style_enum::Regular::Case1{a: 0, b: 31868, c: 31868, d: 31868, e: 31868} +// gdb-check:$1 = generic_struct_style_enum::Regular::Case1{a: 0, b: 31868, c: 31868, d: 31868, e: 31868} // gdb-command:print case2 -// gdbr-check:$2 = generic_struct_style_enum::Regular::Case2{a: 0, b: 286331153, c: 286331153} +// gdb-check:$2 = generic_struct_style_enum::Regular::Case2{a: 0, b: 286331153, c: 286331153} // gdb-command:print case3 -// gdbr-check:$3 = generic_struct_style_enum::Regular::Case3{a: 0, b: 6438275382588823897} +// gdb-check:$3 = generic_struct_style_enum::Regular::Case3{a: 0, b: 6438275382588823897} // gdb-command:print univariant -// gdbr-check:$4 = generic_struct_style_enum::Univariant::TheOnlyCase{a: -1} +// gdb-check:$4 = generic_struct_style_enum::Univariant::TheOnlyCase{a: -1} #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/generic-struct.rs b/tests/debuginfo/generic-struct.rs index 8c74aa42d2c..f26d823d4f2 100644 --- a/tests/debuginfo/generic-struct.rs +++ b/tests/debuginfo/generic-struct.rs @@ -1,7 +1,3 @@ -// Some versions of the non-rust-enabled LLDB print the wrong generic -// parameter type names in this test. -//@ needs-rust-lldb - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -9,35 +5,27 @@ // gdb-command:run // gdb-command:print int_int -// gdbg-check:$1 = {key = 0, value = 1} -// gdbr-check:$1 = generic_struct::AGenericStruct {key: 0, value: 1} +// gdb-check:$1 = generic_struct::AGenericStruct {key: 0, value: 1} // gdb-command:print int_float -// gdbg-check:$2 = {key = 2, value = 3.5} -// gdbr-check:$2 = generic_struct::AGenericStruct {key: 2, value: 3.5} +// gdb-check:$2 = generic_struct::AGenericStruct {key: 2, value: 3.5} // gdb-command:print float_int -// gdbg-check:$3 = {key = 4.5, value = 5} -// gdbr-check:$3 = generic_struct::AGenericStruct {key: 4.5, value: 5} +// gdb-check:$3 = generic_struct::AGenericStruct {key: 4.5, value: 5} // gdb-command:print float_int_float -// gdbg-check:$4 = {key = 6.5, value = {key = 7, value = 8.5}} -// gdbr-check:$4 = generic_struct::AGenericStruct> {key: 6.5, value: generic_struct::AGenericStruct {key: 7, value: 8.5}} +// gdb-check:$4 = generic_struct::AGenericStruct> {key: 6.5, value: generic_struct::AGenericStruct {key: 7, value: 8.5}} // === LLDB TESTS ================================================================================== // lldb-command:run // lldb-command:v int_int -// lldbg-check:[...] AGenericStruct { key: 0, value: 1 } -// lldbr-check:(generic_struct::AGenericStruct) int_int = AGenericStruct { key: 0, value: 1 } +// lldb-check:[...]AGenericStruct) int_int = { key = 0 value = 1 } // lldb-command:v int_float -// lldbg-check:[...] AGenericStruct { key: 2, value: 3.5 } -// lldbr-check:(generic_struct::AGenericStruct) int_float = AGenericStruct { key: 2, value: 3.5 } +// lldb-check:[...]AGenericStruct) int_float = { key = 2 value = 3.5 } // lldb-command:v float_int -// lldbg-check:[...] AGenericStruct { key: 4.5, value: 5 } -// lldbr-check:(generic_struct::AGenericStruct) float_int = AGenericStruct { key: 4.5, value: 5 } +// lldb-check:[...]AGenericStruct) float_int = { key = 4.5 value = 5 } // lldb-command:v float_int_float -// lldbg-check:[...] AGenericStruct> { key: 6.5, value: AGenericStruct { key: 7, value: 8.5 } } -// lldbr-check:(generic_struct::AGenericStruct>) float_int_float = AGenericStruct> { key: 6.5, value: AGenericStruct { key: 7, value: 8.5 } } +// lldb-check:[...]AGenericStruct >) float_int_float = { key = 6.5 value = { key = 7 value = 8.5 } } // === CDB TESTS =================================================================================== diff --git a/tests/debuginfo/generic-tuple-style-enum.rs b/tests/debuginfo/generic-tuple-style-enum.rs index af90c6ce30e..4a5996645cb 100644 --- a/tests/debuginfo/generic-tuple-style-enum.rs +++ b/tests/debuginfo/generic-tuple-style-enum.rs @@ -1,7 +1,3 @@ -// Require a gdb or lldb that can read DW_TAG_variant_part. -//@ min-gdb-version: 8.2 -//@ needs-rust-lldb - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -10,16 +6,16 @@ // gdb-command:run // gdb-command:print case1 -// gdbr-check:$1 = generic_tuple_style_enum::Regular::Case1(0, 31868, 31868, 31868, 31868) +// gdb-check:$1 = generic_tuple_style_enum::Regular::Case1(0, 31868, 31868, 31868, 31868) // gdb-command:print case2 -// gdbr-check:$2 = generic_tuple_style_enum::Regular::Case2(0, 286331153, 286331153) +// gdb-check:$2 = generic_tuple_style_enum::Regular::Case2(0, 286331153, 286331153) // gdb-command:print case3 -// gdbr-check:$3 = generic_tuple_style_enum::Regular::Case3(0, 6438275382588823897) +// gdb-check:$3 = generic_tuple_style_enum::Regular::Case3(0, 6438275382588823897) // gdb-command:print univariant -// gdbr-check:$4 = generic_tuple_style_enum::Univariant::TheOnlyCase(-1) +// gdb-check:$4 = generic_tuple_style_enum::Univariant::TheOnlyCase(-1) // === LLDB TESTS ================================================================================== @@ -27,16 +23,12 @@ // lldb-command:run // lldb-command:v case1 -// lldbr-check:(generic_tuple_style_enum::Regular::Case1) case1 = { __0 = 0 __1 = 31868 __2 = 31868 __3 = 31868 __4 = 31868 } // lldb-command:v case2 -// lldbr-check:(generic_tuple_style_enum::Regular::Case2) case2 = Regular::Case2 { Case1: 0, Case2: 286331153, Case3: 286331153 } // lldb-command:v case3 -// lldbr-check:(generic_tuple_style_enum::Regular::Case3) case3 = Regular::Case3 { Case1: 0, Case2: 6438275382588823897 } // lldb-command:v univariant -// lldbr-check:(generic_tuple_style_enum::Univariant) univariant = Univariant { TheOnlyCase: Univariant::TheOnlyCase(-1) } #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] diff --git a/tests/debuginfo/include_string.rs b/tests/debuginfo/include_string.rs index 628ac92fe34..704b85e1ac2 100644 --- a/tests/debuginfo/include_string.rs +++ b/tests/debuginfo/include_string.rs @@ -1,4 +1,3 @@ -//@ min-lldb-version: 310 //@ ignore-gdb-version: 15.0 - 99.0 // ^ test temporarily disabled as it fails under gdb 15 @@ -18,14 +17,11 @@ // lldb-command:run // lldb-command:v string1.length -// lldbg-check:[...] 48 -// lldbr-check:(usize) length = 48 +// lldb-check:[...] 48 // lldb-command:v string2.length -// lldbg-check:[...] 49 -// lldbr-check:(usize) length = 49 +// lldb-check:[...] 49 // lldb-command:v string3.length -// lldbg-check:[...] 50 -// lldbr-check:(usize) length = 50 +// lldb-check:[...] 50 // lldb-command:continue diff --git a/tests/debuginfo/issue-12886.rs b/tests/debuginfo/issue-12886.rs index c6cf0dd4e05..48250e88537 100644 --- a/tests/debuginfo/issue-12886.rs +++ b/tests/debuginfo/issue-12886.rs @@ -1,4 +1,3 @@ -//@ ignore-windows failing on 64-bit bots FIXME #17638 //@ ignore-lldb //@ ignore-aarch64 @@ -6,7 +5,7 @@ // gdb-command:run // gdb-command:next -// gdb-check:[...]24[...]let s = Some(5).unwrap(); // #break +// gdb-check:[...]23[...]let s = Some(5).unwrap(); // #break // gdb-command:continue #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/issue-13213.rs b/tests/debuginfo/issue-13213.rs index 7ef9178ce9d..b43a6f90ffc 100644 --- a/tests/debuginfo/issue-13213.rs +++ b/tests/debuginfo/issue-13213.rs @@ -1,4 +1,3 @@ -//@ min-lldb-version: 310 //@ ignore-cdb: Fails with exit code 0xc0000135 ("the application failed to initialize properly") //@ aux-build:issue-13213-aux.rs diff --git a/tests/debuginfo/issue-14411.rs b/tests/debuginfo/issue-14411.rs index 3258fec1e87..7da5fb16d44 100644 --- a/tests/debuginfo/issue-14411.rs +++ b/tests/debuginfo/issue-14411.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // No debugger interaction required: just make sure it compiles without diff --git a/tests/debuginfo/issue-22656.rs b/tests/debuginfo/issue-22656.rs index 5a5442acd95..eb0b38cfa4d 100644 --- a/tests/debuginfo/issue-22656.rs +++ b/tests/debuginfo/issue-22656.rs @@ -2,7 +2,6 @@ // when trying to handle a Vec<> or anything else that contains zero-sized // fields. -//@ min-lldb-version: 310 //@ ignore-gdb //@ compile-flags:-g @@ -11,12 +10,9 @@ // lldb-command:run // lldb-command:v v -// lldbg-check:[...] size=3 { [0] = 1 [1] = 2 [2] = 3 } -// lldbr-check:(alloc::vec::Vec) v = size=3 { [0] = 1 [1] = 2 [2] = 3 } +// lldb-check:[...] size=3 { [0] = 1 [1] = 2 [2] = 3 } // lldb-command:v zs -// lldbg-check:[...] { x = y = 123 z = w = 456 } -// lldbr-check:(issue_22656::StructWithZeroSizedField) zs = { x = y = 123 z = w = 456 } -// lldbr-command:continue +// lldb-check:[...] { x = y = 123 z = w = 456 } #![allow(unused_variables)] #![allow(dead_code)] diff --git a/tests/debuginfo/issue-57822.rs b/tests/debuginfo/issue-57822.rs index cadd9b542e9..7abac1c14d3 100644 --- a/tests/debuginfo/issue-57822.rs +++ b/tests/debuginfo/issue-57822.rs @@ -1,8 +1,6 @@ // This test makes sure that the LLDB pretty printer does not throw an exception // for nested closures and coroutines. -// Require a gdb that can read DW_TAG_variant_part. -//@ min-gdb-version: 8.2 //@ min-lldb-version: 1800 //@ compile-flags:-g @@ -21,10 +19,10 @@ // lldb-command:run // lldb-command:v g -// lldbg-check:(issue_57822::main::{closure_env#1}) g = { f = { x = 1 } } +// lldb-check:(issue_57822::main::{closure_env#1}) g = { f = { x = 1 } } // lldb-command:v b -// lldbg-check:(issue_57822::main::{coroutine_env#3}) b = { value = { a = { value = { y = 2 } $discr$ = '\x02' } } $discr$ = '\x02' } +// lldb-check:(issue_57822::main::{coroutine_env#3}) b = { value = { a = { value = { y = 2 } $discr$ = '\x02' } } $discr$ = '\x02' } #![feature(omit_gdb_pretty_printer_section, coroutines, coroutine_trait, stmt_expr_attributes)] #![omit_gdb_pretty_printer_section] diff --git a/tests/debuginfo/issue-7712.rs b/tests/debuginfo/issue-7712.rs index 35e6b10c4e5..11143f79161 100644 --- a/tests/debuginfo/issue-7712.rs +++ b/tests/debuginfo/issue-7712.rs @@ -1,5 +1,4 @@ //@ compile-flags:-C debuginfo=1 -//@ min-lldb-version: 310 pub trait TraitWithDefaultMethod : Sized { fn method(self) { diff --git a/tests/debuginfo/lexical-scope-in-for-loop.rs b/tests/debuginfo/lexical-scope-in-for-loop.rs index 1b1f106fece..08f244f89a0 100644 --- a/tests/debuginfo/lexical-scope-in-for-loop.rs +++ b/tests/debuginfo/lexical-scope-in-for-loop.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -45,41 +43,34 @@ // FIRST ITERATION // lldb-command:v x -// lldbg-check:[...] 1 -// lldbr-check:(i32) x = 1 +// lldb-check:[...] 1 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] -1 -// lldbr-check:(i32) x = -1 +// lldb-check:[...] -1 // lldb-command:continue // SECOND ITERATION // lldb-command:v x -// lldbg-check:[...] 2 -// lldbr-check:(i32) x = 2 +// lldb-check:[...] 2 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] -2 -// lldbr-check:(i32) x = -2 +// lldb-check:[...] -2 // lldb-command:continue // THIRD ITERATION // lldb-command:v x -// lldbg-check:[...] 3 -// lldbr-check:(i32) x = 3 +// lldb-check:[...] 3 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] -3 -// lldbr-check:(i32) x = -3 +// lldb-check:[...] -3 // lldb-command:continue // AFTER LOOP // lldb-command:v x -// lldbg-check:[...] 1000000 -// lldbr-check:(i32) x = 1000000 +// lldb-check:[...] 1000000 // lldb-command:continue #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/lexical-scope-in-if.rs b/tests/debuginfo/lexical-scope-in-if.rs index d472a50f697..c0e1f2f3e05 100644 --- a/tests/debuginfo/lexical-scope-in-if.rs +++ b/tests/debuginfo/lexical-scope-in-if.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -69,74 +67,58 @@ // BEFORE if // lldb-command:v x -// lldbg-check:[...] 999 -// lldbr-check:(i32) x = 999 +// lldb-check:[...] 999 // lldb-command:v y -// lldbg-check:[...] -1 -// lldbr-check:(i32) y = -1 +// lldb-check:[...] -1 // lldb-command:continue // AT BEGINNING of 'then' block // lldb-command:v x -// lldbg-check:[...] 999 -// lldbr-check:(i32) x = 999 +// lldb-check:[...] 999 // lldb-command:v y -// lldbg-check:[...] -1 -// lldbr-check:(i32) y = -1 +// lldb-check:[...] -1 // lldb-command:continue // AFTER 1st redeclaration of 'x' // lldb-command:v x -// lldbg-check:[...] 1001 -// lldbr-check:(i32) x = 1001 +// lldb-check:[...] 1001 // lldb-command:v y -// lldbg-check:[...] -1 -// lldbr-check:(i32) y = -1 +// lldb-check:[...] -1 // lldb-command:continue // AFTER 2st redeclaration of 'x' // lldb-command:v x -// lldbg-check:[...] 1002 -// lldbr-check:(i32) x = 1002 +// lldb-check:[...] 1002 // lldb-command:v y -// lldbg-check:[...] 1003 -// lldbr-check:(i32) y = 1003 +// lldb-check:[...] 1003 // lldb-command:continue // AFTER 1st if expression // lldb-command:v x -// lldbg-check:[...] 999 -// lldbr-check:(i32) x = 999 +// lldb-check:[...] 999 // lldb-command:v y -// lldbg-check:[...] -1 -// lldbr-check:(i32) y = -1 +// lldb-check:[...] -1 // lldb-command:continue // BEGINNING of else branch // lldb-command:v x -// lldbg-check:[...] 999 -// lldbr-check:(i32) x = 999 +// lldb-check:[...] 999 // lldb-command:v y -// lldbg-check:[...] -1 -// lldbr-check:(i32) y = -1 +// lldb-check:[...] -1 // lldb-command:continue // BEGINNING of else branch // lldb-command:v x -// lldbg-check:[...] 1004 -// lldbr-check:(i32) x = 1004 +// lldb-check:[...] 1004 // lldb-command:v y -// lldbg-check:[...] 1005 -// lldbr-check:(i32) y = 1005 +// lldb-check:[...] 1005 // lldb-command:continue // BEGINNING of else branch // lldb-command:v x -// lldbg-check:[...] 999 -// lldbr-check:(i32) x = 999 +// lldb-check:[...] 999 // lldb-command:v y -// lldbg-check:[...] -1 -// lldbr-check:(i32) y = -1 +// lldb-check:[...] -1 // lldb-command:continue #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/lexical-scope-in-match.rs b/tests/debuginfo/lexical-scope-in-match.rs index d5f0fcbe892..9169c19c6a3 100644 --- a/tests/debuginfo/lexical-scope-in-match.rs +++ b/tests/debuginfo/lexical-scope-in-match.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -64,73 +62,55 @@ // lldb-command:run // lldb-command:v shadowed -// lldbg-check:[...] 231 -// lldbr-check:(i32) shadowed = 231 +// lldb-check:[...] 231 // lldb-command:v not_shadowed -// lldbg-check:[...] 232 -// lldbr-check:(i32) not_shadowed = 232 +// lldb-check:[...] 232 // lldb-command:continue // lldb-command:v shadowed -// lldbg-check:[...] 233 -// lldbr-check:(i32) shadowed = 233 +// lldb-check:[...] 233 // lldb-command:v not_shadowed -// lldbg-check:[...] 232 -// lldbr-check:(i32) not_shadowed = 232 +// lldb-check:[...] 232 // lldb-command:v local_to_arm -// lldbg-check:[...] 234 -// lldbr-check:(i32) local_to_arm = 234 +// lldb-check:[...] 234 // lldb-command:continue // lldb-command:v shadowed -// lldbg-check:[...] 236 -// lldbr-check:(i32) shadowed = 236 +// lldb-check:[...] 236 // lldb-command:v not_shadowed -// lldbg-check:[...] 232 -// lldbr-check:(i32) not_shadowed = 232 +// lldb-check:[...] 232 // lldb-command:continue // lldb-command:v shadowed -// lldbg-check:[...] 237 -// lldbr-check:(isize) shadowed = 237 +// lldb-check:[...] 237 // lldb-command:v not_shadowed -// lldbg-check:[...] 232 -// lldbr-check:(i32) not_shadowed = 232 +// lldb-check:[...] 232 // lldb-command:v local_to_arm -// lldbg-check:[...] 238 -// lldbr-check:(isize) local_to_arm = 238 +// lldb-check:[...] 238 // lldb-command:continue // lldb-command:v shadowed -// lldbg-check:[...] 239 -// lldbr-check:(isize) shadowed = 239 +// lldb-check:[...] 239 // lldb-command:v not_shadowed -// lldbg-check:[...] 232 -// lldbr-check:(i32) not_shadowed = 232 +// lldb-check:[...] 232 // lldb-command:continue // lldb-command:v shadowed -// lldbg-check:[...] 241 -// lldbr-check:(isize) shadowed = 241 +// lldb-check:[...] 241 // lldb-command:v not_shadowed -// lldbg-check:[...] 232 -// lldbr-check:(i32) not_shadowed = 232 +// lldb-check:[...] 232 // lldb-command:continue // lldb-command:v shadowed -// lldbg-check:[...] 243 -// lldbr-check:(i32) shadowed = 243 +// lldb-check:[...] 243 // lldb-command:v *local_to_arm -// lldbg-check:[...] 244 -// lldbr-check:(i32) *local_to_arm = 244 +// lldb-check:[...] 244 // lldb-command:continue // lldb-command:v shadowed -// lldbg-check:[...] 231 -// lldbr-check:(i32) shadowed = 231 +// lldb-check:[...] 231 // lldb-command:v not_shadowed -// lldbg-check:[...] 232 -// lldbr-check:(i32) not_shadowed = 232 +// lldb-check:[...] 232 // lldb-command:continue #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/lexical-scope-in-parameterless-closure.rs b/tests/debuginfo/lexical-scope-in-parameterless-closure.rs index fa2cd281c80..dd6da95d388 100644 --- a/tests/debuginfo/lexical-scope-in-parameterless-closure.rs +++ b/tests/debuginfo/lexical-scope-in-parameterless-closure.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-C debuginfo=1 // gdb-command:run diff --git a/tests/debuginfo/lexical-scope-in-stack-closure.rs b/tests/debuginfo/lexical-scope-in-stack-closure.rs index 92582e10c42..d01162c39d6 100644 --- a/tests/debuginfo/lexical-scope-in-stack-closure.rs +++ b/tests/debuginfo/lexical-scope-in-stack-closure.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -36,33 +34,27 @@ // lldb-command:run // lldb-command:v x -// lldbg-check:[...] false -// lldbr-check:(bool) x = false +// lldb-check:[...] false // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] false -// lldbr-check:(bool) x = false +// lldb-check:[...] false // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 1000 -// lldbr-check:(isize) x = 1000 +// lldb-check:[...] 1000 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 2.5 -// lldbr-check:(f64) x = 2.5 +// lldb-check:[...] 2.5 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] true -// lldbr-check:(bool) x = true +// lldb-check:[...] true // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] false -// lldbr-check:(bool) x = false +// lldb-check:[...] false // lldb-command:continue #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/lexical-scope-in-unconditional-loop.rs b/tests/debuginfo/lexical-scope-in-unconditional-loop.rs index b1af018f3eb..dfec570218f 100644 --- a/tests/debuginfo/lexical-scope-in-unconditional-loop.rs +++ b/tests/debuginfo/lexical-scope-in-unconditional-loop.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -68,70 +66,57 @@ // FIRST ITERATION // lldb-command:v x -// lldbg-check:[...] 0 -// lldbr-check:(i32) x = 0 +// lldb-check:[...] 0 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 1 -// lldbr-check:(i32) x = 1 +// lldb-check:[...] 1 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 101 -// lldbr-check:(i32) x = 101 +// lldb-check:[...] 101 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 101 -// lldbr-check:(i32) x = 101 +// lldb-check:[...] 101 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] -987 -// lldbr-check:(i32) x = -987 +// lldb-check:[...] -987 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 101 -// lldbr-check:(i32) x = 101 +// lldb-check:[...] 101 // lldb-command:continue // SECOND ITERATION // lldb-command:v x -// lldbg-check:[...] 1 -// lldbr-check:(i32) x = 1 +// lldb-check:[...] 1 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 2 -// lldbr-check:(i32) x = 2 +// lldb-check:[...] 2 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 102 -// lldbr-check:(i32) x = 102 +// lldb-check:[...] 102 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 102 -// lldbr-check:(i32) x = 102 +// lldb-check:[...] 102 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] -987 -// lldbr-check:(i32) x = -987 +// lldb-check:[...] -987 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 102 -// lldbr-check:(i32) x = 102 +// lldb-check:[...] 102 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 2 -// lldbr-check:(i32) x = 2 +// lldb-check:[...] 2 // lldb-command:continue #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/lexical-scope-in-unique-closure.rs b/tests/debuginfo/lexical-scope-in-unique-closure.rs index a08c2af05cc..db84005121a 100644 --- a/tests/debuginfo/lexical-scope-in-unique-closure.rs +++ b/tests/debuginfo/lexical-scope-in-unique-closure.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -36,33 +34,27 @@ // lldb-command:run // lldb-command:v x -// lldbg-check:[...] false -// lldbr-check:(bool) x = false +// lldb-check:[...] false // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] false -// lldbr-check:(bool) x = false +// lldb-check:[...] false // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 1000 -// lldbr-check:(isize) x = 1000 +// lldb-check:[...] 1000 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 2.5 -// lldbr-check:(f64) x = 2.5 +// lldb-check:[...] 2.5 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] true -// lldbr-check:(bool) x = true +// lldb-check:[...] true // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] false -// lldbr-check:(bool) x = false +// lldb-check:[...] false // lldb-command:continue diff --git a/tests/debuginfo/lexical-scope-in-while.rs b/tests/debuginfo/lexical-scope-in-while.rs index bd885b5b10c..d6536d77545 100644 --- a/tests/debuginfo/lexical-scope-in-while.rs +++ b/tests/debuginfo/lexical-scope-in-while.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -68,70 +66,57 @@ // FIRST ITERATION // lldb-command:v x -// lldbg-check:[...] 0 -// lldbr-check:(i32) x = 0 +// lldb-check:[...] 0 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 1 -// lldbr-check:(i32) x = 1 +// lldb-check:[...] 1 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 101 -// lldbr-check:(i32) x = 101 +// lldb-check:[...] 101 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 101 -// lldbr-check:(i32) x = 101 +// lldb-check:[...] 101 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] -987 -// lldbr-check:(i32) x = -987 +// lldb-check:[...] -987 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 101 -// lldbr-check:(i32) x = 101 +// lldb-check:[...] 101 // lldb-command:continue // SECOND ITERATION // lldb-command:v x -// lldbg-check:[...] 1 -// lldbr-check:(i32) x = 1 +// lldb-check:[...] 1 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 2 -// lldbr-check:(i32) x = 2 +// lldb-check:[...] 2 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 102 -// lldbr-check:(i32) x = 102 +// lldb-check:[...] 102 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 102 -// lldbr-check:(i32) x = 102 +// lldb-check:[...] 102 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] -987 -// lldbr-check:(i32) x = -987 +// lldb-check:[...] -987 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 102 -// lldbr-check:(i32) x = 102 +// lldb-check:[...] 102 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 2 -// lldbr-check:(i32) x = 2 +// lldb-check:[...] 2 // lldb-command:continue #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/lexical-scope-with-macro.rs b/tests/debuginfo/lexical-scope-with-macro.rs index 7ea3dc62e45..6e8fef201ea 100644 --- a/tests/debuginfo/lexical-scope-with-macro.rs +++ b/tests/debuginfo/lexical-scope-with-macro.rs @@ -1,6 +1,3 @@ -//@ min-lldb-version: 310 -//@ ignore-lldb FIXME #48807 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -57,58 +54,48 @@ // lldb-command:run // lldb-command:v a -// lldbg-check:[...] 10 -// lldbr-check:(i32) a = 10 +// lldb-check:[...] 10 // lldb-command:v b -// lldbg-check:[...] 34 -// lldbr-check:(i32) b = 34 +// lldb-check:[...] 34 // lldb-command:continue // lldb-command:v a -// lldbg-check:[...] 890242 -// lldbr-check:(i32) a = 10 +// lldb-check:[...] 890242 // lldb-command:v b -// lldbg-check:[...] 34 -// lldbr-check:(i32) b = 34 +// lldb-check:[...] 34 // lldb-command:continue // lldb-command:v a -// lldbg-check:[...] 10 -// lldbr-check:(i32) a = 10 +// lldb-check:[...] 10 // lldb-command:v b -// lldbg-check:[...] 34 -// lldbr-check:(i32) b = 34 +// lldb-check:[...] 34 // lldb-command:continue // lldb-command:v a -// lldbg-check:[...] 102 -// lldbr-check:(i32) a = 10 +// lldb-check:[...] 102 // lldb-command:v b -// lldbg-check:[...] 34 -// lldbr-check:(i32) b = 34 +// lldb-check:[...] 34 // lldb-command:continue -// Don't test this with rust-enabled lldb for now; see issue #48807 -// lldbg-command:print a -// lldbg-check:[...] 110 -// lldbg-command:print b -// lldbg-check:[...] 34 -// lldbg-command:continue +// lldb-command:print a +// lldb-check:[...] 110 +// lldb-command:print b +// lldb-check:[...] 34 +// lldb-command:continue -// lldbg-command:print a -// lldbg-check:[...] 10 -// lldbg-command:print b -// lldbg-check:[...] 34 -// lldbg-command:continue - -// lldbg-command:print a -// lldbg-check:[...] 10 -// lldbg-command:print b -// lldbg-check:[...] 34 -// lldbg-command:print c -// lldbg-check:[...] 400 -// lldbg-command:continue +// lldb-command:print a +// lldb-check:[...] 10 +// lldb-command:print b +// lldb-check:[...] 34 +// lldb-command:continue +// lldb-command:print a +// lldb-check:[...] 10 +// lldb-command:print b +// lldb-check:[...] 34 +// lldb-command:print c +// lldb-check:[...] 400 +// lldb-command:continue #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] diff --git a/tests/debuginfo/lexical-scopes-in-block-expression.rs b/tests/debuginfo/lexical-scopes-in-block-expression.rs index 5ff70270ea6..cd27c88db58 100644 --- a/tests/debuginfo/lexical-scopes-in-block-expression.rs +++ b/tests/debuginfo/lexical-scopes-in-block-expression.rs @@ -1,14 +1,10 @@ -//@ min-lldb-version: 310 -//@ ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 - //@ compile-flags:-g // === GDB TESTS =================================================================================== // gdb-command:run -// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' -// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT +// gdb-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$1 = 0 // STRUCT EXPRESSION @@ -20,8 +16,7 @@ // gdb-command:print val // gdb-check:$4 = 11 -// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' -// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT +// gdb-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$5 = 1 // gdb-command:print ten // gdb-check:$6 = 10 @@ -42,8 +37,7 @@ // gdb-command:print val // gdb-check:$11 = 12 -// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' -// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT +// gdb-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$12 = 2 // gdb-command:print ten // gdb-check:$13 = 10 @@ -64,8 +58,7 @@ // gdb-command:print val // gdb-check:$18 = 13 -// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' -// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT +// gdb-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$19 = 3 // gdb-command:print ten // gdb-check:$20 = 10 @@ -86,8 +79,7 @@ // gdb-command:print val // gdb-check:$25 = 14 -// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' -// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT +// gdb-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$26 = 4 // gdb-command:print ten // gdb-check:$27 = 10 @@ -108,8 +100,7 @@ // gdb-command:print val // gdb-check:$32 = 15 -// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' -// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT +// gdb-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$33 = 5 // gdb-command:print ten // gdb-check:$34 = 10 @@ -130,8 +121,7 @@ // gdb-command:print val // gdb-check:$39 = 16 -// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' -// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT +// gdb-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$40 = 6 // gdb-command:print ten // gdb-check:$41 = 10 @@ -153,8 +143,7 @@ // gdb-command:print val // gdb-check:$46 = 17 -// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' -// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT +// gdb-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$47 = 7 // gdb-command:print ten // gdb-check:$48 = 10 @@ -175,8 +164,7 @@ // gdb-command:print val // gdb-check:$53 = 18 -// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' -// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT +// gdb-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$54 = 8 // gdb-command:print ten // gdb-check:$55 = 10 @@ -195,203 +183,155 @@ // STRUCT EXPRESSION // lldb-command:v val -// lldbg-check:[...] -1 -// lldbr-check:(i32) val = -1 +// lldb-check:[...] -1 // lldb-command:v ten -// lldbg-check:[...] 10 -// lldbr-check:(isize) ten = 10 +// lldb-check:[...] 10 // lldb-command:continue // lldb-command:v val -// lldbg-check:[...] 11 -// lldbr-check:(isize) val = 11 +// lldb-check:[...] 11 // lldb-command:v ten -// lldbg-check:[...] 10 -// lldbr-check:(isize) ten = 10 +// lldb-check:[...] 10 // lldb-command:continue // lldb-command:v val -// lldbg-check:[...] -1 -// lldbr-check:(i32) val = -1 +// lldb-check:[...] -1 // lldb-command:v ten -// lldbg-check:[...] 10 -// lldbr-check:(isize) ten = 10 +// lldb-check:[...] 10 // lldb-command:continue // FUNCTION CALL // lldb-command:v val -// lldbg-check:[...] -1 -// lldbr-check:(i32) val = -1 +// lldb-check:[...] -1 // lldb-command:v ten -// lldbg-check:[...] 10 -// lldbr-check:(isize) ten = 10 +// lldb-check:[...] 10 // lldb-command:continue // lldb-command:v val -// lldbg-check:[...] 12 -// lldbr-check:(isize) val = 12 +// lldb-check:[...] 12 // lldb-command:v ten -// lldbg-check:[...] 10 -// lldbr-check:(isize) ten = 10 +// lldb-check:[...] 10 // lldb-command:continue // lldb-command:v val -// lldbg-check:[...] -1 -// lldbr-check:(i32) val = -1 +// lldb-check:[...] -1 // lldb-command:v ten -// lldbg-check:[...] 10 -// lldbr-check:(isize) ten = 10 +// lldb-check:[...] 10 // lldb-command:continue // TUPLE EXPRESSION // lldb-command:v val -// lldbg-check:[...] -1 -// lldbr-check:(i32) val = -1 +// lldb-check:[...] -1 // lldb-command:v ten -// lldbg-check:[...] 10 -// lldbr-check:(isize) ten = 10 +// lldb-check:[...] 10 // lldb-command:continue // lldb-command:v val -// lldbg-check:[...] 13 -// lldbr-check:(isize) val = 13 +// lldb-check:[...] 13 // lldb-command:v ten -// lldbg-check:[...] 10 -// lldbr-check:(isize) ten = 10 +// lldb-check:[...] 10 // lldb-command:continue // lldb-command:v val -// lldbg-check:[...] -1 -// lldbr-check:(i32) val = -1 +// lldb-check:[...] -1 // lldb-command:v ten -// lldbg-check:[...] 10 -// lldbr-check:(isize) ten = 10 +// lldb-check:[...] 10 // lldb-command:continue // VEC EXPRESSION // lldb-command:v val -// lldbg-check:[...] -1 -// lldbr-check:(i32) val = -1 +// lldb-check:[...] -1 // lldb-command:v ten -// lldbg-check:[...] 10 -// lldbr-check:(isize) ten = 10 +// lldb-check:[...] 10 // lldb-command:continue // lldb-command:v val -// lldbg-check:[...] 14 -// lldbr-check:(isize) val = 14 +// lldb-check:[...] 14 // lldb-command:v ten -// lldbg-check:[...] 10 -// lldbr-check:(isize) ten = 10 +// lldb-check:[...] 10 // lldb-command:continue // lldb-command:v val -// lldbg-check:[...] -1 -// lldbr-check:(i32) val = -1 +// lldb-check:[...] -1 // lldb-command:v ten -// lldbg-check:[...] 10 -// lldbr-check:(isize) ten = 10 +// lldb-check:[...] 10 // lldb-command:continue // REPEAT VEC EXPRESSION // lldb-command:v val -// lldbg-check:[...] -1 -// lldbr-check:(i32) val = -1 +// lldb-check:[...] -1 // lldb-command:v ten -// lldbg-check:[...] 10 -// lldbr-check:(isize) ten = 10 +// lldb-check:[...] 10 // lldb-command:continue // lldb-command:v val -// lldbg-check:[...] 15 -// lldbr-check:(isize) val = 15 +// lldb-check:[...] 15 // lldb-command:v ten -// lldbg-check:[...] 10 -// lldbr-check:(isize) ten = 10 +// lldb-check:[...] 10 // lldb-command:continue // lldb-command:v val -// lldbg-check:[...] -1 -// lldbr-check:(i32) val = -1 +// lldb-check:[...] -1 // lldb-command:v ten -// lldbg-check:[...] 10 -// lldbr-check:(isize) ten = 10 +// lldb-check:[...] 10 // lldb-command:continue // ASSIGNMENT EXPRESSION // lldb-command:v val -// lldbg-check:[...] -1 -// lldbr-check:(i32) val = -1 +// lldb-check:[...] -1 // lldb-command:v ten -// lldbg-check:[...] 10 -// lldbr-check:(isize) ten = 10 +// lldb-check:[...] 10 // lldb-command:continue // lldb-command:v val -// lldbg-check:[...] 16 -// lldbr-check:(isize) val = 16 +// lldb-check:[...] 16 // lldb-command:v ten -// lldbg-check:[...] 10 -// lldbr-check:(isize) ten = 10 +// lldb-check:[...] 10 // lldb-command:continue // lldb-command:v val -// lldbg-check:[...] -1 -// lldbr-check:(i32) val = -1 +// lldb-check:[...] -1 // lldb-command:v ten -// lldbg-check:[...] 10 -// lldbr-check:(isize) ten = 10 +// lldb-check:[...] 10 // lldb-command:continue // ARITHMETIC EXPRESSION // lldb-command:v val -// lldbg-check:[...] -1 -// lldbr-check:(i32) val = -1 +// lldb-check:[...] -1 // lldb-command:v ten -// lldbg-check:[...] 10 -// lldbr-check:(isize) ten = 10 +// lldb-check:[...] 10 // lldb-command:continue // lldb-command:v val -// lldbg-check:[...] 17 -// lldbr-check:(isize) val = 17 +// lldb-check:[...] 17 // lldb-command:v ten -// lldbg-check:[...] 10 -// lldbr-check:(isize) ten = 10 +// lldb-check:[...] 10 // lldb-command:continue // lldb-command:v val -// lldbg-check:[...] -1 -// lldbr-check:(i32) val = -1 +// lldb-check:[...] -1 // lldb-command:v ten -// lldbg-check:[...] 10 -// lldbr-check:(isize) ten = 10 +// lldb-check:[...] 10 // lldb-command:continue // INDEX EXPRESSION // lldb-command:v val -// lldbg-check:[...] -1 -// lldbr-check:(i32) val = -1 +// lldb-check:[...] -1 // lldb-command:v ten -// lldbg-check:[...] 10 -// lldbr-check:(isize) ten = 10 +// lldb-check:[...] 10 // lldb-command:continue // lldb-command:v val -// lldbg-check:[...] 18 -// lldbr-check:(isize) val = 18 +// lldb-check:[...] 18 // lldb-command:v ten -// lldbg-check:[...] 10 -// lldbr-check:(isize) ten = 10 +// lldb-check:[...] 10 // lldb-command:continue // lldb-command:v val -// lldbg-check:[...] -1 -// lldbr-check:(i32) val = -1 +// lldb-check:[...] -1 // lldb-command:v ten -// lldbg-check:[...] 10 -// lldbr-check:(isize) ten = 10 +// lldb-check:[...] 10 // lldb-command:continue #![allow(unused_variables)] diff --git a/tests/debuginfo/limited-debuginfo.rs b/tests/debuginfo/limited-debuginfo.rs index 32f14955bfa..fb453d8078c 100644 --- a/tests/debuginfo/limited-debuginfo.rs +++ b/tests/debuginfo/limited-debuginfo.rs @@ -1,18 +1,13 @@ //@ ignore-lldb -//@ ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 //@ compile-flags:-C debuginfo=1 // Make sure functions have proper names // gdb-command:info functions -// gdbg-check:[...]void[...]main([...]); -// gdbr-check:fn limited_debuginfo::main(); -// gdbg-check:[...]void[...]some_function([...]); -// gdbr-check:fn limited_debuginfo::some_function(); -// gdbg-check:[...]void[...]some_other_function([...]); -// gdbr-check:fn limited_debuginfo::some_other_function(); -// gdbg-check:[...]void[...]zzz([...]); -// gdbr-check:fn limited_debuginfo::zzz(); +// gdb-check:fn limited_debuginfo::main(); +// gdb-check:fn limited_debuginfo::some_function(); +// gdb-check:fn limited_debuginfo::some_other_function(); +// gdb-check:fn limited_debuginfo::zzz(); // gdb-command:run diff --git a/tests/debuginfo/macro-stepping.rs b/tests/debuginfo/macro-stepping.rs index 5f8d8287168..35bb6de4fef 100644 --- a/tests/debuginfo/macro-stepping.rs +++ b/tests/debuginfo/macro-stepping.rs @@ -1,8 +1,7 @@ -//@ ignore-windows //@ ignore-android //@ ignore-aarch64 -//@ min-lldb-version: 310 -//@ ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 +//@ min-lldb-version: 1800 +//@ min-gdb-version: 13.0 //@ aux-build:macro-stepping.rs @@ -11,7 +10,8 @@ #[macro_use] extern crate macro_stepping; // exports new_scope!() -//@ compile-flags:-g +//@ compile-flags:-g -Zmir-enable-passes=-SingleUseConsts +// SingleUseConsts shouldn't need to be disabled, see #128945 // === GDB TESTS =================================================================================== diff --git a/tests/debuginfo/method-on-enum.rs b/tests/debuginfo/method-on-enum.rs index 8a57060717e..a570144450d 100644 --- a/tests/debuginfo/method-on-enum.rs +++ b/tests/debuginfo/method-on-enum.rs @@ -1,5 +1,5 @@ -//@ min-lldb-version: 310 -//@ ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 +//@ min-lldb-version: 1800 +//@ min-gdb-version: 13.0 //@ compile-flags:-g @@ -9,8 +9,7 @@ // STACK BY REF // gdb-command:print *self -// gdbg-check:$1 = {{RUST$ENUM$DISR = Variant2, [...]}, {RUST$ENUM$DISR = Variant2, __0 = 117901063}} -// gdbr-check:$1 = method_on_enum::Enum::Variant2(117901063) +// gdb-check:$1 = method_on_enum::Enum::Variant2(117901063) // gdb-command:print arg1 // gdb-check:$2 = -1 // gdb-command:print arg2 @@ -19,8 +18,7 @@ // STACK BY VAL // gdb-command:print self -// gdbg-check:$4 = {{RUST$ENUM$DISR = Variant2, [...]}, {RUST$ENUM$DISR = Variant2, __0 = 117901063}} -// gdbr-check:$4 = method_on_enum::Enum::Variant2(117901063) +// gdb-check:$4 = method_on_enum::Enum::Variant2(117901063) // gdb-command:print arg1 // gdb-check:$5 = -3 // gdb-command:print arg2 @@ -29,8 +27,7 @@ // OWNED BY REF // gdb-command:print *self -// gdbg-check:$7 = {{RUST$ENUM$DISR = Variant1, x = 1799, y = 1799}, {RUST$ENUM$DISR = Variant1, [...]}} -// gdbr-check:$7 = method_on_enum::Enum::Variant1{x: 1799, y: 1799} +// gdb-check:$7 = method_on_enum::Enum::Variant1{x: 1799, y: 1799} // gdb-command:print arg1 // gdb-check:$8 = -5 // gdb-command:print arg2 @@ -39,8 +36,7 @@ // OWNED BY VAL // gdb-command:print self -// gdbg-check:$10 = {{RUST$ENUM$DISR = Variant1, x = 1799, y = 1799}, {RUST$ENUM$DISR = Variant1, [...]}} -// gdbr-check:$10 = method_on_enum::Enum::Variant1{x: 1799, y: 1799} +// gdb-check:$10 = method_on_enum::Enum::Variant1{x: 1799, y: 1799} // gdb-command:print arg1 // gdb-check:$11 = -7 // gdb-command:print arg2 @@ -49,8 +45,7 @@ // OWNED MOVED // gdb-command:print *self -// gdbg-check:$13 = {{RUST$ENUM$DISR = Variant1, x = 1799, y = 1799}, {RUST$ENUM$DISR = Variant1, [...]}} -// gdbr-check:$13 = method_on_enum::Enum::Variant1{x: 1799, y: 1799} +// gdb-check:$13 = method_on_enum::Enum::Variant1{x: 1799, y: 1799} // gdb-command:print arg1 // gdb-check:$14 = -9 // gdb-command:print arg2 diff --git a/tests/debuginfo/method-on-generic-struct.rs b/tests/debuginfo/method-on-generic-struct.rs index 64ef0e6bb0c..1e6c9d66178 100644 --- a/tests/debuginfo/method-on-generic-struct.rs +++ b/tests/debuginfo/method-on-generic-struct.rs @@ -1,7 +1,3 @@ -// Some versions of the non-rust-enabled LLDB print the wrong generic -// parameter type names in this test. -//@ needs-rust-lldb - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -10,8 +6,7 @@ // STACK BY REF // gdb-command:print *self -// gdbg-check:$1 = {x = {__0 = 8888, __1 = -8888}} -// gdbr-check:$1 = method_on_generic_struct::Struct<(u32, i32)> {x: (8888, -8888)} +// gdb-check:$1 = method_on_generic_struct::Struct<(u32, i32)> {x: (8888, -8888)} // gdb-command:print arg1 // gdb-check:$2 = -1 // gdb-command:print arg2 @@ -20,8 +15,7 @@ // STACK BY VAL // gdb-command:print self -// gdbg-check:$4 = {x = {__0 = 8888, __1 = -8888}} -// gdbr-check:$4 = method_on_generic_struct::Struct<(u32, i32)> {x: (8888, -8888)} +// gdb-check:$4 = method_on_generic_struct::Struct<(u32, i32)> {x: (8888, -8888)} // gdb-command:print arg1 // gdb-check:$5 = -3 // gdb-command:print arg2 @@ -30,8 +24,7 @@ // OWNED BY REF // gdb-command:print *self -// gdbg-check:$7 = {x = 1234.5} -// gdbr-check:$7 = method_on_generic_struct::Struct {x: 1234.5} +// gdb-check:$7 = method_on_generic_struct::Struct {x: 1234.5} // gdb-command:print arg1 // gdb-check:$8 = -5 // gdb-command:print arg2 @@ -40,8 +33,7 @@ // OWNED BY VAL // gdb-command:print self -// gdbg-check:$10 = {x = 1234.5} -// gdbr-check:$10 = method_on_generic_struct::Struct {x: 1234.5} +// gdb-check:$10 = method_on_generic_struct::Struct {x: 1234.5} // gdb-command:print arg1 // gdb-check:$11 = -7 // gdb-command:print arg2 @@ -50,8 +42,7 @@ // OWNED MOVED // gdb-command:print *self -// gdbg-check:$13 = {x = 1234.5} -// gdbr-check:$13 = method_on_generic_struct::Struct {x: 1234.5} +// gdb-check:$13 = method_on_generic_struct::Struct {x: 1234.5} // gdb-command:print arg1 // gdb-check:$14 = -9 // gdb-command:print arg2 @@ -65,62 +56,47 @@ // STACK BY REF // lldb-command:v *self -// lldbg-check:[...] Struct<(u32, i32)> { x: (8888, -8888) } -// lldbr-check:(method_on_generic_struct::Struct<(u32, i32)>) *self = { x = { = 8888 = -8888 } } +// lldb-check:[...]Struct<(u32, i32)>) *self = { x = { 0 = 8888 1 = -8888 } } // lldb-command:v arg1 -// lldbg-check:[...] -1 -// lldbr-check:(isize) arg1 = -1 +// lldb-check:[...] -1 // lldb-command:v arg2 -// lldbg-check:[...] -2 -// lldbr-check:(isize) arg2 = -2 +// lldb-check:[...] -2 // lldb-command:continue // STACK BY VAL // lldb-command:v self -// lldbg-check:[...] Struct<(u32, i32)> { x: (8888, -8888) } -// lldbr-check:(method_on_generic_struct::Struct<(u32, i32)>) self = { x = { = 8888 = -8888 } } +// lldb-check:[...]Struct<(u32, i32)>) self = { x = { 0 = 8888 1 = -8888 } } // lldb-command:v arg1 -// lldbg-check:[...] -3 -// lldbr-check:(isize) arg1 = -3 +// lldb-check:[...] -3 // lldb-command:v arg2 -// lldbg-check:[...] -4 -// lldbr-check:(isize) arg2 = -4 +// lldb-check:[...] -4 // lldb-command:continue // OWNED BY REF // lldb-command:v *self -// lldbg-check:[...] Struct { x: 1234.5 } -// lldbr-check:(method_on_generic_struct::Struct) *self = Struct { x: 1234.5 } +// lldb-check:[...]Struct) *self = { x = 1234.5 } // lldb-command:v arg1 -// lldbg-check:[...] -5 -// lldbr-check:(isize) arg1 = -5 +// lldb-check:[...] -5 // lldb-command:v arg2 -// lldbg-check:[...] -6 -// lldbr-check:(isize) arg2 = -6 +// lldb-check:[...] -6 // lldb-command:continue // OWNED BY VAL // lldb-command:v self -// lldbg-check:[...] Struct { x: 1234.5 } -// lldbr-check:(method_on_generic_struct::Struct) self = Struct { x: 1234.5 } +// lldb-check:[...]Struct) self = { x = 1234.5 } // lldb-command:v arg1 -// lldbg-check:[...] -7 -// lldbr-check:(isize) arg1 = -7 +// lldb-check:[...] -7 // lldb-command:v arg2 -// lldbg-check:[...] -8 -// lldbr-check:(isize) arg2 = -8 +// lldb-check:[...] -8 // lldb-command:continue // OWNED MOVED // lldb-command:v *self -// lldbg-check:[...] Struct { x: 1234.5 } -// lldbr-check:(method_on_generic_struct::Struct) *self = Struct { x: 1234.5 } +// lldb-check:[...]Struct) *self = { x = 1234.5 } // lldb-command:v arg1 -// lldbg-check:[...] -9 -// lldbr-check:(isize) arg1 = -9 +// lldb-check:[...] -9 // lldb-command:v arg2 -// lldbg-check:[...] -10 -// lldbr-check:(isize) arg2 = -10 +// lldb-check:[...] -10 // lldb-command:continue #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/method-on-struct.rs b/tests/debuginfo/method-on-struct.rs index a4129af5429..91f609365e9 100644 --- a/tests/debuginfo/method-on-struct.rs +++ b/tests/debuginfo/method-on-struct.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -8,8 +6,7 @@ // STACK BY REF // gdb-command:print *self -// gdbg-check:$1 = {x = 100} -// gdbr-check:$1 = method_on_struct::Struct {x: 100} +// gdb-check:$1 = method_on_struct::Struct {x: 100} // gdb-command:print arg1 // gdb-check:$2 = -1 // gdb-command:print arg2 @@ -18,8 +15,7 @@ // STACK BY VAL // gdb-command:print self -// gdbg-check:$4 = {x = 100} -// gdbr-check:$4 = method_on_struct::Struct {x: 100} +// gdb-check:$4 = method_on_struct::Struct {x: 100} // gdb-command:print arg1 // gdb-check:$5 = -3 // gdb-command:print arg2 @@ -28,8 +24,7 @@ // OWNED BY REF // gdb-command:print *self -// gdbg-check:$7 = {x = 200} -// gdbr-check:$7 = method_on_struct::Struct {x: 200} +// gdb-check:$7 = method_on_struct::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$8 = -5 // gdb-command:print arg2 @@ -38,8 +33,7 @@ // OWNED BY VAL // gdb-command:print self -// gdbg-check:$10 = {x = 200} -// gdbr-check:$10 = method_on_struct::Struct {x: 200} +// gdb-check:$10 = method_on_struct::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$11 = -7 // gdb-command:print arg2 @@ -48,8 +42,7 @@ // OWNED MOVED // gdb-command:print *self -// gdbg-check:$13 = {x = 200} -// gdbr-check:$13 = method_on_struct::Struct {x: 200} +// gdb-check:$13 = method_on_struct::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$14 = -9 // gdb-command:print arg2 @@ -63,62 +56,47 @@ // STACK BY REF // lldb-command:v *self -// lldbg-check:[...] { x = 100 } -// lldbr-check:(method_on_struct::Struct) *self = Struct { x: 100 } +// lldb-check:[...] { x = 100 } // lldb-command:v arg1 -// lldbg-check:[...] -1 -// lldbr-check:(isize) arg1 = -1 +// lldb-check:[...] -1 // lldb-command:v arg2 -// lldbg-check:[...] -2 -// lldbr-check:(isize) arg2 = -2 +// lldb-check:[...] -2 // lldb-command:continue // STACK BY VAL // lldb-command:v self -// lldbg-check:[...] { x = 100 } -// lldbr-check:(method_on_struct::Struct) self = Struct { x: 100 } +// lldb-check:[...] { x = 100 } // lldb-command:v arg1 -// lldbg-check:[...] -3 -// lldbr-check:(isize) arg1 = -3 +// lldb-check:[...] -3 // lldb-command:v arg2 -// lldbg-check:[...] -4 -// lldbr-check:(isize) arg2 = -4 +// lldb-check:[...] -4 // lldb-command:continue // OWNED BY REF // lldb-command:v *self -// lldbg-check:[...] { x = 200 } -// lldbr-check:(method_on_struct::Struct) *self = Struct { x: 200 } +// lldb-check:[...] { x = 200 } // lldb-command:v arg1 -// lldbg-check:[...] -5 -// lldbr-check:(isize) arg1 = -5 +// lldb-check:[...] -5 // lldb-command:v arg2 -// lldbg-check:[...] -6 -// lldbr-check:(isize) arg2 = -6 +// lldb-check:[...] -6 // lldb-command:continue // OWNED BY VAL // lldb-command:v self -// lldbg-check:[...] { x = 200 } -// lldbr-check:(method_on_struct::Struct) self = Struct { x: 200 } +// lldb-check:[...] { x = 200 } // lldb-command:v arg1 -// lldbg-check:[...] -7 -// lldbr-check:(isize) arg1 = -7 +// lldb-check:[...] -7 // lldb-command:v arg2 -// lldbg-check:[...] -8 -// lldbr-check:(isize) arg2 = -8 +// lldb-check:[...] -8 // lldb-command:continue // OWNED MOVED // lldb-command:v *self -// lldbg-check:[...] { x = 200 } -// lldbr-check:(method_on_struct::Struct) *self = Struct { x: 200 } +// lldb-check:[...] { x = 200 } // lldb-command:v arg1 -// lldbg-check:[...] -9 -// lldbr-check:(isize) arg1 = -9 +// lldb-check:[...] -9 // lldb-command:v arg2 -// lldbg-check:[...] -10 -// lldbr-check:(isize) arg2 = -10 +// lldb-check:[...] -10 // lldb-command:continue #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/method-on-trait.rs b/tests/debuginfo/method-on-trait.rs index 0934c267ab1..7b95e1f81c7 100644 --- a/tests/debuginfo/method-on-trait.rs +++ b/tests/debuginfo/method-on-trait.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -8,8 +6,7 @@ // STACK BY REF // gdb-command:print *self -// gdbg-check:$1 = {x = 100} -// gdbr-check:$1 = method_on_trait::Struct {x: 100} +// gdb-check:$1 = method_on_trait::Struct {x: 100} // gdb-command:print arg1 // gdb-check:$2 = -1 // gdb-command:print arg2 @@ -18,8 +15,7 @@ // STACK BY VAL // gdb-command:print self -// gdbg-check:$4 = {x = 100} -// gdbr-check:$4 = method_on_trait::Struct {x: 100} +// gdb-check:$4 = method_on_trait::Struct {x: 100} // gdb-command:print arg1 // gdb-check:$5 = -3 // gdb-command:print arg2 @@ -28,8 +24,7 @@ // OWNED BY REF // gdb-command:print *self -// gdbg-check:$7 = {x = 200} -// gdbr-check:$7 = method_on_trait::Struct {x: 200} +// gdb-check:$7 = method_on_trait::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$8 = -5 // gdb-command:print arg2 @@ -38,8 +33,7 @@ // OWNED BY VAL // gdb-command:print self -// gdbg-check:$10 = {x = 200} -// gdbr-check:$10 = method_on_trait::Struct {x: 200} +// gdb-check:$10 = method_on_trait::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$11 = -7 // gdb-command:print arg2 @@ -48,8 +42,7 @@ // OWNED MOVED // gdb-command:print *self -// gdbg-check:$13 = {x = 200} -// gdbr-check:$13 = method_on_trait::Struct {x: 200} +// gdb-check:$13 = method_on_trait::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$14 = -9 // gdb-command:print arg2 @@ -63,62 +56,47 @@ // STACK BY REF // lldb-command:v *self -// lldbg-check:[...] { x = 100 } -// lldbr-check:(method_on_trait::Struct) *self = { x = 100 } +// lldb-check:[...] { x = 100 } // lldb-command:v arg1 -// lldbg-check:[...] -1 -// lldbr-check:(isize) arg1 = -1 +// lldb-check:[...] -1 // lldb-command:v arg2 -// lldbg-check:[...] -2 -// lldbr-check:(isize) arg2 = -2 +// lldb-check:[...] -2 // lldb-command:continue // STACK BY VAL // lldb-command:v self -// lldbg-check:[...] { x = 100 } -// lldbr-check:(method_on_trait::Struct) self = { x = 100 } +// lldb-check:[...] { x = 100 } // lldb-command:v arg1 -// lldbg-check:[...] -3 -// lldbr-check:(isize) arg1 = -3 +// lldb-check:[...] -3 // lldb-command:v arg2 -// lldbg-check:[...] -4 -// lldbr-check:(isize) arg2 = -4 +// lldb-check:[...] -4 // lldb-command:continue // OWNED BY REF // lldb-command:v *self -// lldbg-check:[...] { x = 200 } -// lldbr-check:(method_on_trait::Struct) *self = { x = 200 } +// lldb-check:[...] { x = 200 } // lldb-command:v arg1 -// lldbg-check:[...] -5 -// lldbr-check:(isize) arg1 = -5 +// lldb-check:[...] -5 // lldb-command:v arg2 -// lldbg-check:[...] -6 -// lldbr-check:(isize) arg2 = -6 +// lldb-check:[...] -6 // lldb-command:continue // OWNED BY VAL // lldb-command:v self -// lldbg-check:[...] { x = 200 } -// lldbr-check:(method_on_trait::Struct) self = { x = 200 } +// lldb-check:[...] { x = 200 } // lldb-command:v arg1 -// lldbg-check:[...] -7 -// lldbr-check:(isize) arg1 = -7 +// lldb-check:[...] -7 // lldb-command:v arg2 -// lldbg-check:[...] -8 -// lldbr-check:(isize) arg2 = -8 +// lldb-check:[...] -8 // lldb-command:continue // OWNED MOVED // lldb-command:v *self -// lldbg-check:[...] { x = 200 } -// lldbr-check:(method_on_trait::Struct) *self = { x = 200 } +// lldb-check:[...] { x = 200 } // lldb-command:v arg1 -// lldbg-check:[...] -9 -// lldbr-check:(isize) arg1 = -9 +// lldb-check:[...] -9 // lldb-command:v arg2 -// lldbg-check:[...] -10 -// lldbr-check:(isize) arg2 = -10 +// lldb-check:[...] -10 // lldb-command:continue #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/method-on-tuple-struct.rs b/tests/debuginfo/method-on-tuple-struct.rs index 9cf9c6d7fba..04c00d88302 100644 --- a/tests/debuginfo/method-on-tuple-struct.rs +++ b/tests/debuginfo/method-on-tuple-struct.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -8,8 +6,7 @@ // STACK BY REF // gdb-command:print *self -// gdbg-check:$1 = {__0 = 100, __1 = -100.5} -// gdbr-check:$1 = method_on_tuple_struct::TupleStruct (100, -100.5) +// gdb-check:$1 = method_on_tuple_struct::TupleStruct (100, -100.5) // gdb-command:print arg1 // gdb-check:$2 = -1 // gdb-command:print arg2 @@ -18,8 +15,7 @@ // STACK BY VAL // gdb-command:print self -// gdbg-check:$4 = {__0 = 100, __1 = -100.5} -// gdbr-check:$4 = method_on_tuple_struct::TupleStruct (100, -100.5) +// gdb-check:$4 = method_on_tuple_struct::TupleStruct (100, -100.5) // gdb-command:print arg1 // gdb-check:$5 = -3 // gdb-command:print arg2 @@ -28,8 +24,7 @@ // OWNED BY REF // gdb-command:print *self -// gdbg-check:$7 = {__0 = 200, __1 = -200.5} -// gdbr-check:$7 = method_on_tuple_struct::TupleStruct (200, -200.5) +// gdb-check:$7 = method_on_tuple_struct::TupleStruct (200, -200.5) // gdb-command:print arg1 // gdb-check:$8 = -5 // gdb-command:print arg2 @@ -38,8 +33,7 @@ // OWNED BY VAL // gdb-command:print self -// gdbg-check:$10 = {__0 = 200, __1 = -200.5} -// gdbr-check:$10 = method_on_tuple_struct::TupleStruct (200, -200.5) +// gdb-check:$10 = method_on_tuple_struct::TupleStruct (200, -200.5) // gdb-command:print arg1 // gdb-check:$11 = -7 // gdb-command:print arg2 @@ -48,8 +42,7 @@ // OWNED MOVED // gdb-command:print *self -// gdbg-check:$13 = {__0 = 200, __1 = -200.5} -// gdbr-check:$13 = method_on_tuple_struct::TupleStruct (200, -200.5) +// gdb-check:$13 = method_on_tuple_struct::TupleStruct (200, -200.5) // gdb-command:print arg1 // gdb-check:$14 = -9 // gdb-command:print arg2 @@ -63,62 +56,47 @@ // STACK BY REF // lldb-command:v *self -// lldbg-check:[...] { 0 = 100 1 = -100.5 } -// lldbr-check:(method_on_tuple_struct::TupleStruct) *self = { 0 = 100 1 = -100.5 } +// lldb-check:[...] { 0 = 100 1 = -100.5 } // lldb-command:v arg1 -// lldbg-check:[...] -1 -// lldbr-check:(isize) arg1 = -1 +// lldb-check:[...] -1 // lldb-command:v arg2 -// lldbg-check:[...] -2 -// lldbr-check:(isize) arg2 = -2 +// lldb-check:[...] -2 // lldb-command:continue // STACK BY VAL // lldb-command:v self -// lldbg-check:[...] { 0 = 100 1 = -100.5 } -// lldbr-check:(method_on_tuple_struct::TupleStruct) self = { 0 = 100 1 = -100.5 } +// lldb-check:[...] { 0 = 100 1 = -100.5 } // lldb-command:v arg1 -// lldbg-check:[...] -3 -// lldbr-check:(isize) arg1 = -3 +// lldb-check:[...] -3 // lldb-command:v arg2 -// lldbg-check:[...] -4 -// lldbr-check:(isize) arg2 = -4 +// lldb-check:[...] -4 // lldb-command:continue // OWNED BY REF // lldb-command:v *self -// lldbg-check:[...] { 0 = 200 1 = -200.5 } -// lldbr-check:(method_on_tuple_struct::TupleStruct) *self = { 0 = 200 1 = -200.5 } +// lldb-check:[...] { 0 = 200 1 = -200.5 } // lldb-command:v arg1 -// lldbg-check:[...] -5 -// lldbr-check:(isize) arg1 = -5 +// lldb-check:[...] -5 // lldb-command:v arg2 -// lldbg-check:[...] -6 -// lldbr-check:(isize) arg2 = -6 +// lldb-check:[...] -6 // lldb-command:continue // OWNED BY VAL // lldb-command:v self -// lldbg-check:[...] { 0 = 200 1 = -200.5 } -// lldbr-check:(method_on_tuple_struct::TupleStruct) self = { 0 = 200 1 = -200.5 } +// lldb-check:[...] { 0 = 200 1 = -200.5 } // lldb-command:v arg1 -// lldbg-check:[...] -7 -// lldbr-check:(isize) arg1 = -7 +// lldb-check:[...] -7 // lldb-command:v arg2 -// lldbg-check:[...] -8 -// lldbr-check:(isize) arg2 = -8 +// lldb-check:[...] -8 // lldb-command:continue // OWNED MOVED // lldb-command:v *self -// lldbg-check:[...] { 0 = 200 1 = -200.5 } -// lldbr-check:(method_on_tuple_struct::TupleStruct) *self = { 0 = 200 1 = -200.5 } +// lldb-check:[...] { 0 = 200 1 = -200.5 } // lldb-command:v arg1 -// lldbg-check:[...] -9 -// lldbr-check:(isize) arg1 = -9 +// lldb-check:[...] -9 // lldb-command:v arg2 -// lldbg-check:[...] -10 -// lldbr-check:(isize) arg2 = -10 +// lldb-check:[...] -10 // lldb-command:continue #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/msvc-pretty-enums.rs b/tests/debuginfo/msvc-pretty-enums.rs index a6032cc8642..d60a7b81944 100644 --- a/tests/debuginfo/msvc-pretty-enums.rs +++ b/tests/debuginfo/msvc-pretty-enums.rs @@ -6,72 +6,72 @@ // lldb-command:run // lldb-command:v a -// lldbg-check:(core::option::Option) a = { value = { 0 = Low } } +// lldb-check:(core::option::Option) a = { value = { 0 = Low } } // lldb-command:v b -// lldbg-check:(core::option::Option) b = { value = $discr$ = '\x01' } +// lldb-check:(core::option::Option) b = { value = $discr$ = '\x01' } // lldb-command:v c -// lldbg-check:(msvc_pretty_enums::NicheLayoutEnum) c = { value = $discr$ = '\x11' } +// lldb-check:(msvc_pretty_enums::NicheLayoutEnum) c = { value = $discr$ = '\x11' } // lldb-command:v d -// lldbg-check:(msvc_pretty_enums::NicheLayoutEnum) d = { value = { my_data = High } } +// lldb-check:(msvc_pretty_enums::NicheLayoutEnum) d = { value = { my_data = High } } // lldb-command:v e -// lldbg-check:(msvc_pretty_enums::NicheLayoutEnum) e = { value = $discr$ = '\x13' } +// lldb-check:(msvc_pretty_enums::NicheLayoutEnum) e = { value = $discr$ = '\x13' } // lldb-command:v h -// lldbg-check:(core::option::Option) h = { value = { 0 = 12 } $discr$ = 1 } +// lldb-check:(core::option::Option) h = { value = { 0 = 12 } $discr$ = 1 } // lldb-command:v i -// lldbg-check:(core::option::Option) i = { value = $discr$ = 0 } +// lldb-check:(core::option::Option) i = { value = $discr$ = 0 } // lldb-command:v j -// lldbg-check:(msvc_pretty_enums::CStyleEnum) j = High +// lldb-check:(msvc_pretty_enums::CStyleEnum) j = High // lldb-command:v k -// lldbg-check:(core::option::Option) k = { value = { 0 = "IAMA optional string!" { vec = size=21 { [0] = 'I' [1] = 'A' [2] = 'M' [3] = 'A' [4] = ' ' [5] = 'o' [6] = 'p' [7] = 't' [8] = 'i' [9] = 'o' [10] = 'n' [11] = 'a' [12] = 'l' [13] = ' ' [14] = 's' [15] = 't' [16] = 'r' [17] = 'i' [18] = 'n' [19] = 'g' [20] = '!' } } } } +// lldb-check:(core::option::Option) k = { value = { 0 = "IAMA optional string!" { vec = size=21 { [0] = 'I' [1] = 'A' [2] = 'M' [3] = 'A' [4] = ' ' [5] = 'o' [6] = 'p' [7] = 't' [8] = 'i' [9] = 'o' [10] = 'n' [11] = 'a' [12] = 'l' [13] = ' ' [14] = 's' [15] = 't' [16] = 'r' [17] = 'i' [18] = 'n' [19] = 'g' [20] = '!' } } } } // lldb-command:v l -// lldbg-check:(core::result::Result) l = { value = { 0 = {} } } +// lldb-check:(core::result::Result) l = { value = { 0 = {} } } // lldb-command:v niche128_some -// lldbg-check:(core::option::Option>) niche128_some = { value = $discr$ = 123456 } +// lldb-check:(core::option::Option>) niche128_some = { value = $discr$ = 123456 } // lldb-command:v niche128_none -// lldbg-check:(core::option::Option>) niche128_none = { value = $discr$ = 0 } +// lldb-check:(core::option::Option>) niche128_none = { value = $discr$ = 0 } // lldb-command:v wrapping_niche128_untagged -// lldbg-check:(msvc_pretty_enums::Wrapping128Niche) wrapping_niche128_untagged = { value = { 0 = { 0 = 340282366920938463463374607431768211454 } } } +// lldb-check:(msvc_pretty_enums::Wrapping128Niche) wrapping_niche128_untagged = { value = { 0 = { 0 = 340282366920938463463374607431768211454 } } } // lldb-command:v wrapping_niche128_none1 -// lldbg-check:(msvc_pretty_enums::Wrapping128Niche) wrapping_niche128_none1 = { value = { 0 = { 0 = 2 } } } +// lldb-check:(msvc_pretty_enums::Wrapping128Niche) wrapping_niche128_none1 = { value = { 0 = { 0 = 2 } } } // lldb-command:v direct_tag_128_a -// lldbg-check:(msvc_pretty_enums::DirectTag128) direct_tag_128_a = { value = { 0 = 42 } $discr$ = 0 } +// lldb-check:(msvc_pretty_enums::DirectTag128) direct_tag_128_a = { value = { 0 = 42 } $discr$ = 0 } // lldb-command:v direct_tag_128_b -// lldbg-check:(msvc_pretty_enums::DirectTag128) direct_tag_128_b = { value = { 0 = 137 } $discr$ = 1 } +// lldb-check:(msvc_pretty_enums::DirectTag128) direct_tag_128_b = { value = { 0 = 137 } $discr$ = 1 } // &u32 is incorrectly formatted and LLDB thinks it's a char* so skipping niche_w_fields_1_some // lldb-command:v niche_w_fields_1_none -// lldbg-check:(msvc_pretty_enums::NicheLayoutWithFields1) niche_w_fields_1_none = { value = { 0 = 99 } $discr$ = 1 } +// lldb-check:(msvc_pretty_enums::NicheLayoutWithFields1) niche_w_fields_1_none = { value = { 0 = 99 } $discr$ = 1 } // lldb-command:v niche_w_fields_2_some -// lldbg-check:(msvc_pretty_enums::NicheLayoutWithFields2) niche_w_fields_2_some = { value = { 0 = 800 { __0 = { 0 = 800 } } 1 = 900 } $discr$ = 0 } +// lldb-check:(msvc_pretty_enums::NicheLayoutWithFields2) niche_w_fields_2_some = { value = { 0 = 800 { __0 = { 0 = 800 } } 1 = 900 } $discr$ = 0 } // lldb-command:v niche_w_fields_3_some -// lldbg-check:(msvc_pretty_enums::NicheLayoutWithFields3) niche_w_fields_3_some = { value = { 0 = '\x89' 1 = true } } +// lldb-check:(msvc_pretty_enums::NicheLayoutWithFields3) niche_w_fields_3_some = { value = { 0 = '\x89' 1 = true } } // lldb-command:v niche_w_fields_3_niche3 -// lldbg-check:(msvc_pretty_enums::NicheLayoutWithFields3) niche_w_fields_3_niche3 = { value = { 0 = '"' } $discr$ = '\x04' } +// lldb-check:(msvc_pretty_enums::NicheLayoutWithFields3) niche_w_fields_3_niche3 = { value = { 0 = '"' } $discr$ = '\x04' } // lldb-command:v arbitrary_discr1 -// lldbg-check:(msvc_pretty_enums::ArbitraryDiscr) arbitrary_discr1 = { value = { 0 = 1234 } $discr$ = 1000 } +// lldb-check:(msvc_pretty_enums::ArbitraryDiscr) arbitrary_discr1 = { value = { 0 = 1234 } $discr$ = 1000 } // lldb-command:v arbitrary_discr2 -// lldbg-check:(msvc_pretty_enums::ArbitraryDiscr) arbitrary_discr2 = { value = { 0 = 5678 } $discr$ = 5000000 } +// lldb-check:(msvc_pretty_enums::ArbitraryDiscr) arbitrary_discr2 = { value = { 0 = 5678 } $discr$ = 5000000 } // === CDB TESTS ================================================================================== @@ -206,6 +206,30 @@ // cdb-command: dx -r2 arbitrary_discr2,d // cdb-check: arbitrary_discr2,d : Def [Type: enum2$] // cdb-check: [+0x[...]] __0 : 5678 [Type: unsigned int] +// +// cdb-command: dx c_style_u128_a +// cdb-check: c_style_u128_a : A [Type: enum2$] +// +// cdb-command: dx c_style_u128_b +// cdb-check: c_style_u128_b : B [Type: enum2$] +// +// cdb-command: dx c_style_u128_c +// cdb-check: c_style_u128_c : C [Type: enum2$] +// +// cdb-command: dx c_style_u128_d +// cdb-check: c_style_u128_d : D [Type: enum2$] +// +// cdb-command: dx c_style_i128_a +// cdb-check: c_style_i128_a : A [Type: enum2$] +// +// cdb-command: dx c_style_i128_b +// cdb-check: c_style_i128_b : B [Type: enum2$] +// +// cdb-command: dx c_style_i128_c +// cdb-check: c_style_i128_c : C [Type: enum2$] +// +// cdb-command: dx c_style_i128_d +// cdb-check: c_style_i128_d : D [Type: enum2$] #![feature(rustc_attrs)] #![feature(repr128)] #![feature(arbitrary_enum_discriminant)] @@ -270,6 +294,22 @@ enum ArbitraryDiscr { Def(u32) = 5000_000, } +#[repr(u128)] +pub enum CStyleU128 { + A = 0_u128, + B = 1_u128, + C = u64::MAX as u128 + 1, + D = u128::MAX, +} + +#[repr(i128)] +pub enum CStyleI128 { + A = 0_i128, + B = -1_i128, + C = i128::MIN, + D = i128::MAX, +} + fn main() { let a = Some(CStyleEnum::Low); let b = Option::::None; @@ -313,6 +353,16 @@ fn main() { let arbitrary_discr1 = ArbitraryDiscr::Abc(1234); let arbitrary_discr2 = ArbitraryDiscr::Def(5678); + let c_style_u128_a = CStyleU128::A; + let c_style_u128_b = CStyleU128::B; + let c_style_u128_c = CStyleU128::C; + let c_style_u128_d = CStyleU128::D; + + let c_style_i128_a = CStyleI128::A; + let c_style_i128_b = CStyleI128::B; + let c_style_i128_c = CStyleI128::C; + let c_style_i128_d = CStyleI128::D; + zzz(); // #break } diff --git a/tests/debuginfo/multi-byte-chars.rs b/tests/debuginfo/multi-byte-chars.rs index 8fb066c7185..2ab98d265b8 100644 --- a/tests/debuginfo/multi-byte-chars.rs +++ b/tests/debuginfo/multi-byte-chars.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // This test checks whether debuginfo generation can handle multi-byte UTF-8 diff --git a/tests/debuginfo/multi-cgu.rs b/tests/debuginfo/multi-cgu.rs index 32fd6895877..3bb5269adea 100644 --- a/tests/debuginfo/multi-cgu.rs +++ b/tests/debuginfo/multi-cgu.rs @@ -1,9 +1,6 @@ // This test case makes sure that we get proper break points for binaries // compiled with multiple codegen units. (see #39160) - -//@ min-lldb-version: 310 - //@ compile-flags:-g -Ccodegen-units=2 // === GDB TESTS =============================================================== @@ -24,13 +21,11 @@ // lldb-command:run // lldb-command:v xxx -// lldbg-check:[...] 12345 -// lldbr-check:(u32) xxx = 12345 +// lldb-check:[...] 12345 // lldb-command:continue // lldb-command:v yyy -// lldbg-check:[...] 67890 -// lldbr-check:(u64) yyy = 67890 +// lldb-check:[...] 67890 // lldb-command:continue diff --git a/tests/debuginfo/multiple-functions-equal-var-names.rs b/tests/debuginfo/multiple-functions-equal-var-names.rs index 2d9caf75290..6ae9225d55c 100644 --- a/tests/debuginfo/multiple-functions-equal-var-names.rs +++ b/tests/debuginfo/multiple-functions-equal-var-names.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -23,18 +21,15 @@ // lldb-command:run // lldb-command:v abc -// lldbg-check:[...] 10101 -// lldbr-check:(i32) abc = 10101 +// lldb-check:[...] 10101 // lldb-command:continue // lldb-command:v abc -// lldbg-check:[...] 20202 -// lldbr-check:(i32) abc = 20202 +// lldb-check:[...] 20202 // lldb-command:continue // lldb-command:v abc -// lldbg-check:[...] 30303 -// lldbr-check:(i32) abc = 30303 +// lldb-check:[...] 30303 #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/multiple-functions.rs b/tests/debuginfo/multiple-functions.rs index 5c01a427051..3f7a0ded91b 100644 --- a/tests/debuginfo/multiple-functions.rs +++ b/tests/debuginfo/multiple-functions.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -23,18 +21,15 @@ // lldb-command:run // lldb-command:v a -// lldbg-check:[...] 10101 -// lldbr-check:(i32) a = 10101 +// lldb-check:[...] 10101 // lldb-command:continue // lldb-command:v b -// lldbg-check:[...] 20202 -// lldbr-check:(i32) b = 20202 +// lldb-check:[...] 20202 // lldb-command:continue // lldb-command:v c -// lldbg-check:[...] 30303 -// lldbr-check:(i32) c = 30303 +// lldb-check:[...] 30303 #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/name-shadowing-and-scope-nesting.rs b/tests/debuginfo/name-shadowing-and-scope-nesting.rs index 8813793e59e..d3829b60713 100644 --- a/tests/debuginfo/name-shadowing-and-scope-nesting.rs +++ b/tests/debuginfo/name-shadowing-and-scope-nesting.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -48,51 +46,39 @@ // lldb-command:run // lldb-command:v x -// lldbg-check:[...] false -// lldbr-check:(bool) x = false +// lldb-check:[...] false // lldb-command:v y -// lldbg-check:[...] true -// lldbr-check:(bool) y = true +// lldb-check:[...] true // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 10 -// lldbr-check:(i32) x = 10 +// lldb-check:[...] 10 // lldb-command:v y -// lldbg-check:[...] true -// lldbr-check:(bool) y = true +// lldb-check:[...] true // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 10.5 -// lldbr-check:(f64) x = 10.5 +// lldb-check:[...] 10.5 // lldb-command:v y -// lldbg-check:[...] 20 -// lldbr-check:(i32) y = 20 +// lldb-check:[...] 20 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] true -// lldbr-check:(bool) x = true +// lldb-check:[...] true // lldb-command:v y -// lldbg-check:[...] 2220 -// lldbr-check:(i32) y = 2220 +// lldb-check:[...] 2220 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 203203.5 -// lldbr-check:(f64) x = 203203.5 +// lldb-check:[...] 203203.5 // lldb-command:v y -// lldbg-check:[...] 2220 -// lldbr-check:(i32) y = 2220 +// lldb-check:[...] 2220 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 10.5 -// lldbr-check:(f64) x = 10.5 +// lldb-check:[...] 10.5 // lldb-command:v y -// lldbg-check:[...] 20 -// lldbr-check:(i32) y = 20 +// lldb-check:[...] 20 // lldb-command:continue #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/numeric-types.rs b/tests/debuginfo/numeric-types.rs index 98bc31e8855..9d232578979 100644 --- a/tests/debuginfo/numeric-types.rs +++ b/tests/debuginfo/numeric-types.rs @@ -1,7 +1,6 @@ //@ compile-flags:-g -//@ min-gdb-version: 8.1 -//@ ignore-windows-gnu // emit_debug_gdb_scripts is disabled on Windows +//@ ignore-windows-gnu: #128981 // Tests the visualizations for `NonZero`, `Wrapping` and // `Atomic{Bool,I8,I16,I32,I64,Isize,U8,U16,U32,U64,Usize}` located in `libcore.natvis`. diff --git a/tests/debuginfo/option-like-enum.rs b/tests/debuginfo/option-like-enum.rs index c782796f473..d370796efa9 100644 --- a/tests/debuginfo/option-like-enum.rs +++ b/tests/debuginfo/option-like-enum.rs @@ -1,6 +1,5 @@ -//@ ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 - -//@ min-lldb-version: 310 +//@ min-lldb-version: 1800 +//@ min-gdb-version: 13.0 //@ compile-flags:-g @@ -9,36 +8,28 @@ // gdb-command:run // gdb-command:print some -// gdbg-check:$1 = {RUST$ENCODED$ENUM$0$None = {__0 = 0x12345678}} -// gdbr-check:$1 = core::option::Option<&u32>::Some(0x12345678) +// gdb-check:$1 = core::option::Option<&u32>::Some(0x12345678) // gdb-command:print none -// gdbg-check:$2 = {RUST$ENCODED$ENUM$0$None = {__0 = 0x0}} -// gdbr-check:$2 = core::option::Option<&u32>::None +// gdb-check:$2 = core::option::Option<&u32>::None // gdb-command:print full -// gdbg-check:$3 = {RUST$ENCODED$ENUM$1$Empty = {__0 = 454545, __1 = 0x87654321, __2 = 9988}} -// gdbr-check:$3 = option_like_enum::MoreFields::Full(454545, 0x87654321, 9988) +// gdb-check:$3 = option_like_enum::MoreFields::Full(454545, 0x87654321, 9988) -// gdbg-command:print empty_gdb->discr -// gdbr-command:print empty_gdb.discr -// gdb-check:$4 = (isize *) 0x0 +// gdb-command:print empty_gdb.discr +// gdb-check:$4 = (*mut isize) 0x1 // gdb-command:print droid -// gdbg-check:$5 = {RUST$ENCODED$ENUM$2$Void = {id = 675675, range = 10000001, internals = 0x43218765}} -// gdbr-check:$5 = option_like_enum::NamedFields::Droid{id: 675675, range: 10000001, internals: 0x43218765} +// gdb-check:$5 = option_like_enum::NamedFields::Droid{id: 675675, range: 10000001, internals: 0x43218765} -// gdbg-command:print void_droid_gdb->internals -// gdbr-command:print void_droid_gdb.internals -// gdb-check:$6 = (isize *) 0x0 +// gdb-command:print void_droid_gdb.internals +// gdb-check:$6 = (*mut isize) 0x1 // gdb-command:print nested_non_zero_yep -// gdbg-check:$7 = {RUST$ENCODED$ENUM$1$2$Nope = {__0 = 10.5, __1 = {a = 10, b = 20, c = [...]}}} -// gdbr-check:$7 = option_like_enum::NestedNonZero::Yep(10.5, option_like_enum::NestedNonZeroField {a: 10, b: 20, c: 0x[...] "x[...]"}) +// gdb-check:$7 = option_like_enum::NestedNonZero::Yep(10.5, option_like_enum::NestedNonZeroField {a: 10, b: 20, c: 0x[...]}) // gdb-command:print nested_non_zero_nope -// gdbg-check:$8 = {RUST$ENCODED$ENUM$1$2$Nope = {__0 = [...], __1 = {a = [...], b = [...], c = 0x0}}} -// gdbr-check:$8 = option_like_enum::NestedNonZero::Nope +// gdb-check:$8 = option_like_enum::NestedNonZero::Nope // gdb-command:continue diff --git a/tests/debuginfo/packed-struct-with-destructor.rs b/tests/debuginfo/packed-struct-with-destructor.rs index f9bac844376..f923d36953c 100644 --- a/tests/debuginfo/packed-struct-with-destructor.rs +++ b/tests/debuginfo/packed-struct-with-destructor.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -7,37 +5,29 @@ // gdb-command:run // gdb-command:print packed -// gdbg-check:$1 = {x = 123, y = 234, z = 345} -// gdbr-check:$1 = packed_struct_with_destructor::Packed {x: 123, y: 234, z: 345} +// gdb-check:$1 = packed_struct_with_destructor::Packed {x: 123, y: 234, z: 345} // gdb-command:print packedInPacked -// gdbg-check:$2 = {a = 1111, b = {x = 2222, y = 3333, z = 4444}, c = 5555, d = {x = 6666, y = 7777, z = 8888}} -// gdbr-check:$2 = packed_struct_with_destructor::PackedInPacked {a: 1111, b: packed_struct_with_destructor::Packed {x: 2222, y: 3333, z: 4444}, c: 5555, d: packed_struct_with_destructor::Packed {x: 6666, y: 7777, z: 8888}} +// gdb-check:$2 = packed_struct_with_destructor::PackedInPacked {a: 1111, b: packed_struct_with_destructor::Packed {x: 2222, y: 3333, z: 4444}, c: 5555, d: packed_struct_with_destructor::Packed {x: 6666, y: 7777, z: 8888}} // gdb-command:print packedInUnpacked -// gdbg-check:$3 = {a = -1111, b = {x = -2222, y = -3333, z = -4444}, c = -5555, d = {x = -6666, y = -7777, z = -8888}} -// gdbr-check:$3 = packed_struct_with_destructor::PackedInUnpacked {a: -1111, b: packed_struct_with_destructor::Packed {x: -2222, y: -3333, z: -4444}, c: -5555, d: packed_struct_with_destructor::Packed {x: -6666, y: -7777, z: -8888}} +// gdb-check:$3 = packed_struct_with_destructor::PackedInUnpacked {a: -1111, b: packed_struct_with_destructor::Packed {x: -2222, y: -3333, z: -4444}, c: -5555, d: packed_struct_with_destructor::Packed {x: -6666, y: -7777, z: -8888}} // gdb-command:print unpackedInPacked -// gdbg-check:$4 = {a = 987, b = {x = 876, y = 765, z = 654}, c = {x = 543, y = 432, z = 321}, d = 210} -// gdbr-check:$4 = packed_struct_with_destructor::UnpackedInPacked {a: 987, b: packed_struct_with_destructor::Unpacked {x: 876, y: 765, z: 654}, c: packed_struct_with_destructor::Unpacked {x: 543, y: 432, z: 321}, d: 210} +// gdb-check:$4 = packed_struct_with_destructor::UnpackedInPacked {a: 987, b: packed_struct_with_destructor::Unpacked {x: 876, y: 765, z: 654}, c: packed_struct_with_destructor::Unpacked {x: 543, y: 432, z: 321}, d: 210} // gdb-command:print packedInPackedWithDrop -// gdbg-check:$5 = {a = 11, b = {x = 22, y = 33, z = 44}, c = 55, d = {x = 66, y = 77, z = 88}} -// gdbr-check:$5 = packed_struct_with_destructor::PackedInPackedWithDrop {a: 11, b: packed_struct_with_destructor::Packed {x: 22, y: 33, z: 44}, c: 55, d: packed_struct_with_destructor::Packed {x: 66, y: 77, z: 88}} +// gdb-check:$5 = packed_struct_with_destructor::PackedInPackedWithDrop {a: 11, b: packed_struct_with_destructor::Packed {x: 22, y: 33, z: 44}, c: 55, d: packed_struct_with_destructor::Packed {x: 66, y: 77, z: 88}} // gdb-command:print packedInUnpackedWithDrop -// gdbg-check:$6 = {a = -11, b = {x = -22, y = -33, z = -44}, c = -55, d = {x = -66, y = -77, z = -88}} -// gdbr-check:$6 = packed_struct_with_destructor::PackedInUnpackedWithDrop {a: -11, b: packed_struct_with_destructor::Packed {x: -22, y: -33, z: -44}, c: -55, d: packed_struct_with_destructor::Packed {x: -66, y: -77, z: -88}} +// gdb-check:$6 = packed_struct_with_destructor::PackedInUnpackedWithDrop {a: -11, b: packed_struct_with_destructor::Packed {x: -22, y: -33, z: -44}, c: -55, d: packed_struct_with_destructor::Packed {x: -66, y: -77, z: -88}} // gdb-command:print unpackedInPackedWithDrop -// gdbg-check:$7 = {a = 98, b = {x = 87, y = 76, z = 65}, c = {x = 54, y = 43, z = 32}, d = 21} -// gdbr-check:$7 = packed_struct_with_destructor::UnpackedInPackedWithDrop {a: 98, b: packed_struct_with_destructor::Unpacked {x: 87, y: 76, z: 65}, c: packed_struct_with_destructor::Unpacked {x: 54, y: 43, z: 32}, d: 21} +// gdb-check:$7 = packed_struct_with_destructor::UnpackedInPackedWithDrop {a: 98, b: packed_struct_with_destructor::Unpacked {x: 87, y: 76, z: 65}, c: packed_struct_with_destructor::Unpacked {x: 54, y: 43, z: 32}, d: 21} // gdb-command:print deeplyNested -// gdbg-check:$8 = {a = {a = 1, b = {x = 2, y = 3, z = 4}, c = 5, d = {x = 6, y = 7, z = 8}}, b = {a = 9, b = {x = 10, y = 11, z = 12}, c = {x = 13, y = 14, z = 15}, d = 16}, c = {a = 17, b = {x = 18, y = 19, z = 20}, c = 21, d = {x = 22, y = 23, z = 24}}, d = {a = 25, b = {x = 26, y = 27, z = 28}, c = 29, d = {x = 30, y = 31, z = 32}}, e = {a = 33, b = {x = 34, y = 35, z = 36}, c = {x = 37, y = 38, z = 39}, d = 40}, f = {a = 41, b = {x = 42, y = 43, z = 44}, c = 45, d = {x = 46, y = 47, z = 48}}} -// gdbr-check:$8 = packed_struct_with_destructor::DeeplyNested {a: packed_struct_with_destructor::PackedInPacked {a: 1, b: packed_struct_with_destructor::Packed {x: 2, y: 3, z: 4}, c: 5, d: packed_struct_with_destructor::Packed {x: 6, y: 7, z: 8}}, b: packed_struct_with_destructor::UnpackedInPackedWithDrop {a: 9, b: packed_struct_with_destructor::Unpacked {x: 10, y: 11, z: 12}, c: packed_struct_with_destructor::Unpacked {x: 13, y: 14, z: 15}, d: 16}, c: packed_struct_with_destructor::PackedInUnpacked {a: 17, b: packed_struct_with_destructor::Packed {x: 18, y: 19, z: 20}, c: 21, d: packed_struct_with_destructor::Packed {x: 22, y: 23, z: 24}}, d: packed_struct_with_destructor::PackedInUnpackedWithDrop {a: 25, b: packed_struct_with_destructor::Packed {x: 26, y: 27, z: 28}, c: 29, d: packed_struct_with_destructor::Packed {x: 30, y: 31, z: 32}}, e: packed_struct_with_destructor::UnpackedInPacked {a: 33, b: packed_struct_with_destructor::Unpacked {x: 34, y: 35, z: 36}, c: packed_struct_with_destructor::Unpacked {x: 37, y: 38, z: 39}, d: 40}, f: packed_struct_with_destructor::PackedInPackedWithDrop {a: 41, b: packed_struct_with_destructor::Packed {x: 42, y: 43, z: 44}, c: 45, d: packed_struct_with_destructor::Packed {x: 46, y: 47, z: 48}}} +// gdb-check:$8 = packed_struct_with_destructor::DeeplyNested {a: packed_struct_with_destructor::PackedInPacked {a: 1, b: packed_struct_with_destructor::Packed {x: 2, y: 3, z: 4}, c: 5, d: packed_struct_with_destructor::Packed {x: 6, y: 7, z: 8}}, b: packed_struct_with_destructor::UnpackedInPackedWithDrop {a: 9, b: packed_struct_with_destructor::Unpacked {x: 10, y: 11, z: 12}, c: packed_struct_with_destructor::Unpacked {x: 13, y: 14, z: 15}, d: 16}, c: packed_struct_with_destructor::PackedInUnpacked {a: 17, b: packed_struct_with_destructor::Packed {x: 18, y: 19, z: 20}, c: 21, d: packed_struct_with_destructor::Packed {x: 22, y: 23, z: 24}}, d: packed_struct_with_destructor::PackedInUnpackedWithDrop {a: 25, b: packed_struct_with_destructor::Packed {x: 26, y: 27, z: 28}, c: 29, d: packed_struct_with_destructor::Packed {x: 30, y: 31, z: 32}}, e: packed_struct_with_destructor::UnpackedInPacked {a: 33, b: packed_struct_with_destructor::Unpacked {x: 34, y: 35, z: 36}, c: packed_struct_with_destructor::Unpacked {x: 37, y: 38, z: 39}, d: 40}, f: packed_struct_with_destructor::PackedInPackedWithDrop {a: 41, b: packed_struct_with_destructor::Packed {x: 42, y: 43, z: 44}, c: 45, d: packed_struct_with_destructor::Packed {x: 46, y: 47, z: 48}}} // === LLDB TESTS ================================================================================== @@ -45,36 +35,28 @@ // lldb-command:run // lldb-command:v packed -// lldbg-check:[...] { x = 123 y = 234 z = 345 } -// lldbr-check:(packed_struct_with_destructor::Packed) packed = { x = 123 y = 234 z = 345 } +// lldb-check:[...] { x = 123 y = 234 z = 345 } // lldb-command:v packedInPacked -// lldbg-check:[...] { a = 1111 b = { x = 2222 y = 3333 z = 4444 } c = 5555 d = { x = 6666 y = 7777 z = 8888 } } -// lldbr-check:(packed_struct_with_destructor::PackedInPacked) packedInPacked = { a = 1111 b = { x = 2222 y = 3333 z = 4444 } c = 5555 d = { x = 6666 y = 7777 z = 8888 } } +// lldb-check:[...] { a = 1111 b = { x = 2222 y = 3333 z = 4444 } c = 5555 d = { x = 6666 y = 7777 z = 8888 } } // lldb-command:v packedInUnpacked -// lldbg-check:[...] { a = -1111 b = { x = -2222 y = -3333 z = -4444 } c = -5555 d = { x = -6666 y = -7777 z = -8888 } } -// lldbr-check:(packed_struct_with_destructor::PackedInUnpacked) packedInUnpacked = { a = -1111 b = { x = -2222 y = -3333 z = -4444 } c = -5555 d = { x = -6666 y = -7777 z = -8888 } } +// lldb-check:[...] { a = -1111 b = { x = -2222 y = -3333 z = -4444 } c = -5555 d = { x = -6666 y = -7777 z = -8888 } } // lldb-command:v unpackedInPacked -// lldbg-check:[...] { a = 987 b = { x = 876 y = 765 z = 654 } c = { x = 543 y = 432 z = 321 } d = 210 } -// lldbr-check:(packed_struct_with_destructor::UnpackedInPacked) unpackedInPacked = { a = 987 b = { x = 876 y = 765 z = 654 } c = { x = 543 y = 432 z = 321 } d = 210 } +// lldb-check:[...] { a = 987 b = { x = 876 y = 765 z = 654 } c = { x = 543 y = 432 z = 321 } d = 210 } // lldb-command:v packedInPackedWithDrop -// lldbg-check:[...] { a = 11 b = { x = 22 y = 33 z = 44 } c = 55 d = { x = 66 y = 77 z = 88 } } -// lldbr-check:(packed_struct_with_destructor::PackedInPackedWithDrop) packedInPackedWithDrop = { a = 11 b = { x = 22 y = 33 z = 44 } c = 55 d = { x = 66 y = 77 z = 88 } } +// lldb-check:[...] { a = 11 b = { x = 22 y = 33 z = 44 } c = 55 d = { x = 66 y = 77 z = 88 } } // lldb-command:v packedInUnpackedWithDrop -// lldbg-check:[...] { a = -11 b = { x = -22 y = -33 z = -44 } c = -55 d = { x = -66 y = -77 z = -88 } } -// lldbr-check:(packed_struct_with_destructor::PackedInUnpackedWithDrop) packedInUnpackedWithDrop = { a = -11 b = { x = -22 y = -33 z = -44 } c = -55 d = { x = -66 y = -77 z = -88 } } +// lldb-check:[...] { a = -11 b = { x = -22 y = -33 z = -44 } c = -55 d = { x = -66 y = -77 z = -88 } } // lldb-command:v unpackedInPackedWithDrop -// lldbg-check:[...] { a = 98 b = { x = 87 y = 76 z = 65 } c = { x = 54 y = 43 z = 32 } d = 21 } -// lldbr-check:(packed_struct_with_destructor::UnpackedInPackedWithDrop) unpackedInPackedWithDrop = { a = 98 b = { x = 87 y = 76 z = 65 } c = { x = 54 y = 43 z = 32 } d = 21 } +// lldb-check:[...] { a = 98 b = { x = 87 y = 76 z = 65 } c = { x = 54 y = 43 z = 32 } d = 21 } // lldb-command:v deeplyNested -// lldbg-check:[...] { a = { a = 1 b = { x = 2 y = 3 z = 4 } c = 5 d = { x = 6 y = 7 z = 8 } } b = { a = 9 b = { x = 10 y = 11 z = 12 } c = { x = 13 y = 14 z = 15 } d = 16 } c = { a = 17 b = { x = 18 y = 19 z = 20 } c = 21 d = { x = 22 y = 23 z = 24 } } d = { a = 25 b = { x = 26 y = 27 z = 28 } c = 29 d = { x = 30 y = 31 z = 32 } } e = { a = 33 b = { x = 34 y = 35 z = 36 } c = { x = 37 y = 38 z = 39 } d = 40 } f = { a = 41 b = { x = 42 y = 43 z = 44 } c = 45 d = { x = 46 y = 47 z = 48 } } } -// lldbr-check:(packed_struct_with_destructor::DeeplyNested) deeplyNested = { a = { a = 1 b = { x = 2 y = 3 z = 4 } c = 5 d = { x = 6 y = 7 z = 8 } } b = { a = 9 b = { x = 10 y = 11 z = 12 } c = { x = 13 y = 14 z = 15 } d = 16 } c = { a = 17 b = { x = 18 y = 19 z = 20 } c = 21 d = { x = 22 y = 23 z = 24 } } d = { a = 25 b = { x = 26 y = 27 z = 28 } c = 29 d = { x = 30 y = 31 z = 32 } } e = { a = 33 b = { x = 34 y = 35 z = 36 } c = { x = 37 y = 38 z = 39 } d = 40 } f = { a = 41 b = { x = 42 y = 43 z = 44 } c = 45 d = { x = 46 y = 47 z = 48 } } } +// lldb-check:[...] { a = { a = 1 b = { x = 2 y = 3 z = 4 } c = 5 d = { x = 6 y = 7 z = 8 } } b = { a = 9 b = { x = 10 y = 11 z = 12 } c = { x = 13 y = 14 z = 15 } d = 16 } c = { a = 17 b = { x = 18 y = 19 z = 20 } c = 21 d = { x = 22 y = 23 z = 24 } } d = { a = 25 b = { x = 26 y = 27 z = 28 } c = 29 d = { x = 30 y = 31 z = 32 } } e = { a = 33 b = { x = 34 y = 35 z = 36 } c = { x = 37 y = 38 z = 39 } d = 40 } f = { a = 41 b = { x = 42 y = 43 z = 44 } c = 45 d = { x = 46 y = 47 z = 48 } } } #![allow(unused_variables)] diff --git a/tests/debuginfo/packed-struct.rs b/tests/debuginfo/packed-struct.rs index ea9aa22ba55..2b3652fe861 100644 --- a/tests/debuginfo/packed-struct.rs +++ b/tests/debuginfo/packed-struct.rs @@ -1,6 +1,3 @@ -//@ min-lldb-version: 310 -//@ ignore-gdb-version: 7.11.90 - 7.12.9 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -8,20 +5,16 @@ // gdb-command:run // gdb-command:print packed -// gdbg-check:$1 = {x = 123, y = 234, z = 345} -// gdbr-check:$1 = packed_struct::Packed {x: 123, y: 234, z: 345} +// gdb-check:$1 = packed_struct::Packed {x: 123, y: 234, z: 345} // gdb-command:print packedInPacked -// gdbg-check:$2 = {a = 1111, b = {x = 2222, y = 3333, z = 4444}, c = 5555, d = {x = 6666, y = 7777, z = 8888}} -// gdbr-check:$2 = packed_struct::PackedInPacked {a: 1111, b: packed_struct::Packed {x: 2222, y: 3333, z: 4444}, c: 5555, d: packed_struct::Packed {x: 6666, y: 7777, z: 8888}} +// gdb-check:$2 = packed_struct::PackedInPacked {a: 1111, b: packed_struct::Packed {x: 2222, y: 3333, z: 4444}, c: 5555, d: packed_struct::Packed {x: 6666, y: 7777, z: 8888}} // gdb-command:print packedInUnpacked -// gdbg-check:$3 = {a = -1111, b = {x = -2222, y = -3333, z = -4444}, c = -5555, d = {x = -6666, y = -7777, z = -8888}} -// gdbr-check:$3 = packed_struct::PackedInUnpacked {a: -1111, b: packed_struct::Packed {x: -2222, y: -3333, z: -4444}, c: -5555, d: packed_struct::Packed {x: -6666, y: -7777, z: -8888}} +// gdb-check:$3 = packed_struct::PackedInUnpacked {a: -1111, b: packed_struct::Packed {x: -2222, y: -3333, z: -4444}, c: -5555, d: packed_struct::Packed {x: -6666, y: -7777, z: -8888}} // gdb-command:print unpackedInPacked -// gdbg-check:$4 = {a = 987, b = {x = 876, y = 765, z = 654, w = 543}, c = {x = 432, y = 321, z = 210, w = 109}, d = -98} -// gdbr-check:$4 = packed_struct::UnpackedInPacked {a: 987, b: packed_struct::Unpacked {x: 876, y: 765, z: 654, w: 543}, c: packed_struct::Unpacked {x: 432, y: 321, z: 210, w: 109}, d: -98} +// gdb-check:$4 = packed_struct::UnpackedInPacked {a: 987, b: packed_struct::Unpacked {x: 876, y: 765, z: 654, w: 543}, c: packed_struct::Unpacked {x: 432, y: 321, z: 210, w: 109}, d: -98} // gdb-command:print sizeof(packed) // gdb-check:$5 = 14 @@ -35,28 +28,22 @@ // lldb-command:run // lldb-command:v packed -// lldbg-check:[...] { x = 123 y = 234 z = 345 } -// lldbr-check:(packed_struct::Packed) packed = { x = 123 y = 234 z = 345 } +// lldb-check:[...] { x = 123 y = 234 z = 345 } // lldb-command:v packedInPacked -// lldbg-check:[...] { a = 1111 b = { x = 2222 y = 3333 z = 4444 } c = 5555 d = { x = 6666 y = 7777 z = 8888 } } -// lldbr-check:(packed_struct::PackedInPacked) packedInPacked = { a = 1111 b = { x = 2222 y = 3333 z = 4444 } c = 5555 d = { x = 6666 y = 7777 z = 8888 } } +// lldb-check:[...] { a = 1111 b = { x = 2222 y = 3333 z = 4444 } c = 5555 d = { x = 6666 y = 7777 z = 8888 } } // lldb-command:v packedInUnpacked -// lldbg-check:[...] { a = -1111 b = { x = -2222 y = -3333 z = -4444 } c = -5555 d = { x = -6666 y = -7777 z = -8888 } } -// lldbr-check:(packed_struct::PackedInUnpacked) packedInUnpacked = { a = -1111 b = { x = -2222 y = -3333 z = -4444 } c = -5555 d = { x = -6666 y = -7777 z = -8888 } } +// lldb-check:[...] { a = -1111 b = { x = -2222 y = -3333 z = -4444 } c = -5555 d = { x = -6666 y = -7777 z = -8888 } } // lldb-command:v unpackedInPacked -// lldbg-check:[...] { a = 987 b = { x = 876 y = 765 z = 654 w = 543 } c = { x = 432 y = 321 z = 210 w = 109 } d = -98 } -// lldbr-check:(packed_struct::UnpackedInPacked) unpackedInPacked = { a = 987 b = { x = 876 y = 765 z = 654 w = 543 } c = { x = 432 y = 321 z = 210 w = 109 } d = -98 } +// lldb-check:[...] { a = 987 b = { x = 876 y = 765 z = 654 w = 543 } c = { x = 432 y = 321 z = 210 w = 109 } d = -98 } // lldb-command:expr sizeof(packed) -// lldbg-check:[...] 14 -// lldbr-check:(usize) [...] 14 +// lldb-check:[...] 14 // lldb-command:expr sizeof(packedInPacked) -// lldbg-check:[...] 40 -// lldbr-check:(usize) [...] 40 +// lldb-check:[...] 40 #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/pretty-huge-vec.rs b/tests/debuginfo/pretty-huge-vec.rs index f4b5345b66d..093fbc5b12d 100644 --- a/tests/debuginfo/pretty-huge-vec.rs +++ b/tests/debuginfo/pretty-huge-vec.rs @@ -1,9 +1,6 @@ -//@ ignore-windows failing on win32 bot -//@ ignore-freebsd: gdb package too new +//@ ignore-windows-gnu: #128981 //@ ignore-android: FIXME(#10381) //@ compile-flags:-g -//@ min-gdb-version: 8.1 -//@ min-lldb-version: 310 // === GDB TESTS =================================================================================== diff --git a/tests/debuginfo/pretty-slices.rs b/tests/debuginfo/pretty-slices.rs index 9defa344be0..f1aad836434 100644 --- a/tests/debuginfo/pretty-slices.rs +++ b/tests/debuginfo/pretty-slices.rs @@ -1,16 +1,14 @@ //@ ignore-android: FIXME(#10381) -//@ ignore-windows +//@ ignore-windows-gnu: #128981 //@ compile-flags:-g // gdb-command: run // gdb-command: print slice -// gdbg-check: $1 = struct &[i32](size=3) = {0, 1, 2} -// gdbr-check: $1 = &[i32](size=3) = {0, 1, 2} +// gdb-check: $1 = &[i32](size=3) = {0, 1, 2} // gdb-command: print mut_slice -// gdbg-check: $2 = struct &mut [i32](size=4) = {2, 3, 5, 7} -// gdbr-check: $2 = &mut [i32](size=4) = {2, 3, 5, 7} +// gdb-check: $2 = &mut [i32](size=4) = {2, 3, 5, 7} // gdb-command: print str_slice // gdb-check: $3 = "string slice" diff --git a/tests/debuginfo/pretty-std-collections.rs b/tests/debuginfo/pretty-std-collections.rs index e9c2c4f2a1d..5e133ee718e 100644 --- a/tests/debuginfo/pretty-std-collections.rs +++ b/tests/debuginfo/pretty-std-collections.rs @@ -1,14 +1,7 @@ -//@ ignore-windows failing on win32 bot -//@ ignore-freebsd: gdb package too new //@ ignore-android: FIXME(#10381) +//@ ignore-windows-gnu: #128981 //@ compile-flags:-g -// The pretty printers being tested here require the patch from -// https://sourceware.org/bugzilla/show_bug.cgi?id=21763 -//@ min-gdb-version: 8.1 - -//@ min-lldb-version: 310 - // === GDB TESTS =================================================================================== // gdb-command: run @@ -59,20 +52,16 @@ // lldb-command:run // lldb-command:v vec_deque -// lldbg-check:[...] size=3 { [0] = 5 [1] = 3 [2] = 7 } -// lldbr-check:(alloc::collections::vec_deque::VecDeque) vec_deque = size=3 = { [0] = 5 [1] = 3 [2] = 7 } +// lldb-check:[...] size=3 { [0] = 5 [1] = 3 [2] = 7 } // lldb-command:v vec_deque2 -// lldbg-check:[...] size=7 { [0] = 2 [1] = 3 [2] = 4 [3] = 5 [4] = 6 [5] = 7 [6] = 8 } -// lldbr-check:(alloc::collections::vec_deque::VecDeque) vec_deque2 = size=7 = { [0] = 2 [1] = 3 [2] = 4 [3] = 5 [4] = 6 [5] = 7 [6] = 8 } +// lldb-check:[...] size=7 { [0] = 2 [1] = 3 [2] = 4 [3] = 5 [4] = 6 [5] = 7 [6] = 8 } // lldb-command:v hash_map -// lldbg-check:[...] size=4 { [0] = { 0 = 1 1 = 10 } [1] = { 0 = 2 1 = 20 } [2] = { 0 = 3 1 = 30 } [3] = { 0 = 4 1 = 40 } } -// lldbr-check:(std::collections::hash::map::HashMap) hash_map = size=4 size=4 { [0] = { 0 = 1 1 = 10 } [1] = { 0 = 2 1 = 20 } [2] = { 0 = 3 1 = 30 } [3] = { 0 = 4 1 = 40 } } +// lldb-check:[...] size=4 { [0] = { 0 = 1 1 = 10 } [1] = { 0 = 2 1 = 20 } [2] = { 0 = 3 1 = 30 } [3] = { 0 = 4 1 = 40 } } // lldb-command:v hash_set -// lldbg-check:[...] size=4 { [0] = 1 [1] = 2 [2] = 3 [3] = 4 } -// lldbr-check:(std::collections::hash::set::HashSet) hash_set = size=4 { [0] = 1 [1] = 2 [2] = 3 [3] = 4 } +// lldb-check:[...] size=4 { [0] = 1 [1] = 2 [2] = 3 [3] = 4 } #![allow(unused_variables)] use std::collections::BTreeMap; diff --git a/tests/debuginfo/pretty-std.rs b/tests/debuginfo/pretty-std.rs index 45c6dbf3439..d7c640a5bea 100644 --- a/tests/debuginfo/pretty-std.rs +++ b/tests/debuginfo/pretty-std.rs @@ -1,10 +1,8 @@ // ignore-tidy-linelength -//@ ignore-freebsd: gdb package too new -//@ only-cdb // "Temporarily" ignored on GDB/LLDB due to debuginfo tests being disabled, see PR 47155 +//@ ignore-windows-gnu: #128981 //@ ignore-android: FIXME(#10381) //@ compile-flags:-g -//@ min-gdb-version: 7.7 -//@ min-lldb-version: 310 +//@ min-lldb-version: 1800 //@ min-cdb-version: 10.0.18317.1001 // === GDB TESTS =================================================================================== @@ -12,10 +10,10 @@ // gdb-command: run // gdb-command: print slice -// gdb-check:$1 = &[i32](len: 4) = {0, 1, 2, 3} +// gdb-check:$1 = &[i32](size=4) = {0, 1, 2, 3} // gdb-command: print vec -// gdb-check:$2 = Vec(len: 4, cap: [...]) = {4, 5, 6, 7} +// gdb-check:$2 = Vec(size=4) = {4, 5, 6, 7} // gdb-command: print str_slice // gdb-check:$3 = "IAMA string slice!" @@ -24,37 +22,36 @@ // gdb-check:$4 = "IAMA string!" // gdb-command: print some -// gdb-check:$5 = Some = {8} +// gdb-check:$5 = core::option::Option::Some(8) // gdb-command: print none -// gdbg-check:$6 = None -// gdbr-check:$6 = core::option::Option::None +// gdb-check:$6 = core::option::Option::None // gdb-command: print os_string // gdb-check:$7 = "IAMA OS string 😃" // gdb-command: print some_string -// gdb-check:$8 = Some = {"IAMA optional string!"} +// gdb-check:$8 = core::option::Option::Some("IAMA optional string!") -// gdb-command: set print length 5 +// gdb-command: set print elements 5 // gdb-command: print some_string -// gdb-check:$8 = Some = {"IAMA "...} +// gdb-check:$9 = core::option::Option::Some("IAMA "...) // === LLDB TESTS ================================================================================== // lldb-command:run // lldb-command:v slice -// lldb-check:[...] slice = &[0, 1, 2, 3] +// lldb-check:[...] slice = size=4 { [0] = 0 [1] = 1 [2] = 2 [3] = 3 } // lldb-command:v vec -// lldb-check:[...] vec = vec![4, 5, 6, 7] +// lldb-check:[...] vec = size=4 { [0] = 4 [1] = 5 [2] = 6 [3] = 7 } // lldb-command:v str_slice -// lldb-check:[...] str_slice = "IAMA string slice!" +// lldb-check:[...] str_slice = "IAMA string slice!" { [0] = 'I' [1] = 'A' [2] = 'M' [3] = 'A' [4] = ' ' [5] = 's' [6] = 't' [7] = 'r' [8] = 'i' [9] = 'n' [10] = 'g' [11] = ' ' [12] = 's' [13] = 'l' [14] = 'i' [15] = 'c' [16] = 'e' [17] = '!' } // lldb-command:v string -// lldb-check:[...] string = "IAMA string!" +// lldb-check:[...] string = "IAMA string!" { vec = size=12 { [0] = 'I' [1] = 'A' [2] = 'M' [3] = 'A' [4] = ' ' [5] = 's' [6] = 't' [7] = 'r' [8] = 'i' [9] = 'n' [10] = 'g' [11] = '!' } } // lldb-command:v some // lldb-check:[...] some = Some(8) @@ -63,7 +60,7 @@ // lldb-check:[...] none = None // lldb-command:v os_string -// lldb-check:[...] os_string = "IAMA OS string 😃"[...] +// lldb-check:[...] os_string = "IAMA OS string 😃" { inner = { inner = size=19 { [0] = 'I' [1] = 'A' [2] = 'M' [3] = 'A' [4] = ' ' [5] = 'O' [6] = 'S' [7] = ' ' [8] = 's' [9] = 't' [10] = 'r' [11] = 'i' [12] = 'n' [13] = 'g' [14] = ' ' [15] = '\xf0' [16] = '\x9f' [17] = '\x98' [18] = '\x83' } } } // === CDB TESTS ================================================================================== diff --git a/tests/debuginfo/pretty-uninitialized-vec.rs b/tests/debuginfo/pretty-uninitialized-vec.rs index 225b4a6d534..cea2f26ef58 100644 --- a/tests/debuginfo/pretty-uninitialized-vec.rs +++ b/tests/debuginfo/pretty-uninitialized-vec.rs @@ -1,9 +1,6 @@ -//@ ignore-windows failing on win32 bot -//@ ignore-freebsd: gdb package too new +//@ ignore-windows-gnu: #128981 //@ ignore-android: FIXME(#10381) //@ compile-flags:-g -//@ min-gdb-version: 8.1 -//@ min-lldb-version: 310 // === GDB TESTS =================================================================================== diff --git a/tests/debuginfo/rc_arc.rs b/tests/debuginfo/rc_arc.rs index ca0feb1f465..f636c60702c 100644 --- a/tests/debuginfo/rc_arc.rs +++ b/tests/debuginfo/rc_arc.rs @@ -1,7 +1,6 @@ -//@ ignore-windows-gnu: pretty-printers are not loaded +//@ ignore-windows-gnu: #128981 //@ compile-flags:-g -//@ min-gdb-version: 8.1 //@ min-cdb-version: 10.0.18317.1001 // === GDB TESTS ================================================================================== diff --git a/tests/debuginfo/recursive-struct.rs b/tests/debuginfo/recursive-struct.rs index 1d039527d1a..a97eb295eb4 100644 --- a/tests/debuginfo/recursive-struct.rs +++ b/tests/debuginfo/recursive-struct.rs @@ -1,61 +1,58 @@ //@ ignore-lldb -// Require a gdb that can read DW_TAG_variant_part. -//@ min-gdb-version: 8.2 - //@ compile-flags:-g // gdb-command:run // gdb-command:print stack_unique.value // gdb-check:$1 = 0 -// gdbr-command:print stack_unique.next.val.value +// gdb-command:print stack_unique.next.val.value // gdb-check:$2 = 1 -// gdbr-command:print unique_unique.value +// gdb-command:print unique_unique.value // gdb-check:$3 = 2 -// gdbr-command:print unique_unique.next.val.value +// gdb-command:print unique_unique.next.val.value // gdb-check:$4 = 3 // gdb-command:print vec_unique[0].value // gdb-check:$5 = 6.5 -// gdbr-command:print vec_unique[0].next.val.value +// gdb-command:print vec_unique[0].next.val.value // gdb-check:$6 = 7.5 -// gdbr-command:print borrowed_unique.value +// gdb-command:print borrowed_unique.value // gdb-check:$7 = 8.5 -// gdbr-command:print borrowed_unique.next.val.value +// gdb-command:print borrowed_unique.next.val.value // gdb-check:$8 = 9.5 // LONG CYCLE // gdb-command:print long_cycle1.value // gdb-check:$9 = 20 -// gdbr-command:print long_cycle1.next.value +// gdb-command:print long_cycle1.next.value // gdb-check:$10 = 21 -// gdbr-command:print long_cycle1.next.next.value +// gdb-command:print long_cycle1.next.next.value // gdb-check:$11 = 22 -// gdbr-command:print long_cycle1.next.next.next.value +// gdb-command:print long_cycle1.next.next.next.value // gdb-check:$12 = 23 // gdb-command:print long_cycle2.value // gdb-check:$13 = 24 -// gdbr-command:print long_cycle2.next.value +// gdb-command:print long_cycle2.next.value // gdb-check:$14 = 25 -// gdbr-command:print long_cycle2.next.next.value +// gdb-command:print long_cycle2.next.next.value // gdb-check:$15 = 26 // gdb-command:print long_cycle3.value // gdb-check:$16 = 27 -// gdbr-command:print long_cycle3.next.value +// gdb-command:print long_cycle3.next.value // gdb-check:$17 = 28 // gdb-command:print long_cycle4.value // gdb-check:$18 = 29.5 -// gdbr-command:print long_cycle_w_anon_types.value +// gdb-command:print long_cycle_w_anon_types.value // gdb-check:$19 = 30 -// gdbr-command:print long_cycle_w_anon_types.next.val.value +// gdb-command:print long_cycle_w_anon_types.next.val.value // gdb-check:$20 = 31 // gdb-command:continue diff --git a/tests/debuginfo/reference-debuginfo.rs b/tests/debuginfo/reference-debuginfo.rs index e2fb964ace5..773c3ae4bc3 100644 --- a/tests/debuginfo/reference-debuginfo.rs +++ b/tests/debuginfo/reference-debuginfo.rs @@ -3,7 +3,6 @@ // and leaves codegen to create a ladder of allocations so as `*a == b`. // //@ compile-flags:-g -Zmir-enable-passes=+ReferencePropagation,-ConstDebugInfo -//@ min-lldb-version: 310 // === GDB TESTS =================================================================================== @@ -18,8 +17,7 @@ // gdb-check:$3 = 97 // gdb-command:print *i8_ref -// gdbg-check:$4 = 68 'D' -// gdbr-check:$4 = 68 +// gdb-check:$4 = 68 // gdb-command:print *i16_ref // gdb-check:$5 = -16 @@ -34,8 +32,7 @@ // gdb-check:$8 = 1 // gdb-command:print *u8_ref -// gdbg-check:$9 = 100 'd' -// gdbr-check:$9 = 100 +// gdb-check:$9 = 100 // gdb-command:print *u16_ref // gdb-check:$10 = 16 @@ -63,68 +60,50 @@ // lldb-command:run // lldb-command:v *bool_ref -// lldbg-check:[...] true -// lldbr-check:(bool) *bool_ref = true +// lldb-check:[...] true // lldb-command:v *int_ref -// lldbg-check:[...] -1 -// lldbr-check:(isize) *int_ref = -1 +// lldb-check:[...] -1 -// NOTE: only rust-enabled lldb supports 32bit chars -// lldbr-command:print *char_ref -// lldbr-check:(char) *char_ref = 'a' // lldb-command:v *i8_ref -// lldbg-check:[...] 'D' -// lldbr-check:(i8) *i8_ref = 68 +// lldb-check:[...] 'D' // lldb-command:v *i16_ref -// lldbg-check:[...] -16 -// lldbr-check:(i16) *i16_ref = -16 +// lldb-check:[...] -16 // lldb-command:v *i32_ref -// lldbg-check:[...] -32 -// lldbr-check:(i32) *i32_ref = -32 +// lldb-check:[...] -32 // lldb-command:v *i64_ref -// lldbg-check:[...] -64 -// lldbr-check:(i64) *i64_ref = -64 +// lldb-check:[...] -64 // lldb-command:v *uint_ref -// lldbg-check:[...] 1 -// lldbr-check:(usize) *uint_ref = 1 +// lldb-check:[...] 1 // lldb-command:v *u8_ref -// lldbg-check:[...] 'd' -// lldbr-check:(u8) *u8_ref = 100 +// lldb-check:[...] 'd' // lldb-command:v *u16_ref -// lldbg-check:[...] 16 -// lldbr-check:(u16) *u16_ref = 16 +// lldb-check:[...] 16 // lldb-command:v *u32_ref -// lldbg-check:[...] 32 -// lldbr-check:(u32) *u32_ref = 32 +// lldb-check:[...] 32 // lldb-command:v *u64_ref -// lldbg-check:[...] 64 -// lldbr-check:(u64) *u64_ref = 64 +// lldb-check:[...] 64 // lldb-command:v *f16_ref -// lldbg-check:[...] 1.5 -// lldbr-check:(f16) *f16_ref = 1.5 +// lldb-check:[...] 1.5 // lldb-command:v *f32_ref -// lldbg-check:[...] 2.5 -// lldbr-check:(f32) *f32_ref = 2.5 +// lldb-check:[...] 2.5 // lldb-command:v *f64_ref -// lldbg-check:[...] 3.5 -// lldbr-check:(f64) *f64_ref = 3.5 +// lldb-check:[...] 3.5 // lldb-command:v *f64_double_ref -// lldbg-check:[...] 3.5 -// lldbr-check:(f64) **f64_double_ref = 3.5 +// lldb-check:[...] 3.5 #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/regression-bad-location-list-67992.rs b/tests/debuginfo/regression-bad-location-list-67992.rs index fe410942d51..0ec474b5b5a 100644 --- a/tests/debuginfo/regression-bad-location-list-67992.rs +++ b/tests/debuginfo/regression-bad-location-list-67992.rs @@ -11,8 +11,7 @@ // lldb-command:run // lldb-command:v a -// lldbg-check:(regression_bad_location_list_67992::Foo) [...] -// lldbr-check:(regression_bad_location_list_67992::Foo) a = [...] +// lldb-check:(regression_bad_location_list_67992::Foo) [...] const ARRAY_SIZE: usize = 1024; diff --git a/tests/debuginfo/self-in-default-method.rs b/tests/debuginfo/self-in-default-method.rs index 374951475fc..02fc01d96eb 100644 --- a/tests/debuginfo/self-in-default-method.rs +++ b/tests/debuginfo/self-in-default-method.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -8,8 +6,7 @@ // STACK BY REF // gdb-command:print *self -// gdbg-check:$1 = {x = 100} -// gdbr-check:$1 = self_in_default_method::Struct {x: 100} +// gdb-check:$1 = self_in_default_method::Struct {x: 100} // gdb-command:print arg1 // gdb-check:$2 = -1 // gdb-command:print arg2 @@ -18,8 +15,7 @@ // STACK BY VAL // gdb-command:print self -// gdbg-check:$4 = {x = 100} -// gdbr-check:$4 = self_in_default_method::Struct {x: 100} +// gdb-check:$4 = self_in_default_method::Struct {x: 100} // gdb-command:print arg1 // gdb-check:$5 = -3 // gdb-command:print arg2 @@ -28,8 +24,7 @@ // OWNED BY REF // gdb-command:print *self -// gdbg-check:$7 = {x = 200} -// gdbr-check:$7 = self_in_default_method::Struct {x: 200} +// gdb-check:$7 = self_in_default_method::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$8 = -5 // gdb-command:print arg2 @@ -38,8 +33,7 @@ // OWNED BY VAL // gdb-command:print self -// gdbg-check:$10 = {x = 200} -// gdbr-check:$10 = self_in_default_method::Struct {x: 200} +// gdb-check:$10 = self_in_default_method::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$11 = -7 // gdb-command:print arg2 @@ -48,8 +42,7 @@ // OWNED MOVED // gdb-command:print *self -// gdbg-check:$13 = {x = 200} -// gdbr-check:$13 = self_in_default_method::Struct {x: 200} +// gdb-check:$13 = self_in_default_method::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$14 = -9 // gdb-command:print arg2 @@ -63,62 +56,47 @@ // STACK BY REF // lldb-command:v *self -// lldbg-check:[...] { x = 100 } -// lldbr-check:(self_in_default_method::Struct) *self = Struct { x: 100 } +// lldb-check:[...] { x = 100 } // lldb-command:v arg1 -// lldbg-check:[...] -1 -// lldbr-check:(isize) arg1 = -1 +// lldb-check:[...] -1 // lldb-command:v arg2 -// lldbg-check:[...] -2 -// lldbr-check:(isize) arg2 = -2 +// lldb-check:[...] -2 // lldb-command:continue // STACK BY VAL // lldb-command:v self -// lldbg-check:[...] { x = 100 } -// lldbr-check:(self_in_default_method::Struct) self = Struct { x: 100 } +// lldb-check:[...] { x = 100 } // lldb-command:v arg1 -// lldbg-check:[...] -3 -// lldbr-check:(isize) arg1 = -3 +// lldb-check:[...] -3 // lldb-command:v arg2 -// lldbg-check:[...] -4 -// lldbr-check:(isize) arg2 = -4 +// lldb-check:[...] -4 // lldb-command:continue // OWNED BY REF // lldb-command:v *self -// lldbg-check:[...] { x = 200 } -// lldbr-check:(self_in_default_method::Struct) *self = Struct { x: 200 } +// lldb-check:[...] { x = 200 } // lldb-command:v arg1 -// lldbg-check:[...] -5 -// lldbr-check:(isize) arg1 = -5 +// lldb-check:[...] -5 // lldb-command:v arg2 -// lldbg-check:[...] -6 -// lldbr-check:(isize) arg2 = -6 +// lldb-check:[...] -6 // lldb-command:continue // OWNED BY VAL // lldb-command:v self -// lldbg-check:[...] { x = 200 } -// lldbr-check:(self_in_default_method::Struct) self = Struct { x: 200 } +// lldb-check:[...] { x = 200 } // lldb-command:v arg1 -// lldbg-check:[...] -7 -// lldbr-check:(isize) arg1 = -7 +// lldb-check:[...] -7 // lldb-command:v arg2 -// lldbg-check:[...] -8 -// lldbr-check:(isize) arg2 = -8 +// lldb-check:[...] -8 // lldb-command:continue // OWNED MOVED // lldb-command:v *self -// lldbg-check:[...] { x = 200 } -// lldbr-check:(self_in_default_method::Struct) *self = Struct { x: 200 } +// lldb-check:[...] { x = 200 } // lldb-command:v arg1 -// lldbg-check:[...] -9 -// lldbr-check:(isize) arg1 = -9 +// lldb-check:[...] -9 // lldb-command:v arg2 -// lldbg-check:[...] -10 -// lldbr-check:(isize) arg2 = -10 +// lldb-check:[...] -10 // lldb-command:continue #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/self-in-generic-default-method.rs b/tests/debuginfo/self-in-generic-default-method.rs index 4759ca3ecdc..65018e549ee 100644 --- a/tests/debuginfo/self-in-generic-default-method.rs +++ b/tests/debuginfo/self-in-generic-default-method.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -8,8 +6,7 @@ // STACK BY REF // gdb-command:print *self -// gdbg-check:$1 = {x = 987} -// gdbr-check:$1 = self_in_generic_default_method::Struct {x: 987} +// gdb-check:$1 = self_in_generic_default_method::Struct {x: 987} // gdb-command:print arg1 // gdb-check:$2 = -1 // gdb-command:print arg2 @@ -18,8 +15,7 @@ // STACK BY VAL // gdb-command:print self -// gdbg-check:$4 = {x = 987} -// gdbr-check:$4 = self_in_generic_default_method::Struct {x: 987} +// gdb-check:$4 = self_in_generic_default_method::Struct {x: 987} // gdb-command:print arg1 // gdb-check:$5 = -3 // gdb-command:print arg2 @@ -28,8 +24,7 @@ // OWNED BY REF // gdb-command:print *self -// gdbg-check:$7 = {x = 879} -// gdbr-check:$7 = self_in_generic_default_method::Struct {x: 879} +// gdb-check:$7 = self_in_generic_default_method::Struct {x: 879} // gdb-command:print arg1 // gdb-check:$8 = -5 // gdb-command:print arg2 @@ -38,8 +33,7 @@ // OWNED BY VAL // gdb-command:print self -// gdbg-check:$10 = {x = 879} -// gdbr-check:$10 = self_in_generic_default_method::Struct {x: 879} +// gdb-check:$10 = self_in_generic_default_method::Struct {x: 879} // gdb-command:print arg1 // gdb-check:$11 = -7 // gdb-command:print arg2 @@ -48,8 +42,7 @@ // OWNED MOVED // gdb-command:print *self -// gdbg-check:$13 = {x = 879} -// gdbr-check:$13 = self_in_generic_default_method::Struct {x: 879} +// gdb-check:$13 = self_in_generic_default_method::Struct {x: 879} // gdb-command:print arg1 // gdb-check:$14 = -9 // gdb-command:print arg2 @@ -63,62 +56,47 @@ // STACK BY REF // lldb-command:v *self -// lldbg-check:[...] { x = 987 } -// lldbr-check:(self_in_generic_default_method::Struct) *self = Struct { x: 987 } +// lldb-check:[...] { x = 987 } // lldb-command:v arg1 -// lldbg-check:[...] -1 -// lldbr-check:(isize) arg1 = -1 +// lldb-check:[...] -1 // lldb-command:v arg2 -// lldbg-check:[...] 2 -// lldbr-check:(u16) arg2 = 2 +// lldb-check:[...] 2 // lldb-command:continue // STACK BY VAL // lldb-command:v self -// lldbg-check:[...] { x = 987 } -// lldbr-check:(self_in_generic_default_method::Struct) self = Struct { x: 987 } +// lldb-check:[...] { x = 987 } // lldb-command:v arg1 -// lldbg-check:[...] -3 -// lldbr-check:(isize) arg1 = -3 +// lldb-check:[...] -3 // lldb-command:v arg2 -// lldbg-check:[...] -4 -// lldbr-check:(i16) arg2 = -4 +// lldb-check:[...] -4 // lldb-command:continue // OWNED BY REF // lldb-command:v *self -// lldbg-check:[...] { x = 879 } -// lldbr-check:(self_in_generic_default_method::Struct) *self = Struct { x: 879 } +// lldb-check:[...] { x = 879 } // lldb-command:v arg1 -// lldbg-check:[...] -5 -// lldbr-check:(isize) arg1 = -5 +// lldb-check:[...] -5 // lldb-command:v arg2 -// lldbg-check:[...] -6 -// lldbr-check:(i32) arg2 = -6 +// lldb-check:[...] -6 // lldb-command:continue // OWNED BY VAL // lldb-command:v self -// lldbg-check:[...] { x = 879 } -// lldbr-check:(self_in_generic_default_method::Struct) self = Struct { x: 879 } +// lldb-check:[...] { x = 879 } // lldb-command:v arg1 -// lldbg-check:[...] -7 -// lldbr-check:(isize) arg1 = -7 +// lldb-check:[...] -7 // lldb-command:v arg2 -// lldbg-check:[...] -8 -// lldbr-check:(i64) arg2 = -8 +// lldb-check:[...] -8 // lldb-command:continue // OWNED MOVED // lldb-command:v *self -// lldbg-check:[...] { x = 879 } -// lldbr-check:(self_in_generic_default_method::Struct) *self = Struct { x: 879 } +// lldb-check:[...] { x = 879 } // lldb-command:v arg1 -// lldbg-check:[...] -9 -// lldbr-check:(isize) arg1 = -9 +// lldb-check:[...] -9 // lldb-command:v arg2 -// lldbg-check:[...] -10.5 -// lldbr-check:(f32) arg2 = -10.5 +// lldb-check:[...] -10.5 // lldb-command:continue #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/shadowed-argument.rs b/tests/debuginfo/shadowed-argument.rs index e7bc731336e..3a575b4addf 100644 --- a/tests/debuginfo/shadowed-argument.rs +++ b/tests/debuginfo/shadowed-argument.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -30,27 +28,21 @@ // lldb-command:run // lldb-command:v x -// lldbg-check:[...] false -// lldbr-check:(bool) x = false +// lldb-check:[...] false // lldb-command:v y -// lldbg-check:[...] true -// lldbr-check:(bool) y = true +// lldb-check:[...] true // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 10 -// lldbr-check:(i32) x = 10 +// lldb-check:[...] 10 // lldb-command:v y -// lldbg-check:[...] true -// lldbr-check:(bool) y = true +// lldb-check:[...] true // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 10.5 -// lldbr-check:(f64) x = 10.5 +// lldb-check:[...] 10.5 // lldb-command:v y -// lldbg-check:[...] 20 -// lldbr-check:(i32) y = 20 +// lldb-check:[...] 20 // lldb-command:continue diff --git a/tests/debuginfo/shadowed-variable.rs b/tests/debuginfo/shadowed-variable.rs index 3cc5fe14cb2..752e4c233f1 100644 --- a/tests/debuginfo/shadowed-variable.rs +++ b/tests/debuginfo/shadowed-variable.rs @@ -1,4 +1,3 @@ -//@ min-lldb-version: 310 //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -40,43 +39,33 @@ // lldb-command:run // lldb-command:v x -// lldbg-check:[...] false -// lldbr-check:(bool) x = false +// lldb-check:[...] false // lldb-command:v y -// lldbg-check:[...] true -// lldbr-check:(bool) y = true +// lldb-check:[...] true // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 10 -// lldbr-check:(i32) x = 10 +// lldb-check:[...] 10 // lldb-command:v y -// lldbg-check:[...] true -// lldbr-check:(bool) y = true +// lldb-check:[...] true // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 10.5 -// lldbr-check:(f64) x = 10.5 +// lldb-check:[...] 10.5 // lldb-command:v y -// lldbg-check:[...] 20 -// lldbr-check:(i32) y = 20 +// lldb-check:[...] 20 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 10.5 -// lldbr-check:(f64) x = 10.5 +// lldb-check:[...] 10.5 // lldb-command:v y -// lldbg-check:[...] 20 -// lldbr-check:(i32) y = 20 +// lldb-check:[...] 20 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 11.5 -// lldbr-check:(f64) x = 11.5 +// lldb-check:[...] 11.5 // lldb-command:v y -// lldbg-check:[...] 20 -// lldbr-check:(i32) y = 20 +// lldb-check:[...] 20 // lldb-command:continue #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/should-fail.rs b/tests/debuginfo/should-fail.rs index 0f153394a44..bc9b83fc242 100644 --- a/tests/debuginfo/should-fail.rs +++ b/tests/debuginfo/should-fail.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - // == Test [gdb|lldb]-[command|check] are parsed correctly === //@ should-fail //@ needs-run-enabled diff --git a/tests/debuginfo/simd.rs b/tests/debuginfo/simd.rs index a5dd2e61a8d..e4fe262235b 100644 --- a/tests/debuginfo/simd.rs +++ b/tests/debuginfo/simd.rs @@ -9,46 +9,28 @@ //@ compile-flags:-g // gdb-command:run -// gdbg-command:print/d vi8x16 -// gdbr-command:print vi8x16 -// gdbg-check:$1 = {__0 = 0, __1 = 1, __2 = 2, __3 = 3, __4 = 4, __5 = 5, __6 = 6, __7 = 7, __8 = 8, __9 = 9, __10 = 10, __11 = 11, __12 = 12, __13 = 13, __14 = 14, __15 = 15} -// gdbr-check:$1 = simd::i8x16 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) -// gdbg-command:print/d vi16x8 -// gdbr-command:print vi16x8 -// gdbg-check:$2 = {__0 = 16, __1 = 17, __2 = 18, __3 = 19, __4 = 20, __5 = 21, __6 = 22, __7 = 23} -// gdbr-check:$2 = simd::i16x8 (16, 17, 18, 19, 20, 21, 22, 23) -// gdbg-command:print/d vi32x4 -// gdbr-command:print vi32x4 -// gdbg-check:$3 = {__0 = 24, __1 = 25, __2 = 26, __3 = 27} -// gdbr-check:$3 = simd::i32x4 (24, 25, 26, 27) -// gdbg-command:print/d vi64x2 -// gdbr-command:print vi64x2 -// gdbg-check:$4 = {__0 = 28, __1 = 29} -// gdbr-check:$4 = simd::i64x2 (28, 29) +// gdb-command:print vi8x16 +// gdb-check:$1 = simd::i8x16 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) +// gdb-command:print vi16x8 +// gdb-check:$2 = simd::i16x8 (16, 17, 18, 19, 20, 21, 22, 23) +// gdb-command:print vi32x4 +// gdb-check:$3 = simd::i32x4 (24, 25, 26, 27) +// gdb-command:print vi64x2 +// gdb-check:$4 = simd::i64x2 (28, 29) -// gdbg-command:print/d vu8x16 -// gdbr-command:print vu8x16 -// gdbg-check:$5 = {__0 = 30, __1 = 31, __2 = 32, __3 = 33, __4 = 34, __5 = 35, __6 = 36, __7 = 37, __8 = 38, __9 = 39, __10 = 40, __11 = 41, __12 = 42, __13 = 43, __14 = 44, __15 = 45} -// gdbr-check:$5 = simd::u8x16 (30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45) -// gdbg-command:print/d vu16x8 -// gdbr-command:print vu16x8 -// gdbg-check:$6 = {__0 = 46, __1 = 47, __2 = 48, __3 = 49, __4 = 50, __5 = 51, __6 = 52, __7 = 53} -// gdbr-check:$6 = simd::u16x8 (46, 47, 48, 49, 50, 51, 52, 53) -// gdbg-command:print/d vu32x4 -// gdbr-command:print vu32x4 -// gdbg-check:$7 = {__0 = 54, __1 = 55, __2 = 56, __3 = 57} -// gdbr-check:$7 = simd::u32x4 (54, 55, 56, 57) -// gdbg-command:print/d vu64x2 -// gdbr-command:print vu64x2 -// gdbg-check:$8 = {__0 = 58, __1 = 59} -// gdbr-check:$8 = simd::u64x2 (58, 59) +// gdb-command:print vu8x16 +// gdb-check:$5 = simd::u8x16 (30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45) +// gdb-command:print vu16x8 +// gdb-check:$6 = simd::u16x8 (46, 47, 48, 49, 50, 51, 52, 53) +// gdb-command:print vu32x4 +// gdb-check:$7 = simd::u32x4 (54, 55, 56, 57) +// gdb-command:print vu64x2 +// gdb-check:$8 = simd::u64x2 (58, 59) // gdb-command:print vf32x4 -// gdbg-check:$9 = {__0 = 60.5, __1 = 61.5, __2 = 62.5, __3 = 63.5} -// gdbr-check:$9 = simd::f32x4 (60.5, 61.5, 62.5, 63.5) +// gdb-check:$9 = simd::f32x4 (60.5, 61.5, 62.5, 63.5) // gdb-command:print vf64x2 -// gdbg-check:$10 = {__0 = 64.5, __1 = 65.5} -// gdbr-check:$10 = simd::f64x2 (64.5, 65.5) +// gdb-check:$10 = simd::f64x2 (64.5, 65.5) // gdb-command:continue diff --git a/tests/debuginfo/simple-lexical-scope.rs b/tests/debuginfo/simple-lexical-scope.rs index 4156e68f8b1..6008489bd65 100644 --- a/tests/debuginfo/simple-lexical-scope.rs +++ b/tests/debuginfo/simple-lexical-scope.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -40,38 +38,31 @@ // lldb-command:run // lldb-command:v x -// lldbg-check:[...] false -// lldbr-check:(bool) x = false +// lldb-check:[...] false // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] false -// lldbr-check:(bool) x = false +// lldb-check:[...] false // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 10 -// lldbr-check:(i32) x = 10 +// lldb-check:[...] 10 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 10 -// lldbr-check:(i32) x = 10 +// lldb-check:[...] 10 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 10.5 -// lldbr-check:(f64) x = 10.5 +// lldb-check:[...] 10.5 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] 10 -// lldbr-check:(i32) x = 10 +// lldb-check:[...] 10 // lldb-command:continue // lldb-command:v x -// lldbg-check:[...] false -// lldbr-check:(bool) x = false +// lldb-check:[...] false // lldb-command:continue diff --git a/tests/debuginfo/simple-struct.rs b/tests/debuginfo/simple-struct.rs index 968a5c63e89..bb6b2b79810 100644 --- a/tests/debuginfo/simple-struct.rs +++ b/tests/debuginfo/simple-struct.rs @@ -1,95 +1,62 @@ -//@ min-lldb-version: 310 -//@ ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 - //@ compile-flags: -g -Zmir-enable-passes=-CheckAlignment // === GDB TESTS =================================================================================== -// gdbg-command:print 'simple_struct::NO_PADDING_16' -// gdbr-command:print simple_struct::NO_PADDING_16 -// gdbg-check:$1 = {x = 1000, y = -1001} -// gdbr-check:$1 = simple_struct::NoPadding16 {x: 1000, y: -1001} +// gdb-command:print simple_struct::NO_PADDING_16 +// gdb-check:$1 = simple_struct::NoPadding16 {x: 1000, y: -1001} -// gdbg-command:print 'simple_struct::NO_PADDING_32' -// gdbr-command:print simple_struct::NO_PADDING_32 -// gdbg-check:$2 = {x = 1, y = 2, z = 3} -// gdbr-check:$2 = simple_struct::NoPadding32 {x: 1, y: 2, z: 3} +// gdb-command:print simple_struct::NO_PADDING_32 +// gdb-check:$2 = simple_struct::NoPadding32 {x: 1, y: 2, z: 3} -// gdbg-command:print 'simple_struct::NO_PADDING_64' -// gdbr-command:print simple_struct::NO_PADDING_64 -// gdbg-check:$3 = {x = 4, y = 5, z = 6} -// gdbr-check:$3 = simple_struct::NoPadding64 {x: 4, y: 5, z: 6} +// gdb-command:print simple_struct::NO_PADDING_64 +// gdb-check:$3 = simple_struct::NoPadding64 {x: 4, y: 5, z: 6} -// gdbg-command:print 'simple_struct::NO_PADDING_163264' -// gdbr-command:print simple_struct::NO_PADDING_163264 -// gdbg-check:$4 = {a = 7, b = 8, c = 9, d = 10} -// gdbr-check:$4 = simple_struct::NoPadding163264 {a: 7, b: 8, c: 9, d: 10} +// gdb-command:print simple_struct::NO_PADDING_163264 +// gdb-check:$4 = simple_struct::NoPadding163264 {a: 7, b: 8, c: 9, d: 10} -// gdbg-command:print 'simple_struct::INTERNAL_PADDING' -// gdbr-command:print simple_struct::INTERNAL_PADDING -// gdbg-check:$5 = {x = 11, y = 12} -// gdbr-check:$5 = simple_struct::InternalPadding {x: 11, y: 12} +// gdb-command:print simple_struct::INTERNAL_PADDING +// gdb-check:$5 = simple_struct::InternalPadding {x: 11, y: 12} -// gdbg-command:print 'simple_struct::PADDING_AT_END' -// gdbr-command:print simple_struct::PADDING_AT_END -// gdbg-check:$6 = {x = 13, y = 14} -// gdbr-check:$6 = simple_struct::PaddingAtEnd {x: 13, y: 14} +// gdb-command:print simple_struct::PADDING_AT_END +// gdb-check:$6 = simple_struct::PaddingAtEnd {x: 13, y: 14} // gdb-command:run // gdb-command:print no_padding16 -// gdbg-check:$7 = {x = 10000, y = -10001} -// gdbr-check:$7 = simple_struct::NoPadding16 {x: 10000, y: -10001} +// gdb-check:$7 = simple_struct::NoPadding16 {x: 10000, y: -10001} // gdb-command:print no_padding32 -// gdbg-check:$8 = {x = -10002, y = -10003.5, z = 10004} -// gdbr-check:$8 = simple_struct::NoPadding32 {x: -10002, y: -10003.5, z: 10004} +// gdb-check:$8 = simple_struct::NoPadding32 {x: -10002, y: -10003.5, z: 10004} // gdb-command:print no_padding64 -// gdbg-check:$9 = {x = -10005.5, y = 10006, z = 10007} -// gdbr-check:$9 = simple_struct::NoPadding64 {x: -10005.5, y: 10006, z: 10007} +// gdb-check:$9 = simple_struct::NoPadding64 {x: -10005.5, y: 10006, z: 10007} // gdb-command:print no_padding163264 -// gdbg-check:$10 = {a = -10008, b = 10009, c = 10010, d = 10011} -// gdbr-check:$10 = simple_struct::NoPadding163264 {a: -10008, b: 10009, c: 10010, d: 10011} +// gdb-check:$10 = simple_struct::NoPadding163264 {a: -10008, b: 10009, c: 10010, d: 10011} // gdb-command:print internal_padding -// gdbg-check:$11 = {x = 10012, y = -10013} -// gdbr-check:$11 = simple_struct::InternalPadding {x: 10012, y: -10013} +// gdb-check:$11 = simple_struct::InternalPadding {x: 10012, y: -10013} // gdb-command:print padding_at_end -// gdbg-check:$12 = {x = -10014, y = 10015} -// gdbr-check:$12 = simple_struct::PaddingAtEnd {x: -10014, y: 10015} +// gdb-check:$12 = simple_struct::PaddingAtEnd {x: -10014, y: 10015} -// gdbg-command:print 'simple_struct::NO_PADDING_16' -// gdbr-command:print simple_struct::NO_PADDING_16 -// gdbg-check:$13 = {x = 100, y = -101} -// gdbr-check:$13 = simple_struct::NoPadding16 {x: 100, y: -101} +// gdb-command:print simple_struct::NO_PADDING_16 +// gdb-check:$13 = simple_struct::NoPadding16 {x: 100, y: -101} -// gdbg-command:print 'simple_struct::NO_PADDING_32' -// gdbr-command:print simple_struct::NO_PADDING_32 -// gdbg-check:$14 = {x = -15, y = -16, z = 17} -// gdbr-check:$14 = simple_struct::NoPadding32 {x: -15, y: -16, z: 17} +// gdb-command:print simple_struct::NO_PADDING_32 +// gdb-check:$14 = simple_struct::NoPadding32 {x: -15, y: -16, z: 17} -// gdbg-command:print 'simple_struct::NO_PADDING_64' -// gdbr-command:print simple_struct::NO_PADDING_64 -// gdbg-check:$15 = {x = -18, y = 19, z = 20} -// gdbr-check:$15 = simple_struct::NoPadding64 {x: -18, y: 19, z: 20} +// gdb-command:print simple_struct::NO_PADDING_64 +// gdb-check:$15 = simple_struct::NoPadding64 {x: -18, y: 19, z: 20} -// gdbg-command:print 'simple_struct::NO_PADDING_163264' -// gdbr-command:print simple_struct::NO_PADDING_163264 -// gdbg-check:$16 = {a = -21, b = 22, c = 23, d = 24} -// gdbr-check:$16 = simple_struct::NoPadding163264 {a: -21, b: 22, c: 23, d: 24} +// gdb-command:print simple_struct::NO_PADDING_163264 +// gdb-check:$16 = simple_struct::NoPadding163264 {a: -21, b: 22, c: 23, d: 24} -// gdbg-command:print 'simple_struct::INTERNAL_PADDING' -// gdbr-command:print simple_struct::INTERNAL_PADDING -// gdbg-check:$17 = {x = 25, y = -26} -// gdbr-check:$17 = simple_struct::InternalPadding {x: 25, y: -26} +// gdb-command:print simple_struct::INTERNAL_PADDING +// gdb-check:$17 = simple_struct::InternalPadding {x: 25, y: -26} -// gdbg-command:print 'simple_struct::PADDING_AT_END' -// gdbr-command:print simple_struct::PADDING_AT_END -// gdbg-check:$18 = {x = -27, y = 28} -// gdbr-check:$18 = simple_struct::PaddingAtEnd {x: -27, y: 28} +// gdb-command:print simple_struct::PADDING_AT_END +// gdb-check:$18 = simple_struct::PaddingAtEnd {x: -27, y: 28} // gdb-command:continue @@ -98,28 +65,22 @@ // lldb-command:run // lldb-command:v no_padding16 -// lldbg-check:[...] { x = 10000 y = -10001 } -// lldbr-check:(simple_struct::NoPadding16) no_padding16 = { x = 10000 y = -10001 } +// lldb-check:[...] { x = 10000 y = -10001 } // lldb-command:v no_padding32 -// lldbg-check:[...] { x = -10002 y = -10003.5 z = 10004 } -// lldbr-check:(simple_struct::NoPadding32) no_padding32 = { x = -10002 y = -10003.5 z = 10004 } +// lldb-check:[...] { x = -10002 y = -10003.5 z = 10004 } // lldb-command:v no_padding64 -// lldbg-check:[...] { x = -10005.5 y = 10006 z = 10007 } -// lldbr-check:(simple_struct::NoPadding64) no_padding64 = { x = -10005.5 y = 10006 z = 10007 } +// lldb-check:[...] { x = -10005.5 y = 10006 z = 10007 } // lldb-command:v no_padding163264 -// lldbg-check:[...] { a = -10008 b = 10009 c = 10010 d = 10011 } -// lldbr-check:(simple_struct::NoPadding163264) no_padding163264 = { a = -10008 b = 10009 c = 10010 d = 10011 } +// lldb-check:[...] { a = -10008 b = 10009 c = 10010 d = 10011 } // lldb-command:v internal_padding -// lldbg-check:[...] { x = 10012 y = -10013 } -// lldbr-check:(simple_struct::InternalPadding) internal_padding = { x = 10012 y = -10013 } +// lldb-check:[...] { x = 10012 y = -10013 } // lldb-command:v padding_at_end -// lldbg-check:[...] { x = -10014 y = 10015 } -// lldbr-check:(simple_struct::PaddingAtEnd) padding_at_end = { x = -10014 y = 10015 } +// lldb-check:[...] { x = -10014 y = 10015 } #![allow(unused_variables)] #![allow(dead_code)] diff --git a/tests/debuginfo/simple-tuple.rs b/tests/debuginfo/simple-tuple.rs index 86003105f36..82467ef3bcf 100644 --- a/tests/debuginfo/simple-tuple.rs +++ b/tests/debuginfo/simple-tuple.rs @@ -1,98 +1,59 @@ -//@ min-lldb-version: 310 -//@ ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 - //@ compile-flags:-g // === GDB TESTS =================================================================================== -// gdbg-command:print/d 'simple_tuple::NO_PADDING_8' -// gdbr-command:print simple_tuple::NO_PADDING_8 -// gdbg-check:$1 = {__0 = -50, __1 = 50} -// gdbr-check:$1 = (-50, 50) -// gdbg-command:print 'simple_tuple::NO_PADDING_16' -// gdbr-command:print simple_tuple::NO_PADDING_16 -// gdbg-check:$2 = {__0 = -1, __1 = 2, __2 = 3} -// gdbr-check:$2 = (-1, 2, 3) -// gdbg-command:print 'simple_tuple::NO_PADDING_32' -// gdbr-command:print simple_tuple::NO_PADDING_32 -// gdbg-check:$3 = {__0 = 4, __1 = 5, __2 = 6} -// gdbr-check:$3 = (4, 5, 6) -// gdbg-command:print 'simple_tuple::NO_PADDING_64' -// gdbr-command:print simple_tuple::NO_PADDING_64 -// gdbg-check:$4 = {__0 = 7, __1 = 8, __2 = 9} -// gdbr-check:$4 = (7, 8, 9) +// gdb-command:print simple_tuple::NO_PADDING_8 +// gdb-check:$1 = (-50, 50) +// gdb-command:print simple_tuple::NO_PADDING_16 +// gdb-check:$2 = (-1, 2, 3) +// gdb-command:print simple_tuple::NO_PADDING_32 +// gdb-check:$3 = (4, 5, 6) +// gdb-command:print simple_tuple::NO_PADDING_64 +// gdb-check:$4 = (7, 8, 9) -// gdbg-command:print 'simple_tuple::INTERNAL_PADDING_1' -// gdbr-command:print simple_tuple::INTERNAL_PADDING_1 -// gdbg-check:$5 = {__0 = 10, __1 = 11} -// gdbr-check:$5 = (10, 11) -// gdbg-command:print 'simple_tuple::INTERNAL_PADDING_2' -// gdbr-command:print simple_tuple::INTERNAL_PADDING_2 -// gdbg-check:$6 = {__0 = 12, __1 = 13, __2 = 14, __3 = 15} -// gdbr-check:$6 = (12, 13, 14, 15) +// gdb-command:print simple_tuple::INTERNAL_PADDING_1 +// gdb-check:$5 = (10, 11) +// gdb-command:print simple_tuple::INTERNAL_PADDING_2 +// gdb-check:$6 = (12, 13, 14, 15) -// gdbg-command:print 'simple_tuple::PADDING_AT_END' -// gdbr-command:print simple_tuple::PADDING_AT_END -// gdbg-check:$7 = {__0 = 16, __1 = 17} -// gdbr-check:$7 = (16, 17) +// gdb-command:print simple_tuple::PADDING_AT_END +// gdb-check:$7 = (16, 17) // gdb-command:run -// gdbg-command:print/d noPadding8 -// gdbr-command:print noPadding8 -// gdbg-check:$8 = {__0 = -100, __1 = 100} -// gdbr-check:$8 = (-100, 100) +// gdb-command:print noPadding8 +// gdb-check:$8 = (-100, 100) // gdb-command:print noPadding16 -// gdbg-check:$9 = {__0 = 0, __1 = 1, __2 = 2} -// gdbr-check:$9 = (0, 1, 2) +// gdb-check:$9 = (0, 1, 2) // gdb-command:print noPadding32 -// gdbg-check:$10 = {__0 = 3, __1 = 4.5, __2 = 5} -// gdbr-check:$10 = (3, 4.5, 5) +// gdb-check:$10 = (3, 4.5, 5) // gdb-command:print noPadding64 -// gdbg-check:$11 = {__0 = 6, __1 = 7.5, __2 = 8} -// gdbr-check:$11 = (6, 7.5, 8) +// gdb-check:$11 = (6, 7.5, 8) // gdb-command:print internalPadding1 -// gdbg-check:$12 = {__0 = 9, __1 = 10} -// gdbr-check:$12 = (9, 10) +// gdb-check:$12 = (9, 10) // gdb-command:print internalPadding2 -// gdbg-check:$13 = {__0 = 11, __1 = 12, __2 = 13, __3 = 14} -// gdbr-check:$13 = (11, 12, 13, 14) +// gdb-check:$13 = (11, 12, 13, 14) // gdb-command:print paddingAtEnd -// gdbg-check:$14 = {__0 = 15, __1 = 16} -// gdbr-check:$14 = (15, 16) +// gdb-check:$14 = (15, 16) -// gdbg-command:print/d 'simple_tuple::NO_PADDING_8' -// gdbr-command:print simple_tuple::NO_PADDING_8 -// gdbg-check:$15 = {__0 = -127, __1 = 127} -// gdbr-check:$15 = (-127, 127) -// gdbg-command:print 'simple_tuple::NO_PADDING_16' -// gdbr-command:print simple_tuple::NO_PADDING_16 -// gdbg-check:$16 = {__0 = -10, __1 = 10, __2 = 9} -// gdbr-check:$16 = (-10, 10, 9) -// gdbg-command:print 'simple_tuple::NO_PADDING_32' -// gdbr-command:print simple_tuple::NO_PADDING_32 -// gdbg-check:$17 = {__0 = 14, __1 = 15, __2 = 16} -// gdbr-check:$17 = (14, 15, 16) -// gdbg-command:print 'simple_tuple::NO_PADDING_64' -// gdbr-command:print simple_tuple::NO_PADDING_64 -// gdbg-check:$18 = {__0 = 17, __1 = 18, __2 = 19} -// gdbr-check:$18 = (17, 18, 19) +// gdb-command:print simple_tuple::NO_PADDING_8 +// gdb-check:$15 = (-127, 127) +// gdb-command:print simple_tuple::NO_PADDING_16 +// gdb-check:$16 = (-10, 10, 9) +// gdb-command:print simple_tuple::NO_PADDING_32 +// gdb-check:$17 = (14, 15, 16) +// gdb-command:print simple_tuple::NO_PADDING_64 +// gdb-check:$18 = (17, 18, 19) -// gdbg-command:print 'simple_tuple::INTERNAL_PADDING_1' -// gdbr-command:print simple_tuple::INTERNAL_PADDING_1 -// gdbg-check:$19 = {__0 = 110, __1 = 111} -// gdbr-check:$19 = (110, 111) -// gdbg-command:print 'simple_tuple::INTERNAL_PADDING_2' -// gdbr-command:print simple_tuple::INTERNAL_PADDING_2 -// gdbg-check:$20 = {__0 = 112, __1 = 113, __2 = 114, __3 = 115} -// gdbr-check:$20 = (112, 113, 114, 115) +// gdb-command:print simple_tuple::INTERNAL_PADDING_1 +// gdb-check:$19 = (110, 111) +// gdb-command:print simple_tuple::INTERNAL_PADDING_2 +// gdb-check:$20 = (112, 113, 114, 115) -// gdbg-command:print 'simple_tuple::PADDING_AT_END' -// gdbr-command:print simple_tuple::PADDING_AT_END -// gdbg-check:$21 = {__0 = 116, __1 = 117} -// gdbr-check:$21 = (116, 117) +// gdb-command:print simple_tuple::PADDING_AT_END +// gdb-check:$21 = (116, 117) // === LLDB TESTS ================================================================================== @@ -100,28 +61,21 @@ // lldb-command:run // lldb-command:v/d noPadding8 -// lldbg-check:[...] { 0 = -100 1 = 100 } -// lldbr-check:((i8, u8)) noPadding8 = { 0 = -100 1 = 100 } +// lldb-check:[...] { 0 = -100 1 = 100 } // lldb-command:v noPadding16 -// lldbg-check:[...] { 0 = 0 1 = 1 2 = 2 } -// lldbr-check:((i16, i16, u16)) noPadding16 = { 0 = 0 1 = 1 2 = 2 } +// lldb-check:[...] { 0 = 0 1 = 1 2 = 2 } // lldb-command:v noPadding32 -// lldbg-check:[...] { 0 = 3 1 = 4.5 2 = 5 } -// lldbr-check:((i32, f32, u32)) noPadding32 = { 0 = 3 1 = 4.5 2 = 5 } +// lldb-check:[...] { 0 = 3 1 = 4.5 2 = 5 } // lldb-command:v noPadding64 -// lldbg-check:[...] { 0 = 6 1 = 7.5 2 = 8 } -// lldbr-check:((i64, f64, u64)) noPadding64 = { 0 = 6 1 = 7.5 2 = 8 } +// lldb-check:[...] { 0 = 6 1 = 7.5 2 = 8 } // lldb-command:v internalPadding1 -// lldbg-check:[...] { 0 = 9 1 = 10 } -// lldbr-check:((i16, i32)) internalPadding1 = { 0 = 9 1 = 10 } +// lldb-check:[...] { 0 = 9 1 = 10 } // lldb-command:v internalPadding2 -// lldbg-check:[...] { 0 = 11 1 = 12 2 = 13 3 = 14 } -// lldbr-check:((i16, i32, u32, u64)) internalPadding2 = { 0 = 11 1 = 12 2 = 13 3 = 14 } +// lldb-check:[...] { 0 = 11 1 = 12 2 = 13 3 = 14 } // lldb-command:v paddingAtEnd -// lldbg-check:[...] { 0 = 15 1 = 16 } -// lldbr-check:((i32, i16)) paddingAtEnd = { 0 = 15 1 = 16 } +// lldb-check:[...] { 0 = 15 1 = 16 } // === CDB TESTS ================================================================================== diff --git a/tests/debuginfo/static-method-on-struct-and-enum.rs b/tests/debuginfo/static-method-on-struct-and-enum.rs index b4ec4543572..b487512a52f 100644 --- a/tests/debuginfo/static-method-on-struct-and-enum.rs +++ b/tests/debuginfo/static-method-on-struct-and-enum.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -29,23 +27,18 @@ // STRUCT // lldb-command:v arg1 -// lldbg-check:[...] 1 -// lldbr-check:(isize) arg1 = 1 +// lldb-check:[...] 1 // lldb-command:v arg2 -// lldbg-check:[...] 2 -// lldbr-check:(isize) arg2 = 2 +// lldb-check:[...] 2 // lldb-command:continue // ENUM // lldb-command:v arg1 -// lldbg-check:[...] -3 -// lldbr-check:(isize) arg1 = -3 +// lldb-check:[...] -3 // lldb-command:v arg2 -// lldbg-check:[...] 4.5 -// lldbr-check:(f64) arg2 = 4.5 +// lldb-check:[...] 4.5 // lldb-command:v arg3 -// lldbg-check:[...] 5 -// lldbr-check:(usize) arg3 = 5 +// lldb-check:[...] 5 // lldb-command:continue #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/strings-and-strs.rs b/tests/debuginfo/strings-and-strs.rs index 2d29ac12bd8..b7ee3312d13 100644 --- a/tests/debuginfo/strings-and-strs.rs +++ b/tests/debuginfo/strings-and-strs.rs @@ -7,37 +7,37 @@ // gdb-command:run // gdb-command:print plain_string -// gdbr-check:$1 = alloc::string::String {vec: alloc::vec::Vec {buf: alloc::raw_vec::RawVec {inner: alloc::raw_vec::RawVecInner {ptr: core::ptr::unique::Unique {pointer: core::ptr::non_null::NonNull {pointer: 0x[...]}, _marker: core::marker::PhantomData}, cap: alloc::raw_vec::Cap (5), alloc: alloc::alloc::Global}, _marker: core::marker::PhantomData}, len: 5}} +// gdb-check:$1 = alloc::string::String {vec: alloc::vec::Vec {buf: alloc::raw_vec::RawVec {inner: alloc::raw_vec::RawVecInner {ptr: core::ptr::unique::Unique {pointer: core::ptr::non_null::NonNull {pointer: 0x[...]}, _marker: core::marker::PhantomData}, cap: alloc::raw_vec::Cap (5), alloc: alloc::alloc::Global}, _marker: core::marker::PhantomData}, len: 5}} // gdb-command:print plain_str -// gdbr-check:$2 = "Hello" +// gdb-check:$2 = "Hello" // gdb-command:print str_in_struct -// gdbr-check:$3 = strings_and_strs::Foo {inner: "Hello"} +// gdb-check:$3 = strings_and_strs::Foo {inner: "Hello"} // gdb-command:print str_in_tuple -// gdbr-check:$4 = ("Hello", "World") +// gdb-check:$4 = ("Hello", "World") // gdb-command:print str_in_rc -// gdbr-check:$5 = alloc::rc::Rc<&str, alloc::alloc::Global> {ptr: core::ptr::non_null::NonNull> {pointer: 0x[...]}, phantom: core::marker::PhantomData>, alloc: alloc::alloc::Global} +// gdb-check:$5 = alloc::rc::Rc<&str, alloc::alloc::Global> {ptr: core::ptr::non_null::NonNull> {pointer: 0x[...]}, phantom: core::marker::PhantomData>, alloc: alloc::alloc::Global} // === LLDB TESTS ================================================================================== // lldb-command:run // lldb-command:v plain_string -// lldbg-check:(alloc::string::String) plain_string = "Hello" { vec = size=5 { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } } +// lldb-check:(alloc::string::String) plain_string = "Hello" { vec = size=5 { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } } // lldb-command:v plain_str -// lldbg-check:(&str) plain_str = "Hello" { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } +// lldb-check:(&str) plain_str = "Hello" { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } // lldb-command:v str_in_struct -// lldbg-check:((&str, &str)) str_in_tuple = { 0 = "Hello" { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } 1 = "World" { [0] = 'W' [1] = 'o' [2] = 'r' [3] = 'l' [4] = 'd' } } +// lldb-check:((&str, &str)) str_in_tuple = { 0 = "Hello" { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } 1 = "World" { [0] = 'W' [1] = 'o' [2] = 'r' [3] = 'l' [4] = 'd' } } // lldb-command:v str_in_tuple -// lldbg-check:((&str, &str)) str_in_tuple = { 0 = "Hello" { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } 1 = "World" { [0] = 'W' [1] = 'o' [2] = 'r' [3] = 'l' [4] = 'd' } } +// lldb-check:((&str, &str)) str_in_tuple = { 0 = "Hello" { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } 1 = "World" { [0] = 'W' [1] = 'o' [2] = 'r' [3] = 'l' [4] = 'd' } } // lldb-command:v str_in_rc -// lldbg-check:(alloc::rc::Rc<&str, alloc::alloc::Global>) str_in_rc = strong=1, weak=0 { value = "Hello" { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } } +// lldb-check:(alloc::rc::Rc<&str, alloc::alloc::Global>) str_in_rc = strong=1, weak=0 { value = "Hello" { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } } #![allow(unused_variables)] diff --git a/tests/debuginfo/struct-in-enum.rs b/tests/debuginfo/struct-in-enum.rs index 52e419e6b47..bc2c59fe4aa 100644 --- a/tests/debuginfo/struct-in-enum.rs +++ b/tests/debuginfo/struct-in-enum.rs @@ -1,6 +1,4 @@ -//@ min-lldb-version: 310 -//@ ignore-gdb-version: 7.11.90 - 7.12.9 -//@ ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 +//@ min-lldb-version: 1800 //@ compile-flags:-g @@ -10,16 +8,13 @@ // gdb-command:run // gdb-command:print case1 -// gdbg-check:$1 = {{RUST$ENUM$DISR = Case1, __0 = 0, __1 = {x = 2088533116, y = 2088533116, z = 31868}}, {RUST$ENUM$DISR = Case1, [...]}} -// gdbr-check:$1 = struct_in_enum::Regular::Case1(0, struct_in_enum::Struct {x: 2088533116, y: 2088533116, z: 31868}) +// gdb-check:$1 = struct_in_enum::Regular::Case1(0, struct_in_enum::Struct {x: 2088533116, y: 2088533116, z: 31868}) // gdb-command:print case2 -// gdbg-check:$2 = {{RUST$ENUM$DISR = Case2, [...]}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 1229782938247303441, __2 = 4369}} -// gdbr-check:$2 = struct_in_enum::Regular::Case2(0, 1229782938247303441, 4369) +// gdb-check:$2 = struct_in_enum::Regular::Case2(0, 1229782938247303441, 4369) // gdb-command:print univariant -// gdbg-check:$3 = {{__0 = {x = 123, y = 456, z = 789}}} -// gdbr-check:$3 = struct_in_enum::Univariant::TheOnlyCase(struct_in_enum::Struct {x: 123, y: 456, z: 789}) +// gdb-check:$3 = struct_in_enum::Univariant::TheOnlyCase(struct_in_enum::Struct {x: 123, y: 456, z: 789}) // === LLDB TESTS ================================================================================== diff --git a/tests/debuginfo/struct-in-struct.rs b/tests/debuginfo/struct-in-struct.rs index 7ca0e3a5ef6..3cf48470391 100644 --- a/tests/debuginfo/struct-in-struct.rs +++ b/tests/debuginfo/struct-in-struct.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -7,16 +5,13 @@ // gdb-command:run // gdb-command:print three_simple_structs -// gdbg-check:$1 = {x = {x = 1}, y = {x = 2}, z = {x = 3}} -// gdbr-check:$1 = struct_in_struct::ThreeSimpleStructs {x: struct_in_struct::Simple {x: 1}, y: struct_in_struct::Simple {x: 2}, z: struct_in_struct::Simple {x: 3}} +// gdb-check:$1 = struct_in_struct::ThreeSimpleStructs {x: struct_in_struct::Simple {x: 1}, y: struct_in_struct::Simple {x: 2}, z: struct_in_struct::Simple {x: 3}} // gdb-command:print internal_padding_parent -// gdbg-check:$2 = {x = {x = 4, y = 5}, y = {x = 6, y = 7}, z = {x = 8, y = 9}} -// gdbr-check:$2 = struct_in_struct::InternalPaddingParent {x: struct_in_struct::InternalPadding {x: 4, y: 5}, y: struct_in_struct::InternalPadding {x: 6, y: 7}, z: struct_in_struct::InternalPadding {x: 8, y: 9}} +// gdb-check:$2 = struct_in_struct::InternalPaddingParent {x: struct_in_struct::InternalPadding {x: 4, y: 5}, y: struct_in_struct::InternalPadding {x: 6, y: 7}, z: struct_in_struct::InternalPadding {x: 8, y: 9}} // gdb-command:print padding_at_end_parent -// gdbg-check:$3 = {x = {x = 10, y = 11}, y = {x = 12, y = 13}, z = {x = 14, y = 15}} -// gdbr-check:$3 = struct_in_struct::PaddingAtEndParent {x: struct_in_struct::PaddingAtEnd {x: 10, y: 11}, y: struct_in_struct::PaddingAtEnd {x: 12, y: 13}, z: struct_in_struct::PaddingAtEnd {x: 14, y: 15}} +// gdb-check:$3 = struct_in_struct::PaddingAtEndParent {x: struct_in_struct::PaddingAtEnd {x: 10, y: 11}, y: struct_in_struct::PaddingAtEnd {x: 12, y: 13}, z: struct_in_struct::PaddingAtEnd {x: 14, y: 15}} // === LLDB TESTS ================================================================================== @@ -24,36 +19,28 @@ // lldb-command:run // lldb-command:v three_simple_structs -// lldbg-check:[...] { x = { x = 1 } y = { x = 2 } z = { x = 3 } } -// lldbr-check:(struct_in_struct::ThreeSimpleStructs) three_simple_structs = { x = { x = 1 } y = { x = 2 } z = { x = 3 } } +// lldb-check:[...] { x = { x = 1 } y = { x = 2 } z = { x = 3 } } // lldb-command:v internal_padding_parent -// lldbg-check:[...] { x = { x = 4 y = 5 } y = { x = 6 y = 7 } z = { x = 8 y = 9 } } -// lldbr-check:(struct_in_struct::InternalPaddingParent) internal_padding_parent = { x = { x = 4 y = 5 } y = { x = 6 y = 7 } z = { x = 8 y = 9 } } +// lldb-check:[...] { x = { x = 4 y = 5 } y = { x = 6 y = 7 } z = { x = 8 y = 9 } } // lldb-command:v padding_at_end_parent -// lldbg-check:[...] { x = { x = 10 y = 11 } y = { x = 12 y = 13 } z = { x = 14 y = 15 } } -// lldbr-check:(struct_in_struct::PaddingAtEndParent) padding_at_end_parent = { x = { x = 10 y = 11 } y = { x = 12 y = 13 } z = { x = 14 y = 15 } } +// lldb-check:[...] { x = { x = 10 y = 11 } y = { x = 12 y = 13 } z = { x = 14 y = 15 } } // lldb-command:v mixed -// lldbg-check:[...] { x = { x = 16 y = 17 } y = { x = 18 y = 19 } z = { x = 20 } w = 21 } -// lldbr-check:(struct_in_struct::Mixed) mixed = { x = { x = 16 y = 17 } y = { x = 18 y = 19 } z = { x = 20 } w = 21 } +// lldb-check:[...] { x = { x = 16 y = 17 } y = { x = 18 y = 19 } z = { x = 20 } w = 21 } // lldb-command:v bag -// lldbg-check:[...] { x = { x = 22 } } -// lldbr-check:(struct_in_struct::Bag) bag = { x = { x = 22 } } +// lldb-check:[...] { x = { x = 22 } } // lldb-command:v bag_in_bag -// lldbg-check:[...] { x = { x = { x = 23 } } } -// lldbr-check:(struct_in_struct::BagInBag) bag_in_bag = { x = { x = { x = 23 } } } +// lldb-check:[...] { x = { x = { x = 23 } } } // lldb-command:v tjo -// lldbg-check:[...] { x = { x = { x = { x = 24 } } } } -// lldbr-check:(struct_in_struct::ThatsJustOverkill) tjo = { x = { x = { x = { x = 24 } } } } +// lldb-check:[...] { x = { x = { x = { x = 24 } } } } // lldb-command:v tree -// lldbg-check:[...] { x = { x = 25 } y = { x = { x = 26 y = 27 } y = { x = 28 y = 29 } z = { x = 30 y = 31 } } z = { x = { x = { x = 32 } } } } -// lldbr-check:(struct_in_struct::Tree) tree = { x = { x = 25 } y = { x = { x = 26 y = 27 } y = { x = 28 y = 29 } z = { x = 30 y = 31 } } z = { x = { x = { x = 32 } } } } +// lldb-check:[...] { x = { x = 25 } y = { x = { x = 26 y = 27 } y = { x = 28 y = 29 } z = { x = 30 y = 31 } } z = { x = { x = { x = 32 } } } } #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/struct-namespace.rs b/tests/debuginfo/struct-namespace.rs index 3cae51e83dd..95788419100 100644 --- a/tests/debuginfo/struct-namespace.rs +++ b/tests/debuginfo/struct-namespace.rs @@ -1,23 +1,18 @@ //@ ignore-gdb //@ compile-flags:-g -//@ min-lldb-version: 310 // Check that structs get placed in the correct namespace // lldb-command:run // lldb-command:v struct1 -// lldbg-check:(struct_namespace::Struct1)[...] -// lldbr-check:(struct_namespace::Struct1) struct1 = Struct1 { a: 0, b: 1 } +// lldb-check:(struct_namespace::Struct1)[...] // lldb-command:v struct2 -// lldbg-check:(struct_namespace::Struct2)[...] -// lldbr-check:(struct_namespace::Struct2) struct2 = { = 2 } +// lldb-check:(struct_namespace::Struct2)[...] // lldb-command:v mod1_struct1 -// lldbg-check:(struct_namespace::mod1::Struct1)[...] -// lldbr-check:(struct_namespace::mod1::Struct1) mod1_struct1 = Struct1 { a: 3, b: 4 } +// lldb-check:(struct_namespace::mod1::Struct1)[...] // lldb-command:v mod1_struct2 -// lldbg-check:(struct_namespace::mod1::Struct2)[...] -// lldbr-check:(struct_namespace::mod1::Struct2) mod1_struct2 = { = 5 } +// lldb-check:(struct_namespace::mod1::Struct2)[...] #![allow(unused_variables)] #![allow(dead_code)] diff --git a/tests/debuginfo/struct-style-enum.rs b/tests/debuginfo/struct-style-enum.rs index 42368017cae..cea9f3def8b 100644 --- a/tests/debuginfo/struct-style-enum.rs +++ b/tests/debuginfo/struct-style-enum.rs @@ -1,5 +1,3 @@ -// Require a gdb or lldb that can read DW_TAG_variant_part. -//@ min-gdb-version: 8.2 //@ min-lldb-version: 1800 //@ compile-flags:-g @@ -9,16 +7,16 @@ // gdb-command:run // gdb-command:print case1 -// gdbr-check:$1 = struct_style_enum::Regular::Case1{a: 0, b: 31868, c: 31868, d: 31868, e: 31868} +// gdb-check:$1 = struct_style_enum::Regular::Case1{a: 0, b: 31868, c: 31868, d: 31868, e: 31868} // gdb-command:print case2 -// gdbr-check:$2 = struct_style_enum::Regular::Case2{a: 0, b: 286331153, c: 286331153} +// gdb-check:$2 = struct_style_enum::Regular::Case2{a: 0, b: 286331153, c: 286331153} // gdb-command:print case3 -// gdbr-check:$3 = struct_style_enum::Regular::Case3{a: 0, b: 6438275382588823897} +// gdb-check:$3 = struct_style_enum::Regular::Case3{a: 0, b: 6438275382588823897} // gdb-command:print univariant -// gdbr-check:$4 = struct_style_enum::Univariant::TheOnlyCase{a: -1} +// gdb-check:$4 = struct_style_enum::Univariant::TheOnlyCase{a: -1} // === LLDB TESTS ================================================================================== @@ -26,20 +24,16 @@ // lldb-command:run // lldb-command:v case1 -// lldbg-check:(struct_style_enum::Regular) case1 = { value = { a = 0 b = 31868 c = 31868 d = 31868 e = 31868 } $discr$ = 0 } -// lldbr-check:(struct_style_enum::Regular::Case1) case1 = { a = 0 b = 31868 c = 31868 d = 31868 e = 31868 } +// lldb-check:(struct_style_enum::Regular) case1 = { value = { a = 0 b = 31868 c = 31868 d = 31868 e = 31868 } $discr$ = 0 } // lldb-command:v case2 -// lldbg-check:(struct_style_enum::Regular) case2 = { value = { a = 0 b = 286331153 c = 286331153 } $discr$ = 1 } -// lldbr-check:(struct_style_enum::Regular::Case2) case2 = Case2 { Case1: 0, Case2: 286331153, Case3: 286331153 } +// lldb-check:(struct_style_enum::Regular) case2 = { value = { a = 0 b = 286331153 c = 286331153 } $discr$ = 1 } // lldb-command:v case3 -// lldbg-check:(struct_style_enum::Regular) case3 = { value = { a = 0 b = 6438275382588823897 } $discr$ = 2 } -// lldbr-check:(struct_style_enum::Regular::Case3) case3 = Case3 { Case1: 0, Case2: 6438275382588823897 } +// lldb-check:(struct_style_enum::Regular) case3 = { value = { a = 0 b = 6438275382588823897 } $discr$ = 2 } // lldb-command:v univariant -// lldbg-check:(struct_style_enum::Univariant) univariant = { value = { a = -1 } } -// lldbr-check:(struct_style_enum::Univariant) univariant = Univariant { TheOnlyCase: TheOnlyCase { a: -1 } } +// lldb-check:(struct_style_enum::Univariant) univariant = { value = { a = -1 } } #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/struct-with-destructor.rs b/tests/debuginfo/struct-with-destructor.rs index 12e2ac4225c..c159824980a 100644 --- a/tests/debuginfo/struct-with-destructor.rs +++ b/tests/debuginfo/struct-with-destructor.rs @@ -1,45 +1,35 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== // gdb-command:run // gdb-command:print simple -// gdbg-check:$1 = {x = 10, y = 20} -// gdbr-check:$1 = struct_with_destructor::WithDestructor {x: 10, y: 20} +// gdb-check:$1 = struct_with_destructor::WithDestructor {x: 10, y: 20} // gdb-command:print noDestructor -// gdbg-check:$2 = {a = {x = 10, y = 20}, guard = -1} -// gdbr-check:$2 = struct_with_destructor::NoDestructorGuarded {a: struct_with_destructor::NoDestructor {x: 10, y: 20}, guard: -1} +// gdb-check:$2 = struct_with_destructor::NoDestructorGuarded {a: struct_with_destructor::NoDestructor {x: 10, y: 20}, guard: -1} // gdb-command:print withDestructor -// gdbg-check:$3 = {a = {x = 10, y = 20}, guard = -1} -// gdbr-check:$3 = struct_with_destructor::WithDestructorGuarded {a: struct_with_destructor::WithDestructor {x: 10, y: 20}, guard: -1} +// gdb-check:$3 = struct_with_destructor::WithDestructorGuarded {a: struct_with_destructor::WithDestructor {x: 10, y: 20}, guard: -1} // gdb-command:print nested -// gdbg-check:$4 = {a = {a = {x = 7890, y = 9870}}} -// gdbr-check:$4 = struct_with_destructor::NestedOuter {a: struct_with_destructor::NestedInner {a: struct_with_destructor::WithDestructor {x: 7890, y: 9870}}} +// gdb-check:$4 = struct_with_destructor::NestedOuter {a: struct_with_destructor::NestedInner {a: struct_with_destructor::WithDestructor {x: 7890, y: 9870}}} // === LLDB TESTS ================================================================================== // lldb-command:run // lldb-command:v simple -// lldbg-check:[...] { x = 10 y = 20 } -// lldbr-check:(struct_with_destructor::WithDestructor) simple = { x = 10 y = 20 } +// lldb-check:[...] { x = 10 y = 20 } // lldb-command:v noDestructor -// lldbg-check:[...] { a = { x = 10 y = 20 } guard = -1 } -// lldbr-check:(struct_with_destructor::NoDestructorGuarded) noDestructor = { a = { x = 10 y = 20 } guard = -1 } +// lldb-check:[...] { a = { x = 10 y = 20 } guard = -1 } // lldb-command:v withDestructor -// lldbg-check:[...] { a = { x = 10 y = 20 } guard = -1 } -// lldbr-check:(struct_with_destructor::WithDestructorGuarded) withDestructor = { a = { x = 10 y = 20 } guard = -1 } +// lldb-check:[...] { a = { x = 10 y = 20 } guard = -1 } // lldb-command:v nested -// lldbg-check:[...] { a = { a = { x = 7890 y = 9870 } } } -// lldbr-check:(struct_with_destructor::NestedOuter) nested = { a = { a = { x = 7890 y = 9870 } } } +// lldb-check:[...] { a = { a = { x = 7890 y = 9870 } } } #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/thread-names.rs b/tests/debuginfo/thread-names.rs index 6b3b0c7f4b2..265b9271cf3 100644 --- a/tests/debuginfo/thread-names.rs +++ b/tests/debuginfo/thread-names.rs @@ -4,7 +4,7 @@ //@[macos] only-macos //@[win] only-windows //@ ignore-sgx -//@ ignore-windows-gnu +//@ ignore-windows-gnu: gdb on windows-gnu does not print thread names // === GDB TESTS ================================================================================== // diff --git a/tests/debuginfo/trait-pointers.rs b/tests/debuginfo/trait-pointers.rs index 2b4dde4d3a0..71da71b897a 100644 --- a/tests/debuginfo/trait-pointers.rs +++ b/tests/debuginfo/trait-pointers.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // gdb-command:run // lldb-command:run diff --git a/tests/debuginfo/tuple-in-struct.rs b/tests/debuginfo/tuple-in-struct.rs index e36d924e925..a74d6203f5f 100644 --- a/tests/debuginfo/tuple-in-struct.rs +++ b/tests/debuginfo/tuple-in-struct.rs @@ -1,43 +1,31 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // gdb-command:run // gdb-command:print no_padding1 -// gdbg-check:$1 = {x = {__0 = 0, __1 = 1}, y = 2, z = {__0 = 3, __1 = 4, __2 = 5}} -// gdbr-check:$1 = tuple_in_struct::NoPadding1 {x: (0, 1), y: 2, z: (3, 4, 5)} +// gdb-check:$1 = tuple_in_struct::NoPadding1 {x: (0, 1), y: 2, z: (3, 4, 5)} // gdb-command:print no_padding2 -// gdbg-check:$2 = {x = {__0 = 6, __1 = 7}, y = {__0 = {__0 = 8, __1 = 9}, __1 = 10}} -// gdbr-check:$2 = tuple_in_struct::NoPadding2 {x: (6, 7), y: ((8, 9), 10)} +// gdb-check:$2 = tuple_in_struct::NoPadding2 {x: (6, 7), y: ((8, 9), 10)} // gdb-command:print tuple_internal_padding -// gdbg-check:$3 = {x = {__0 = 11, __1 = 12}, y = {__0 = 13, __1 = 14}} -// gdbr-check:$3 = tuple_in_struct::TupleInternalPadding {x: (11, 12), y: (13, 14)} +// gdb-check:$3 = tuple_in_struct::TupleInternalPadding {x: (11, 12), y: (13, 14)} // gdb-command:print struct_internal_padding -// gdbg-check:$4 = {x = {__0 = 15, __1 = 16}, y = {__0 = 17, __1 = 18}} -// gdbr-check:$4 = tuple_in_struct::StructInternalPadding {x: (15, 16), y: (17, 18)} +// gdb-check:$4 = tuple_in_struct::StructInternalPadding {x: (15, 16), y: (17, 18)} // gdb-command:print both_internally_padded -// gdbg-check:$5 = {x = {__0 = 19, __1 = 20, __2 = 21}, y = {__0 = 22, __1 = 23}} -// gdbr-check:$5 = tuple_in_struct::BothInternallyPadded {x: (19, 20, 21), y: (22, 23)} +// gdb-check:$5 = tuple_in_struct::BothInternallyPadded {x: (19, 20, 21), y: (22, 23)} // gdb-command:print single_tuple -// gdbg-check:$6 = {x = {__0 = 24, __1 = 25, __2 = 26}} -// gdbr-check:$6 = tuple_in_struct::SingleTuple {x: (24, 25, 26)} +// gdb-check:$6 = tuple_in_struct::SingleTuple {x: (24, 25, 26)} // gdb-command:print tuple_padded_at_end -// gdbg-check:$7 = {x = {__0 = 27, __1 = 28}, y = {__0 = 29, __1 = 30}} -// gdbr-check:$7 = tuple_in_struct::TuplePaddedAtEnd {x: (27, 28), y: (29, 30)} +// gdb-check:$7 = tuple_in_struct::TuplePaddedAtEnd {x: (27, 28), y: (29, 30)} // gdb-command:print struct_padded_at_end -// gdbg-check:$8 = {x = {__0 = 31, __1 = 32}, y = {__0 = 33, __1 = 34}} -// gdbr-check:$8 = tuple_in_struct::StructPaddedAtEnd {x: (31, 32), y: (33, 34)} +// gdb-check:$8 = tuple_in_struct::StructPaddedAtEnd {x: (31, 32), y: (33, 34)} // gdb-command:print both_padded_at_end -// gdbg-check:$9 = {x = {__0 = 35, __1 = 36, __2 = 37}, y = {__0 = 38, __1 = 39}} -// gdbr-check:$9 = tuple_in_struct::BothPaddedAtEnd {x: (35, 36, 37), y: (38, 39)} +// gdb-check:$9 = tuple_in_struct::BothPaddedAtEnd {x: (35, 36, 37), y: (38, 39)} // gdb-command:print mixed_padding -// gdbg-check:$10 = {x = {__0 = {__0 = 40, __1 = 41, __2 = 42}, __1 = {__0 = 43, __1 = 44}}, y = {__0 = 45, __1 = 46, __2 = 47, __3 = 48}} -// gdbr-check:$10 = tuple_in_struct::MixedPadding {x: ((40, 41, 42), (43, 44)), y: (45, 46, 47, 48)} +// gdb-check:$10 = tuple_in_struct::MixedPadding {x: ((40, 41, 42), (43, 44)), y: (45, 46, 47, 48)} #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/tuple-in-tuple.rs b/tests/debuginfo/tuple-in-tuple.rs index 8ed0e1f9c13..d4388095ad7 100644 --- a/tests/debuginfo/tuple-in-tuple.rs +++ b/tests/debuginfo/tuple-in-tuple.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -7,28 +5,21 @@ // gdb-command:run // gdb-command:print no_padding1 -// gdbg-check:$1 = {__0 = {__0 = 0, __1 = 1}, __1 = 2, __2 = 3} -// gdbr-check:$1 = ((0, 1), 2, 3) +// gdb-check:$1 = ((0, 1), 2, 3) // gdb-command:print no_padding2 -// gdbg-check:$2 = {__0 = 4, __1 = {__0 = 5, __1 = 6}, __2 = 7} -// gdbr-check:$2 = (4, (5, 6), 7) +// gdb-check:$2 = (4, (5, 6), 7) // gdb-command:print no_padding3 -// gdbg-check:$3 = {__0 = 8, __1 = 9, __2 = {__0 = 10, __1 = 11}} -// gdbr-check:$3 = (8, 9, (10, 11)) +// gdb-check:$3 = (8, 9, (10, 11)) // gdb-command:print internal_padding1 -// gdbg-check:$4 = {__0 = 12, __1 = {__0 = 13, __1 = 14}} -// gdbr-check:$4 = (12, (13, 14)) +// gdb-check:$4 = (12, (13, 14)) // gdb-command:print internal_padding2 -// gdbg-check:$5 = {__0 = 15, __1 = {__0 = 16, __1 = 17}} -// gdbr-check:$5 = (15, (16, 17)) +// gdb-check:$5 = (15, (16, 17)) // gdb-command:print padding_at_end1 -// gdbg-check:$6 = {__0 = 18, __1 = {__0 = 19, __1 = 20}} -// gdbr-check:$6 = (18, (19, 20)) +// gdb-check:$6 = (18, (19, 20)) // gdb-command:print padding_at_end2 -// gdbg-check:$7 = {__0 = {__0 = 21, __1 = 22}, __1 = 23} -// gdbr-check:$7 = ((21, 22), 23) +// gdb-check:$7 = ((21, 22), 23) // === LLDB TESTS ================================================================================== @@ -36,28 +27,21 @@ // lldb-command:run // lldb-command:v no_padding1 -// lldbg-check:[...] { 0 = { 0 = 0 1 = 1 } 1 = 2 2 = 3 } -// lldbr-check:(((u32, u32), u32, u32)) no_padding1 = { 0 = { 0 = 0 1 = 1 } 1 = 2 2 = 3 } +// lldb-check:[...] { 0 = { 0 = 0 1 = 1 } 1 = 2 2 = 3 } // lldb-command:v no_padding2 -// lldbg-check:[...] { 0 = 4 1 = { 0 = 5 1 = 6 } 2 = 7 } -// lldbr-check:((u32, (u32, u32), u32)) no_padding2 = { 0 = 4 1 = { 0 = 5 1 = 6 } 2 = 7 } +// lldb-check:[...] { 0 = 4 1 = { 0 = 5 1 = 6 } 2 = 7 } // lldb-command:v no_padding3 -// lldbg-check:[...] { 0 = 8 1 = 9 2 = { 0 = 10 1 = 11 } } -// lldbr-check:((u32, u32, (u32, u32))) no_padding3 = { 0 = 8 1 = 9 2 = { 0 = 10 1 = 11 } } +// lldb-check:[...] { 0 = 8 1 = 9 2 = { 0 = 10 1 = 11 } } // lldb-command:v internal_padding1 -// lldbg-check:[...] { 0 = 12 1 = { 0 = 13 1 = 14 } } -// lldbr-check:((i16, (i32, i32))) internal_padding1 = { 0 = 12 1 = { 0 = 13 1 = 14 } } +// lldb-check:[...] { 0 = 12 1 = { 0 = 13 1 = 14 } } // lldb-command:v internal_padding2 -// lldbg-check:[...] { 0 = 15 1 = { 0 = 16 1 = 17 } } -// lldbr-check:((i16, (i16, i32))) internal_padding2 = { 0 = 15 1 = { 0 = 16 1 = 17 } } +// lldb-check:[...] { 0 = 15 1 = { 0 = 16 1 = 17 } } // lldb-command:v padding_at_end1 -// lldbg-check:[...] { 0 = 18 1 = { 0 = 19 1 = 20 } } -// lldbr-check:((i32, (i32, i16))) padding_at_end1 = { 0 = 18 1 = { 0 = 19 1 = 20 } } +// lldb-check:[...] { 0 = 18 1 = { 0 = 19 1 = 20 } } // lldb-command:v padding_at_end2 -// lldbg-check:[...] { 0 = { 0 = 21 1 = 22 } 1 = 23 } -// lldbr-check:(((i32, i16), i32)) padding_at_end2 = { 0 = { 0 = 21 1 = 22 } 1 = 23 } +// lldb-check:[...] { 0 = { 0 = 21 1 = 22 } 1 = 23 } // === CDB TESTS ================================================================================== diff --git a/tests/debuginfo/tuple-struct.rs b/tests/debuginfo/tuple-struct.rs index 88b1ae19e29..0110203a7c7 100644 --- a/tests/debuginfo/tuple-struct.rs +++ b/tests/debuginfo/tuple-struct.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -7,28 +5,22 @@ // gdb-command:run // gdb-command:print no_padding16 -// gdbg-check:$1 = {__0 = 10000, __1 = -10001} -// gdbr-check:$1 = tuple_struct::NoPadding16 (10000, -10001) +// gdb-check:$1 = tuple_struct::NoPadding16 (10000, -10001) // gdb-command:print no_padding32 -// gdbg-check:$2 = {__0 = -10002, __1 = -10003.5, __2 = 10004} -// gdbr-check:$2 = tuple_struct::NoPadding32 (-10002, -10003.5, 10004) +// gdb-check:$2 = tuple_struct::NoPadding32 (-10002, -10003.5, 10004) // gdb-command:print no_padding64 -// gdbg-check:$3 = {__0 = -10005.5, __1 = 10006, __2 = 10007} -// gdbr-check:$3 = tuple_struct::NoPadding64 (-10005.5, 10006, 10007) +// gdb-check:$3 = tuple_struct::NoPadding64 (-10005.5, 10006, 10007) // gdb-command:print no_padding163264 -// gdbg-check:$4 = {__0 = -10008, __1 = 10009, __2 = 10010, __3 = 10011} -// gdbr-check:$4 = tuple_struct::NoPadding163264 (-10008, 10009, 10010, 10011) +// gdb-check:$4 = tuple_struct::NoPadding163264 (-10008, 10009, 10010, 10011) // gdb-command:print internal_padding -// gdbg-check:$5 = {__0 = 10012, __1 = -10013} -// gdbr-check:$5 = tuple_struct::InternalPadding (10012, -10013) +// gdb-check:$5 = tuple_struct::InternalPadding (10012, -10013) // gdb-command:print padding_at_end -// gdbg-check:$6 = {__0 = -10014, __1 = 10015} -// gdbr-check:$6 = tuple_struct::PaddingAtEnd (-10014, 10015) +// gdb-check:$6 = tuple_struct::PaddingAtEnd (-10014, 10015) // === LLDB TESTS ================================================================================== @@ -36,28 +28,22 @@ // lldb-command:run // lldb-command:v no_padding16 -// lldbg-check:[...] { 0 = 10000 1 = -10001 } -// lldbr-check:(tuple_struct::NoPadding16) no_padding16 = { 0 = 10000 1 = -10001 } +// lldb-check:[...] { 0 = 10000 1 = -10001 } // lldb-command:v no_padding32 -// lldbg-check:[...] { 0 = -10002 1 = -10003.5 2 = 10004 } -// lldbr-check:(tuple_struct::NoPadding32) no_padding32 = { 0 = -10002 1 = -10003.5 2 = 10004 } +// lldb-check:[...] { 0 = -10002 1 = -10003.5 2 = 10004 } // lldb-command:v no_padding64 -// lldbg-check:[...] { 0 = -10005.5 1 = 10006 2 = 10007 } -// lldbr-check:(tuple_struct::NoPadding64) no_padding64 = { 0 = -10005.5 1 = 10006 2 = 10007 } +// lldb-check:[...] { 0 = -10005.5 1 = 10006 2 = 10007 } // lldb-command:v no_padding163264 -// lldbg-check:[...] { 0 = -10008 1 = 10009 2 = 10010 3 = 10011 } -// lldbr-check:(tuple_struct::NoPadding163264) no_padding163264 = { 0 = -10008 1 = 10009 2 = 10010 3 = 10011 } +// lldb-check:[...] { 0 = -10008 1 = 10009 2 = 10010 3 = 10011 } // lldb-command:v internal_padding -// lldbg-check:[...] { 0 = 10012 1 = -10013 } -// lldbr-check:(tuple_struct::InternalPadding) internal_padding = { 0 = 10012 1 = -10013 } +// lldb-check:[...] { 0 = 10012 1 = -10013 } // lldb-command:v padding_at_end -// lldbg-check:[...] { 0 = -10014 1 = 10015 } -// lldbr-check:(tuple_struct::PaddingAtEnd) padding_at_end = { 0 = -10014 1 = 10015 } +// lldb-check:[...] { 0 = -10014 1 = 10015 } // This test case mainly makes sure that no field names are generated for tuple structs (as opposed // to all fields having the name ""). Otherwise they are handled the same a normal diff --git a/tests/debuginfo/tuple-style-enum.rs b/tests/debuginfo/tuple-style-enum.rs index 3de4ecb1284..a759ad61c05 100644 --- a/tests/debuginfo/tuple-style-enum.rs +++ b/tests/debuginfo/tuple-style-enum.rs @@ -1,5 +1,3 @@ -// Require a gdb or lldb that can read DW_TAG_variant_part. -//@ min-gdb-version: 8.2 //@ min-lldb-version: 1800 //@ compile-flags:-g @@ -10,16 +8,16 @@ // gdb-command:run // gdb-command:print case1 -// gdbr-check:$1 = tuple_style_enum::Regular::Case1(0, 31868, 31868, 31868, 31868) +// gdb-check:$1 = tuple_style_enum::Regular::Case1(0, 31868, 31868, 31868, 31868) // gdb-command:print case2 -// gdbr-check:$2 = tuple_style_enum::Regular::Case2(0, 286331153, 286331153) +// gdb-check:$2 = tuple_style_enum::Regular::Case2(0, 286331153, 286331153) // gdb-command:print case3 -// gdbr-check:$3 = tuple_style_enum::Regular::Case3(0, 6438275382588823897) +// gdb-check:$3 = tuple_style_enum::Regular::Case3(0, 6438275382588823897) // gdb-command:print univariant -// gdbr-check:$4 = tuple_style_enum::Univariant::TheOnlyCase(-1) +// gdb-check:$4 = tuple_style_enum::Univariant::TheOnlyCase(-1) // === LLDB TESTS ================================================================================== @@ -27,20 +25,16 @@ // lldb-command:run // lldb-command:v case1 -// lldbg-check:(tuple_style_enum::Regular) case1 = { value = { 0 = 0 1 = 31868 2 = 31868 3 = 31868 4 = 31868 } $discr$ = 0 } -// lldbr-check:(tuple_style_enum::Regular::Case1) case1 = { = 0 = 31868 = 31868 = 31868 = 31868 } +// lldb-check:(tuple_style_enum::Regular) case1 = { value = { 0 = 0 1 = 31868 2 = 31868 3 = 31868 4 = 31868 } $discr$ = 0 } // lldb-command:v case2 -// lldbg-check:(tuple_style_enum::Regular) case2 = { value = { 0 = 0 1 = 286331153 2 = 286331153 } $discr$ = 1 } -// lldbr-check:(tuple_style_enum::Regular::Case2) case2 = Case2 { Case1: 0, Case2: 286331153, Case3: 286331153 } +// lldb-check:(tuple_style_enum::Regular) case2 = { value = { 0 = 0 1 = 286331153 2 = 286331153 } $discr$ = 1 } // lldb-command:v case3 -// lldbg-check:(tuple_style_enum::Regular) case3 = { value = { 0 = 0 1 = 6438275382588823897 } $discr$ = 2 } -// lldbr-check:(tuple_style_enum::Regular::Case3) case3 = Case3 { Case1: 0, Case2: 6438275382588823897 } +// lldb-check:(tuple_style_enum::Regular) case3 = { value = { 0 = 0 1 = 6438275382588823897 } $discr$ = 2 } // lldb-command:v univariant -// lldbg-check:(tuple_style_enum::Univariant) univariant = { value = { 0 = -1 } } -// lldbr-check:(tuple_style_enum::Univariant) univariant = { TheOnlyCase = { = -1 } } +// lldb-check:(tuple_style_enum::Univariant) univariant = { value = { 0 = -1 } } #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/union-smoke.rs b/tests/debuginfo/union-smoke.rs index 9b1cf6e1e95..6043240069e 100644 --- a/tests/debuginfo/union-smoke.rs +++ b/tests/debuginfo/union-smoke.rs @@ -1,31 +1,21 @@ -//@ min-lldb-version: 310 -//@ ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 - -//@ ignore-gdb-version: 7.11.90 - 7.12.9 - //@ compile-flags:-g // === GDB TESTS =================================================================================== // gdb-command:run // gdb-command:print u -// gdbg-check:$1 = {a = {__0 = 2 '\002', __1 = 2 '\002'}, b = 514} -// gdbr-check:$1 = union_smoke::U {a: (2, 2), b: 514} +// gdb-check:$1 = union_smoke::U {a: (2, 2), b: 514} // gdb-command:print union_smoke::SU -// gdbg-check:$2 = {a = {__0 = 1 '\001', __1 = 1 '\001'}, b = 257} -// gdbr-check:$2 = union_smoke::U {a: (1, 1), b: 257} +// gdb-check:$2 = union_smoke::U {a: (1, 1), b: 257} // === LLDB TESTS ================================================================================== // lldb-command:run // lldb-command:v u -// lldbg-check:[...] { a = { 0 = '\x02' 1 = '\x02' } b = 514 } -// lldbr-check:(union_smoke::U) u = { a = { 0 = '\x02' 1 = '\x02' } b = 514 } +// lldb-check:[...] { a = { 0 = '\x02' 1 = '\x02' } b = 514 } -// Don't test this with rust-enabled lldb for now; see -// https://github.com/rust-lang-nursery/lldb/issues/18 -// lldbg-command:print union_smoke::SU -// lldbg-check:[...] { a = { 0 = '\x01' 1 = '\x01' } b = 257 } +// lldb-command:print union_smoke::SU +// lldb-check:[...] { a = { 0 = '\x01' 1 = '\x01' } b = 257 } #![allow(unused)] #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/unique-enum.rs b/tests/debuginfo/unique-enum.rs index 514c7c50812..230429278aa 100644 --- a/tests/debuginfo/unique-enum.rs +++ b/tests/debuginfo/unique-enum.rs @@ -1,5 +1,3 @@ -// Require a gdb or lldb that can read DW_TAG_variant_part. -//@ min-gdb-version: 8.2 //@ min-lldb-version: 1800 //@ compile-flags:-g @@ -9,13 +7,13 @@ // gdb-command:run // gdb-command:print *the_a -// gdbr-check:$1 = unique_enum::ABC::TheA{x: 0, y: 8970181431921507452} +// gdb-check:$1 = unique_enum::ABC::TheA{x: 0, y: 8970181431921507452} // gdb-command:print *the_b -// gdbr-check:$2 = unique_enum::ABC::TheB(0, 286331153, 286331153) +// gdb-check:$2 = unique_enum::ABC::TheB(0, 286331153, 286331153) // gdb-command:print *univariant -// gdbr-check:$3 = unique_enum::Univariant::TheOnlyCase(123234) +// gdb-check:$3 = unique_enum::Univariant::TheOnlyCase(123234) // === LLDB TESTS ================================================================================== @@ -23,16 +21,13 @@ // lldb-command:run // lldb-command:v *the_a -// lldbg-check:(unique_enum::ABC) *the_a = { value = { x = 0 y = 8970181431921507452 } $discr$ = 0 } -// lldbr-check:(unique_enum::ABC::TheA) *the_a = TheA { TheA: 0, TheB: 8970181431921507452 } +// lldb-check:(unique_enum::ABC) *the_a = { value = { x = 0 y = 8970181431921507452 } $discr$ = 0 } // lldb-command:v *the_b -// lldbg-check:(unique_enum::ABC) *the_b = { value = { 0 = 0 1 = 286331153 2 = 286331153 } $discr$ = 1 } -// lldbr-check:(unique_enum::ABC::TheB) *the_b = { = 0 = 286331153 = 286331153 } +// lldb-check:(unique_enum::ABC) *the_b = { value = { 0 = 0 1 = 286331153 2 = 286331153 } $discr$ = 1 } // lldb-command:v *univariant -// lldbg-check:(unique_enum::Univariant) *univariant = { value = { 0 = 123234 } } -// lldbr-check:(unique_enum::Univariant) *univariant = { TheOnlyCase = { = 123234 } } +// lldb-check:(unique_enum::Univariant) *univariant = { value = { 0 = 123234 } } #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/unit-type.rs b/tests/debuginfo/unit-type.rs index 60b105fc53d..42c0ff11f71 100644 --- a/tests/debuginfo/unit-type.rs +++ b/tests/debuginfo/unit-type.rs @@ -1,8 +1,5 @@ //@ compile-flags:-g -// We only test Rust-aware versions of GDB: -//@ min-gdb-version: 8.2 - // === GDB TESTS =================================================================================== // gdb-command: run diff --git a/tests/debuginfo/unreachable-locals.rs b/tests/debuginfo/unreachable-locals.rs index 72effc10391..d4416387e0b 100644 --- a/tests/debuginfo/unreachable-locals.rs +++ b/tests/debuginfo/unreachable-locals.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g #![allow(unused_variables)] diff --git a/tests/debuginfo/unsized.rs b/tests/debuginfo/unsized.rs index 982ab003a2a..acfe511be7c 100644 --- a/tests/debuginfo/unsized.rs +++ b/tests/debuginfo/unsized.rs @@ -7,28 +7,22 @@ // gdb-command:run // gdb-command:print a -// gdbg-check:$1 = {data_ptr = [...], length = 4} -// gdbr-check:$1 = &unsized::Foo<[u8]> {data_ptr: [...], length: 4} +// gdb-check:$1 = &unsized::Foo<[u8]> {data_ptr: [...], length: 4} // gdb-command:print b -// gdbg-check:$2 = {data_ptr = [...], length = 4} -// gdbr-check:$2 = &unsized::Foo> {data_ptr: [...], length: 4} +// gdb-check:$2 = &unsized::Foo> {data_ptr: [...], length: 4} // gdb-command:print c -// gdbg-check:$3 = {pointer = [...], vtable = [...]} -// gdbr-check:$3 = &unsized::Foo {pointer: [...], vtable: [...]} +// gdb-check:$3 = &unsized::Foo {pointer: [...], vtable: [...]} // gdb-command:print _box -// gdbg-check:$4 = {pointer = [...], vtable = [...]} -// gdbr-check:$4 = alloc::boxed::Box, alloc::alloc::Global> {pointer: [...], vtable: [...]} +// gdb-check:$4 = alloc::boxed::Box, alloc::alloc::Global> {pointer: [...], vtable: [...]} // gdb-command:print tuple_slice -// gdbg-check:$5 = {data_ptr = [...], length = 2} -// gdbr-check:$5 = &(i32, i32, [i32]) {data_ptr: [...], length: 2} +// gdb-check:$5 = &(i32, i32, [i32]) {data_ptr: [...], length: 2} // gdb-command:print tuple_dyn -// gdbg-check:$6 = {pointer = [...], vtable = [...]} -// gdbr-check:$6 = &(i32, i32, dyn core::fmt::Debug) {pointer: [...], vtable: [...]} +// gdb-check:$6 = &(i32, i32, dyn core::fmt::Debug) {pointer: [...], vtable: [...]} // === CDB TESTS =================================================================================== diff --git a/tests/debuginfo/var-captured-in-nested-closure.rs b/tests/debuginfo/var-captured-in-nested-closure.rs index 7772ec00337..4e8700015ba 100644 --- a/tests/debuginfo/var-captured-in-nested-closure.rs +++ b/tests/debuginfo/var-captured-in-nested-closure.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -11,11 +9,9 @@ // gdb-command:print constant // gdb-check:$2 = 2 // gdb-command:print a_struct -// gdbg-check:$3 = {a = -3, b = 4.5, c = 5} -// gdbr-check:$3 = var_captured_in_nested_closure::Struct {a: -3, b: 4.5, c: 5} +// gdb-check:$3 = var_captured_in_nested_closure::Struct {a: -3, b: 4.5, c: 5} // gdb-command:print *struct_ref -// gdbg-check:$4 = {a = -3, b = 4.5, c = 5} -// gdbr-check:$4 = var_captured_in_nested_closure::Struct {a: -3, b: 4.5, c: 5} +// gdb-check:$4 = var_captured_in_nested_closure::Struct {a: -3, b: 4.5, c: 5} // gdb-command:print *owned // gdb-check:$5 = 6 // gdb-command:print closure_local @@ -27,11 +23,9 @@ // gdb-command:print constant // gdb-check:$8 = 2 // gdb-command:print a_struct -// gdbg-check:$9 = {a = -3, b = 4.5, c = 5} -// gdbr-check:$9 = var_captured_in_nested_closure::Struct {a: -3, b: 4.5, c: 5} +// gdb-check:$9 = var_captured_in_nested_closure::Struct {a: -3, b: 4.5, c: 5} // gdb-command:print *struct_ref -// gdbg-check:$10 = {a = -3, b = 4.5, c = 5} -// gdbr-check:$10 = var_captured_in_nested_closure::Struct {a: -3, b: 4.5, c: 5} +// gdb-check:$10 = var_captured_in_nested_closure::Struct {a: -3, b: 4.5, c: 5} // gdb-command:print *owned // gdb-check:$11 = 6 // gdb-command:print closure_local @@ -44,43 +38,31 @@ // lldb-command:run // lldb-command:v variable -// lldbg-check:[...] 1 -// lldbr-check:(isize) variable = 1 +// lldb-check:[...] 1 // lldb-command:v constant -// lldbg-check:[...] 2 -// lldbr-check:(isize) constant = 2 +// lldb-check:[...] 2 // lldb-command:v a_struct -// lldbg-check:[...] { a = -3 b = 4.5 c = 5 } -// lldbr-check:(var_captured_in_nested_closure::Struct) a_struct = { a = -3 b = 4.5 c = 5 } +// lldb-check:[...] { a = -3 b = 4.5 c = 5 } // lldb-command:v *struct_ref -// lldbg-check:[...] { a = -3 b = 4.5 c = 5 } -// lldbr-check:(var_captured_in_nested_closure::Struct) *struct_ref = { a = -3 b = 4.5 c = 5 } +// lldb-check:[...] { a = -3 b = 4.5 c = 5 } // lldb-command:v *owned -// lldbg-check:[...] 6 -// lldbr-check:(isize) *owned = 6 +// lldb-check:[...] 6 // lldb-command:v closure_local -// lldbg-check:[...] 8 -// lldbr-check:(isize) closure_local = 8 +// lldb-check:[...] 8 // lldb-command:continue // lldb-command:v variable -// lldbg-check:[...] 1 -// lldbr-check:(isize) variable = 1 +// lldb-check:[...] 1 // lldb-command:v constant -// lldbg-check:[...] 2 -// lldbr-check:(isize) constant = 2 +// lldb-check:[...] 2 // lldb-command:v a_struct -// lldbg-check:[...] { a = -3 b = 4.5 c = 5 } -// lldbr-check:(var_captured_in_nested_closure::Struct) a_struct = { a = -3 b = 4.5 c = 5 } +// lldb-check:[...] { a = -3 b = 4.5 c = 5 } // lldb-command:v *struct_ref -// lldbg-check:[...] { a = -3 b = 4.5 c = 5 } -// lldbr-check:(var_captured_in_nested_closure::Struct) *struct_ref = { a = -3 b = 4.5 c = 5 } +// lldb-check:[...] { a = -3 b = 4.5 c = 5 } // lldb-command:v *owned -// lldbg-check:[...] 6 -// lldbr-check:(isize) *owned = 6 +// lldb-check:[...] 6 // lldb-command:v closure_local -// lldbg-check:[...] 8 -// lldbr-check:(isize) closure_local = 8 +// lldb-check:[...] 8 // lldb-command:continue diff --git a/tests/debuginfo/var-captured-in-sendable-closure.rs b/tests/debuginfo/var-captured-in-sendable-closure.rs index 782a7d11373..cbb09daeb5f 100644 --- a/tests/debuginfo/var-captured-in-sendable-closure.rs +++ b/tests/debuginfo/var-captured-in-sendable-closure.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -9,8 +7,7 @@ // gdb-command:print constant // gdb-check:$1 = 1 // gdb-command:print a_struct -// gdbg-check:$2 = {a = -2, b = 3.5, c = 4} -// gdbr-check:$2 = var_captured_in_sendable_closure::Struct {a: -2, b: 3.5, c: 4} +// gdb-check:$2 = var_captured_in_sendable_closure::Struct {a: -2, b: 3.5, c: 4} // gdb-command:print *owned // gdb-check:$3 = 5 // gdb-command:continue @@ -24,14 +21,11 @@ // lldb-command:run // lldb-command:v constant -// lldbg-check:[...] 1 -// lldbr-check:(isize) constant = 1 +// lldb-check:[...] 1 // lldb-command:v a_struct -// lldbg-check:[...] { a = -2 b = 3.5 c = 4 } -// lldbr-check:(var_captured_in_sendable_closure::Struct) a_struct = { a = -2 b = 3.5 c = 4 } +// lldb-check:[...] { a = -2 b = 3.5 c = 4 } // lldb-command:v *owned -// lldbg-check:[...] 5 -// lldbr-check:(isize) *owned = 5 +// lldb-check:[...] 5 #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/var-captured-in-stack-closure.rs b/tests/debuginfo/var-captured-in-stack-closure.rs index c9a93cd7b7f..0f84ea57b00 100644 --- a/tests/debuginfo/var-captured-in-stack-closure.rs +++ b/tests/debuginfo/var-captured-in-stack-closure.rs @@ -1,5 +1,3 @@ -//@ min-lldb-version: 310 - //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -11,11 +9,9 @@ // gdb-command:print constant // gdb-check:$2 = 2 // gdb-command:print a_struct -// gdbg-check:$3 = {a = -3, b = 4.5, c = 5} -// gdbr-check:$3 = var_captured_in_stack_closure::Struct {a: -3, b: 4.5, c: 5} +// gdb-check:$3 = var_captured_in_stack_closure::Struct {a: -3, b: 4.5, c: 5} // gdb-command:print *struct_ref -// gdbg-check:$4 = {a = -3, b = 4.5, c = 5} -// gdbr-check:$4 = var_captured_in_stack_closure::Struct {a: -3, b: 4.5, c: 5} +// gdb-check:$4 = var_captured_in_stack_closure::Struct {a: -3, b: 4.5, c: 5} // gdb-command:print *owned // gdb-check:$5 = 6 @@ -26,11 +22,9 @@ // gdb-command:print constant // gdb-check:$7 = 2 // gdb-command:print a_struct -// gdbg-check:$8 = {a = -3, b = 4.5, c = 5} -// gdbr-check:$8 = var_captured_in_stack_closure::Struct {a: -3, b: 4.5, c: 5} +// gdb-check:$8 = var_captured_in_stack_closure::Struct {a: -3, b: 4.5, c: 5} // gdb-command:print *struct_ref -// gdbg-check:$9 = {a = -3, b = 4.5, c = 5} -// gdbr-check:$9 = var_captured_in_stack_closure::Struct {a: -3, b: 4.5, c: 5} +// gdb-check:$9 = var_captured_in_stack_closure::Struct {a: -3, b: 4.5, c: 5} // gdb-command:print *owned // gdb-check:$10 = 6 @@ -40,38 +34,28 @@ // lldb-command:run // lldb-command:v variable -// lldbg-check:[...] 1 -// lldbr-check:(isize) variable = 1 +// lldb-check:[...] 1 // lldb-command:v constant -// lldbg-check:[...] 2 -// lldbr-check:(isize) constant = 2 +// lldb-check:[...] 2 // lldb-command:v a_struct -// lldbg-check:[...] { a = -3 b = 4.5 c = 5 } -// lldbr-check:(var_captured_in_stack_closure::Struct) a_struct = { a = -3 b = 4.5 c = 5 } +// lldb-check:[...] { a = -3 b = 4.5 c = 5 } // lldb-command:v *struct_ref -// lldbg-check:[...] { a = -3 b = 4.5 c = 5 } -// lldbr-check:(var_captured_in_stack_closure::Struct) *struct_ref = { a = -3 b = 4.5 c = 5 } +// lldb-check:[...] { a = -3 b = 4.5 c = 5 } // lldb-command:v *owned -// lldbg-check:[...] 6 -// lldbr-check:(isize) *owned = 6 +// lldb-check:[...] 6 // lldb-command:continue // lldb-command:v variable -// lldbg-check:[...] 2 -// lldbr-check:(isize) variable = 2 +// lldb-check:[...] 2 // lldb-command:v constant -// lldbg-check:[...] 2 -// lldbr-check:(isize) constant = 2 +// lldb-check:[...] 2 // lldb-command:v a_struct -// lldbg-check:[...] { a = -3 b = 4.5 c = 5 } -// lldbr-check:(var_captured_in_stack_closure::Struct) a_struct = { a = -3 b = 4.5 c = 5 } +// lldb-check:[...] { a = -3 b = 4.5 c = 5 } // lldb-command:v *struct_ref -// lldbg-check:[...] { a = -3 b = 4.5 c = 5 } -// lldbr-check:(var_captured_in_stack_closure::Struct) *struct_ref = { a = -3 b = 4.5 c = 5 } +// lldb-check:[...] { a = -3 b = 4.5 c = 5 } // lldb-command:v *owned -// lldbg-check:[...] 6 -// lldbr-check:(isize) *owned = 6 +// lldb-check:[...] 6 // === CDB TESTS =================================================================================== diff --git a/tests/debuginfo/vec-slices.rs b/tests/debuginfo/vec-slices.rs index a8235dba40c..2b4d624976a 100644 --- a/tests/debuginfo/vec-slices.rs +++ b/tests/debuginfo/vec-slices.rs @@ -1,4 +1,3 @@ -//@ min-lldb-version: 310 //@ ignore-gdb-version: 15.0 - 99.0 // ^ test temporarily disabled as it fails under gdb 15 @@ -12,89 +11,64 @@ // gdb-command:print singleton.length // gdb-check:$2 = 1 -// gdbg-command:print *((i64[1]*)(singleton.data_ptr)) -// gdbr-command:print *(singleton.data_ptr as *const [i64; 1]) -// gdbg-check:$3 = {1} -// gdbr-check:$3 = [1] +// gdb-command:print *(singleton.data_ptr as *const [i64; 1]) +// gdb-check:$3 = [1] // gdb-command:print multiple.length // gdb-check:$4 = 4 -// gdbg-command:print *((i64[4]*)(multiple.data_ptr)) -// gdbr-command:print *(multiple.data_ptr as *const [i64; 4]) -// gdbg-check:$5 = {2, 3, 4, 5} -// gdbr-check:$5 = [2, 3, 4, 5] +// gdb-command:print *(multiple.data_ptr as *const [i64; 4]) +// gdb-check:$5 = [2, 3, 4, 5] // gdb-command:print slice_of_slice.length // gdb-check:$6 = 2 -// gdbg-command:print *((i64[2]*)(slice_of_slice.data_ptr)) -// gdbr-command:print *(slice_of_slice.data_ptr as *const [i64; 2]) -// gdbg-check:$7 = {3, 4} -// gdbr-check:$7 = [3, 4] +// gdb-command:print *(slice_of_slice.data_ptr as *const [i64; 2]) +// gdb-check:$7 = [3, 4] // gdb-command:print padded_tuple.length // gdb-check:$8 = 2 // gdb-command:print padded_tuple.data_ptr[0] -// gdbg-check:$9 = {__0 = 6, __1 = 7} -// gdbr-check:$9 = (6, 7) +// gdb-check:$9 = (6, 7) // gdb-command:print padded_tuple.data_ptr[1] -// gdbg-check:$10 = {__0 = 8, __1 = 9} -// gdbr-check:$10 = (8, 9) +// gdb-check:$10 = (8, 9) // gdb-command:print padded_struct.length // gdb-check:$11 = 2 // gdb-command:print padded_struct.data_ptr[0] -// gdbg-check:$12 = {x = 10, y = 11, z = 12} -// gdbr-check:$12 = vec_slices::AStruct {x: 10, y: 11, z: 12} +// gdb-check:$12 = vec_slices::AStruct {x: 10, y: 11, z: 12} // gdb-command:print padded_struct.data_ptr[1] -// gdbg-check:$13 = {x = 13, y = 14, z = 15} -// gdbr-check:$13 = vec_slices::AStruct {x: 13, y: 14, z: 15} +// gdb-check:$13 = vec_slices::AStruct {x: 13, y: 14, z: 15} // gdb-command:print mut_slice.length // gdb-check:$14 = 5 -// gdbg-command:print *((i64[5]*)(mut_slice.data_ptr)) -// gdbr-command:print *(mut_slice.data_ptr as *const [i64; 5]) -// gdbg-check:$15 = {1, 2, 3, 4, 5} -// gdbr-check:$15 = [1, 2, 3, 4, 5] +// gdb-command:print *(mut_slice.data_ptr as *const [i64; 5]) +// gdb-check:$15 = [1, 2, 3, 4, 5] -// Some lines below are marked with [ignored] because old GDB versions seem to have trouble -// accessing globals. - -// [ignored] gdbg-command:print 'vec_slices::MUT_VECT_SLICE'.length -// gdbr-command:print MUT_VECT_SLICE.length -// [ignored] gdbg-check:$16 = 2 -// gdbr-check:$16 = 2 -// [ignored] gdbg-command:print *((i64[2]*)('vec_slices::MUT_VECT_SLICE'.data_ptr)) -// gdbr-command:print *(MUT_VECT_SLICE.data_ptr as *const [i64; 2]) -// [ignored] gdbg-check:$17 = {64, 65} -// gdbr-check:$17 = [64, 65] +// gdb-command:print MUT_VECT_SLICE.length +// gdb-check:$16 = 2 +// gdb-command:print *(MUT_VECT_SLICE.data_ptr as *const [i64; 2]) +// gdb-check:$17 = [64, 65] // === LLDB TESTS ================================================================================== // lldb-command:run // lldb-command:v empty -// lldbg-check:[...] size=0 -// lldbr-check:(&[i64]) empty = size=0 +// lldb-check:[...] size=0 // lldb-command:v singleton -// lldbg-check:[...] size=1 { [0] = 1 } -// lldbr-check:(&[i64]) singleton = &[1] +// lldb-check:[...] size=1 { [0] = 1 } // lldb-command:v multiple -// lldbg-check:[...] size=4 { [0] = 2 [1] = 3 [2] = 4 [3] = 5 } -// lldbr-check:(&[i64]) multiple = size=4 { [0] = 2 [1] = 3 [2] = 4 [3] = 5 } +// lldb-check:[...] size=4 { [0] = 2 [1] = 3 [2] = 4 [3] = 5 } // lldb-command:v slice_of_slice -// lldbg-check:[...] size=2 { [0] = 3 [1] = 4 } -// lldbr-check:(&[i64]) slice_of_slice = size=2 { [0] = 3 [1] = 4 } +// lldb-check:[...] size=2 { [0] = 3 [1] = 4 } // lldb-command:v padded_tuple -// lldbg-check:[...] size=2 { [0] = { 0 = 6 1 = 7 } [1] = { 0 = 8 1 = 9 } } -// lldbr-check:(&[(i32, i16)]) padded_tuple = size=2 { [0] = { 0 = 6 1 = 7 } [1] = { 0 = 8 1 = 9 } } +// lldb-check:[...] size=2 { [0] = { 0 = 6 1 = 7 } [1] = { 0 = 8 1 = 9 } } // lldb-command:v padded_struct -// lldbg-check:[...] size=2 { [0] = { x = 10 y = 11 z = 12 } [1] = { x = 13 y = 14 z = 15 } } -// lldbr-check:(&[vec_slices::AStruct]) padded_struct = size=2 { [0] = { x = 10 y = 11 z = 12 } [1] = { x = 13 y = 14 z = 15 } } +// lldb-check:[...] size=2 { [0] = { x = 10 y = 11 z = 12 } [1] = { x = 13 y = 14 z = 15 } } #![allow(dead_code, unused_variables)] #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/debuginfo/vec.rs b/tests/debuginfo/vec.rs index cf7de0b9b55..1093e38d878 100644 --- a/tests/debuginfo/vec.rs +++ b/tests/debuginfo/vec.rs @@ -1,25 +1,19 @@ -//@ min-lldb-version: 310 -//@ ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 - //@ compile-flags:-g // === GDB TESTS =================================================================================== // gdb-command:run // gdb-command:print a -// gdbg-check:$1 = {1, 2, 3} -// gdbr-check:$1 = [1, 2, 3] +// gdb-check:$1 = [1, 2, 3] // gdb-command:print vec::VECT -// gdbg-check:$2 = {4, 5, 6} -// gdbr-check:$2 = [4, 5, 6] +// gdb-check:$2 = [4, 5, 6] // === LLDB TESTS ================================================================================== // lldb-command:run // lldb-command:v a -// lldbg-check:[...] { [0] = 1 [1] = 2 [2] = 3 } -// lldbr-check:([i32; 3]) a = { [0] = 1 [1] = 2 [2] = 3 } +// lldb-check:[...] { [0] = 1 [1] = 2 [2] = 3 } #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/incremental/decl_macro.rs b/tests/incremental/decl_macro.rs new file mode 100644 index 00000000000..74810ae4227 --- /dev/null +++ b/tests/incremental/decl_macro.rs @@ -0,0 +1,34 @@ +//@ revisions: rpass1 rpass2 + +// issue#112680 + +#![feature(decl_macro)] + +pub trait T { + type Key; + fn index_from_key(key: Self::Key) -> usize; +} + +pub macro m($key_ty:ident, $val_ty:ident) { + struct $key_ty { + inner: usize, + } + + impl T for $val_ty { + type Key = $key_ty; + + fn index_from_key(key: Self::Key) -> usize { + key.inner + } + } +} + +m!(TestId, Test); + +#[cfg(rpass1)] +struct Test(u32); + +#[cfg(rpass2)] +struct Test; + +fn main() {} diff --git a/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir b/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir index cb72ad3d253..be636da4517 100644 --- a/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir @@ -140,7 +140,7 @@ fn address_of_reborrow() -> () { StorageLive(_6); _6 = &raw const (*_1); AscribeUserType(_6, o, UserTypeProjection { base: UserType(0), projs: [] }); - _5 = _6; + _5 = copy _6; StorageDead(_6); StorageDead(_5); StorageLive(_7); @@ -153,7 +153,7 @@ fn address_of_reborrow() -> () { _9 = move _10 as *const dyn std::marker::Send (PointerCoercion(Unsize)); StorageDead(_10); AscribeUserType(_9, o, UserTypeProjection { base: UserType(1), projs: [] }); - _8 = _9; + _8 = copy _9; StorageDead(_9); StorageDead(_8); StorageLive(_11); @@ -194,7 +194,7 @@ fn address_of_reborrow() -> () { StorageLive(_22); _22 = &raw const (*_3); AscribeUserType(_22, o, UserTypeProjection { base: UserType(10), projs: [] }); - _21 = _22; + _21 = copy _22; StorageDead(_22); StorageDead(_21); StorageLive(_23); @@ -207,7 +207,7 @@ fn address_of_reborrow() -> () { _25 = move _26 as *const dyn std::marker::Send (PointerCoercion(Unsize)); StorageDead(_26); AscribeUserType(_25, o, UserTypeProjection { base: UserType(11), projs: [] }); - _24 = _25; + _24 = copy _25; StorageDead(_25); StorageDead(_24); StorageLive(_27); @@ -242,7 +242,7 @@ fn address_of_reborrow() -> () { StorageLive(_36); _36 = &raw mut (*_3); AscribeUserType(_36, o, UserTypeProjection { base: UserType(20), projs: [] }); - _35 = _36; + _35 = copy _36; StorageDead(_36); StorageDead(_35); StorageLive(_37); @@ -255,7 +255,7 @@ fn address_of_reborrow() -> () { _39 = move _40 as *mut dyn std::marker::Send (PointerCoercion(Unsize)); StorageDead(_40); AscribeUserType(_39, o, UserTypeProjection { base: UserType(21), projs: [] }); - _38 = _39; + _38 = copy _39; StorageDead(_39); StorageDead(_38); StorageLive(_41); diff --git a/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.panic-abort.mir b/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.panic-abort.mir index ef51b07827f..a467987e886 100644 --- a/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.panic-abort.mir +++ b/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.panic-abort.mir @@ -33,17 +33,17 @@ fn main() -> () { StorageDead(_4); StorageLive(_5); StorageLive(_6); - _6 = _3; + _6 = copy _3; _5 = foo(move _6) -> [return: bb1, unwind unreachable]; } bb1: { StorageDead(_6); StorageLive(_7); - _7 = _2; + _7 = copy _2; _8 = Len(_1); - _9 = Lt(_7, _8); - assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, _7) -> [success: bb2, unwind unreachable]; + _9 = Lt(copy _7, copy _8); + assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, copy _7) -> [success: bb2, unwind unreachable]; } bb2: { diff --git a/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.panic-unwind.mir b/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.panic-unwind.mir index d1aa9382a2c..bd7365543bd 100644 --- a/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.panic-unwind.mir +++ b/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.panic-unwind.mir @@ -33,17 +33,17 @@ fn main() -> () { StorageDead(_4); StorageLive(_5); StorageLive(_6); - _6 = _3; + _6 = copy _3; _5 = foo(move _6) -> [return: bb1, unwind continue]; } bb1: { StorageDead(_6); StorageLive(_7); - _7 = _2; + _7 = copy _2; _8 = Len(_1); - _9 = Lt(_7, _8); - assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, _7) -> [success: bb2, unwind continue]; + _9 = Lt(copy _7, copy _8); + assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, copy _7) -> [success: bb2, unwind continue]; } bb2: { diff --git a/tests/mir-opt/array_index_is_temporary.rs b/tests/mir-opt/array_index_is_temporary.rs index 771fb3771b5..cda9e86b3e6 100644 --- a/tests/mir-opt/array_index_is_temporary.rs +++ b/tests/mir-opt/array_index_is_temporary.rs @@ -15,7 +15,7 @@ fn main() { // CHECK: debug x => [[x:_.*]]; // CHECK: debug y => [[y:_.*]]; // CHECK: [[y]] = const 1_usize; - // CHECK: [[tmp:_.*]] = [[y]]; + // CHECK: [[tmp:_.*]] = copy [[y]]; // CHECK: [[x]][[[tmp]]] = let mut x = [42, 43, 44]; let mut y = 1; diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.panic-abort.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.panic-abort.mir index 1c34955a8d9..1f5bb551b8e 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.panic-abort.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.panic-abort.mir @@ -22,7 +22,7 @@ yields () bb0: { StorageLive(_3); - _3 = (_1.0: i32); + _3 = copy (_1.0: i32); FakeRead(ForLet(None), _3); StorageLive(_4); _4 = &_3; diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.panic-unwind.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.panic-unwind.mir index 1c34955a8d9..1f5bb551b8e 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.panic-unwind.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.panic-unwind.mir @@ -22,7 +22,7 @@ yields () bb0: { StorageLive(_3); - _3 = (_1.0: i32); + _3 = copy (_1.0: i32); FakeRead(ForLet(None), _3); StorageLive(_4); _4 = &_3; diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.coroutine_by_move.0.panic-abort.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.coroutine_by_move.0.panic-abort.mir index 516908144a6..17fa9314806 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.coroutine_by_move.0.panic-abort.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.coroutine_by_move.0.panic-abort.mir @@ -22,7 +22,7 @@ yields () bb0: { StorageLive(_3); - _3 = (_1.0: i32); + _3 = copy (_1.0: i32); FakeRead(ForLet(None), _3); StorageLive(_4); _4 = &_3; diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.coroutine_by_move.0.panic-unwind.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.coroutine_by_move.0.panic-unwind.mir index 516908144a6..17fa9314806 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.coroutine_by_move.0.panic-unwind.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.coroutine_by_move.0.panic-unwind.mir @@ -22,7 +22,7 @@ yields () bb0: { StorageLive(_3); - _3 = (_1.0: i32); + _3 = copy (_1.0: i32); FakeRead(ForLet(None), _3); StorageLive(_4); _4 = &_3; diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-abort.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-abort.mir index ba20c28cd01..3fdc81791de 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-abort.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-abort.mir @@ -4,7 +4,7 @@ fn main::{closure#0}::{closure#1}(_1: &{async closure@$DIR/async_closure_shims.r let mut _0: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10}; bb0: { - _0 = {coroutine@$DIR/async_closure_shims.rs:62:48: 65:10 (#0)} { a: move _2, b: ((*_1).0: &i32) }; + _0 = {coroutine@$DIR/async_closure_shims.rs:62:48: 65:10 (#0)} { a: move _2, b: copy ((*_1).0: &i32) }; return; } } diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-unwind.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-unwind.mir index ba20c28cd01..3fdc81791de 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-unwind.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-unwind.mir @@ -4,7 +4,7 @@ fn main::{closure#0}::{closure#1}(_1: &{async closure@$DIR/async_closure_shims.r let mut _0: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10}; bb0: { - _0 = {coroutine@$DIR/async_closure_shims.rs:62:48: 65:10 (#0)} { a: move _2, b: ((*_1).0: &i32) }; + _0 = {coroutine@$DIR/async_closure_shims.rs:62:48: 65:10 (#0)} { a: move _2, b: copy ((*_1).0: &i32) }; return; } } diff --git a/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff b/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff index f187f959727..2d6adaca19e 100644 --- a/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff +++ b/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff @@ -27,7 +27,7 @@ _1 = const false; StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; _2 = move _3; StorageDead(_3); StorageLive(_4); diff --git a/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir b/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir index 5c0d1e9b93f..d4f0363e443 100644 --- a/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir @@ -31,7 +31,7 @@ fn main() -> () { FakeRead(ForLet(None), _1); StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; _2 = move _3; StorageDead(_3); StorageLive(_4); diff --git a/tests/mir-opt/box_expr.rs b/tests/mir-opt/box_expr.rs index a2d3ab94db6..41cd4ca57bf 100644 --- a/tests/mir-opt/box_expr.rs +++ b/tests/mir-opt/box_expr.rs @@ -7,7 +7,7 @@ fn main() { // CHECK-LABEL: fn main( // CHECK: [[box:_.*]] = ShallowInitBox( - // CHECK: [[ptr:_.*]] = ((([[box]].0: std::ptr::Unique).0: std::ptr::NonNull).0: *const S); + // CHECK: [[ptr:_.*]] = copy ((([[box]].0: std::ptr::Unique).0: std::ptr::NonNull).0: *const S); // CHECK: (*[[ptr]]) = S::new() -> [return: [[ret:bb.*]], unwind: [[unwind:bb.*]]]; // CHECK: [[ret]]: { // CHECK: [[box2:_.*]] = move [[box]]; diff --git a/tests/mir-opt/build_correct_coerce.main.built.after.mir b/tests/mir-opt/build_correct_coerce.main.built.after.mir new file mode 100644 index 00000000000..061174d69bb --- /dev/null +++ b/tests/mir-opt/build_correct_coerce.main.built.after.mir @@ -0,0 +1,18 @@ +// MIR for `main` after built + +fn main() -> () { + let mut _0: (); + let _1: for<'a> fn(&'a (), &'a ()); + scope 1 { + debug x => _1; + } + + bb0: { + StorageLive(_1); + _1 = foo as for<'a> fn(&'a (), &'a ()) (PointerCoercion(ReifyFnPointer)); + FakeRead(ForLet(None), _1); + _0 = const (); + StorageDead(_1); + return; + } +} diff --git a/tests/mir-opt/build_correct_coerce.rs b/tests/mir-opt/build_correct_coerce.rs new file mode 100644 index 00000000000..b6c861636dc --- /dev/null +++ b/tests/mir-opt/build_correct_coerce.rs @@ -0,0 +1,12 @@ +// skip-filecheck + +// Validate that we record the target for the `as` coercion as `for<'a> fn(&'a (), &'a ())`, +// and not `for<'a, 'b>(&'a (), &'b ())`. We previously did the latter due to a bug in +// the code that records adjustments in HIR typeck. + +fn foo<'a, 'b>(_: &'a (), _: &'b ()) {} + +// EMIT_MIR build_correct_coerce.main.built.after.mir +fn main() { + let x = foo as for<'a> fn(&'a (), &'a ()); +} diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir index c0f16ee7ec0..c1c2fdcfa94 100644 --- a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir +++ b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir @@ -151,7 +151,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> StorageLive(_13); StorageLive(_14); StorageLive(_15); - _15 = _38; + _15 = copy _38; _14 = move _15; goto -> bb6; } @@ -194,8 +194,8 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> bb10: { StorageLive(_17); - _17 = ((_9 as Ready).0: ()); - _3 = _17; + _17 = copy ((_9 as Ready).0: ()); + _3 = copy _17; StorageDead(_17); StorageDead(_14); StorageDead(_12); @@ -253,7 +253,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> StorageLive(_29); StorageLive(_30); StorageLive(_31); - _31 = _38; + _31 = copy _38; _30 = move _31; goto -> bb18; } @@ -291,8 +291,8 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> bb21: { StorageLive(_33); - _33 = ((_25 as Ready).0: ()); - _37 = _33; + _33 = copy ((_25 as Ready).0: ()); + _37 = copy _33; StorageDead(_33); StorageDead(_30); StorageDead(_28); diff --git a/tests/mir-opt/building/custom/aggregate_exprs.adt.built.after.mir b/tests/mir-opt/building/custom/aggregate_exprs.adt.built.after.mir index c14882142f5..6d4d261b895 100644 --- a/tests/mir-opt/building/custom/aggregate_exprs.adt.built.after.mir +++ b/tests/mir-opt/building/custom/aggregate_exprs.adt.built.after.mir @@ -9,8 +9,8 @@ fn adt() -> Onion { bb0: { _1 = const 1_i32; _2 = Foo { a: const 1_i32, b: const 2_i32 }; - _3 = Bar::Foo(move _2, _1); - _0 = Onion { neon: ((_3 as variant#0).1: i32) }; + _3 = Bar::Foo(move _2, copy _1); + _0 = Onion { neon: copy ((_3 as variant#0).1: i32) }; return; } } diff --git a/tests/mir-opt/building/custom/aggregate_exprs.array.built.after.mir b/tests/mir-opt/building/custom/aggregate_exprs.array.built.after.mir index fde007abab0..2c14258956a 100644 --- a/tests/mir-opt/building/custom/aggregate_exprs.array.built.after.mir +++ b/tests/mir-opt/building/custom/aggregate_exprs.array.built.after.mir @@ -8,7 +8,7 @@ fn array() -> [i32; 2] { bb0: { _1 = [const 42_i32, const 43_i32]; _2 = const 1_i32; - _1 = [_2, const 2_i32]; + _1 = [copy _2, const 2_i32]; _0 = move _1; return; } diff --git a/tests/mir-opt/building/custom/arbitrary_let.arbitrary_let.built.after.mir b/tests/mir-opt/building/custom/arbitrary_let.arbitrary_let.built.after.mir index 189996f1179..72a16b35885 100644 --- a/tests/mir-opt/building/custom/arbitrary_let.arbitrary_let.built.after.mir +++ b/tests/mir-opt/building/custom/arbitrary_let.arbitrary_let.built.after.mir @@ -6,17 +6,17 @@ fn arbitrary_let(_1: i32) -> i32 { let mut _3: i32; bb0: { - _2 = _1; + _2 = copy _1; goto -> bb2; } bb1: { - _0 = _3; + _0 = copy _3; return; } bb2: { - _3 = _2; + _3 = copy _2; goto -> bb1; } } diff --git a/tests/mir-opt/building/custom/arrays.arrays.built.after.mir b/tests/mir-opt/building/custom/arrays.arrays.built.after.mir index eaeba302f15..30d11e31e4d 100644 --- a/tests/mir-opt/building/custom/arrays.arrays.built.after.mir +++ b/tests/mir-opt/building/custom/arrays.arrays.built.after.mir @@ -8,7 +8,7 @@ fn arrays() -> usize { bb0: { _1 = [const 5_i32; C]; _2 = Len(_1); - _0 = _2; + _0 = copy _2; return; } } diff --git a/tests/mir-opt/building/custom/as_cast.float_to_int.built.after.mir b/tests/mir-opt/building/custom/as_cast.float_to_int.built.after.mir index e3334bc7dbe..93750719d27 100644 --- a/tests/mir-opt/building/custom/as_cast.float_to_int.built.after.mir +++ b/tests/mir-opt/building/custom/as_cast.float_to_int.built.after.mir @@ -4,7 +4,7 @@ fn float_to_int(_1: f32) -> i32 { let mut _0: i32; bb0: { - _0 = _1 as i32 (FloatToInt); + _0 = copy _1 as i32 (FloatToInt); return; } } diff --git a/tests/mir-opt/building/custom/as_cast.int_to_int.built.after.mir b/tests/mir-opt/building/custom/as_cast.int_to_int.built.after.mir index d71cb9d78d3..9adec45d64b 100644 --- a/tests/mir-opt/building/custom/as_cast.int_to_int.built.after.mir +++ b/tests/mir-opt/building/custom/as_cast.int_to_int.built.after.mir @@ -4,7 +4,7 @@ fn int_to_int(_1: u32) -> i32 { let mut _0: i32; bb0: { - _0 = _1 as i32 (IntToInt); + _0 = copy _1 as i32 (IntToInt); return; } } diff --git a/tests/mir-opt/building/custom/as_cast.int_to_ptr.built.after.mir b/tests/mir-opt/building/custom/as_cast.int_to_ptr.built.after.mir index faff79e8c57..aa642258095 100644 --- a/tests/mir-opt/building/custom/as_cast.int_to_ptr.built.after.mir +++ b/tests/mir-opt/building/custom/as_cast.int_to_ptr.built.after.mir @@ -4,7 +4,7 @@ fn int_to_ptr(_1: usize) -> *const i32 { let mut _0: *const i32; bb0: { - _0 = _1 as *const i32 (PointerWithExposedProvenance); + _0 = copy _1 as *const i32 (PointerWithExposedProvenance); return; } } diff --git a/tests/mir-opt/building/custom/assume.assume_local.built.after.mir b/tests/mir-opt/building/custom/assume.assume_local.built.after.mir index 7ea1fcd30c2..36e2859ce16 100644 --- a/tests/mir-opt/building/custom/assume.assume_local.built.after.mir +++ b/tests/mir-opt/building/custom/assume.assume_local.built.after.mir @@ -4,7 +4,7 @@ fn assume_local(_1: bool) -> () { let mut _0: (); bb0: { - assume(_1); + assume(copy _1); return; } } diff --git a/tests/mir-opt/building/custom/assume.assume_place.built.after.mir b/tests/mir-opt/building/custom/assume.assume_place.built.after.mir index ce914618d3d..074af333d63 100644 --- a/tests/mir-opt/building/custom/assume.assume_place.built.after.mir +++ b/tests/mir-opt/building/custom/assume.assume_place.built.after.mir @@ -4,7 +4,7 @@ fn assume_place(_1: (bool, u8)) -> () { let mut _0: (); bb0: { - assume((_1.0: bool)); + assume(copy (_1.0: bool)); return; } } diff --git a/tests/mir-opt/building/custom/enums.switch_bool.built.after.mir b/tests/mir-opt/building/custom/enums.switch_bool.built.after.mir index f82e5f1c6fd..beefef331df 100644 --- a/tests/mir-opt/building/custom/enums.switch_bool.built.after.mir +++ b/tests/mir-opt/building/custom/enums.switch_bool.built.after.mir @@ -4,7 +4,7 @@ fn switch_bool(_1: bool) -> u32 { let mut _0: u32; bb0: { - switchInt(_1) -> [1: bb1, 0: bb2, otherwise: bb2]; + switchInt(copy _1) -> [1: bb1, 0: bb2, otherwise: bb2]; } bb1: { diff --git a/tests/mir-opt/building/custom/enums.switch_option.built.after.mir b/tests/mir-opt/building/custom/enums.switch_option.built.after.mir index fa03f274be3..a854df87866 100644 --- a/tests/mir-opt/building/custom/enums.switch_option.built.after.mir +++ b/tests/mir-opt/building/custom/enums.switch_option.built.after.mir @@ -6,7 +6,7 @@ fn switch_option(_1: Option<()>) -> bool { bb0: { _2 = discriminant(_1); - switchInt(_2) -> [0: bb1, 1: bb2, otherwise: bb2]; + switchInt(copy _2) -> [0: bb1, 1: bb2, otherwise: bb2]; } bb1: { diff --git a/tests/mir-opt/building/custom/enums.switch_option_repr.built.after.mir b/tests/mir-opt/building/custom/enums.switch_option_repr.built.after.mir index eec2197a8bd..4ffc08772a8 100644 --- a/tests/mir-opt/building/custom/enums.switch_option_repr.built.after.mir +++ b/tests/mir-opt/building/custom/enums.switch_option_repr.built.after.mir @@ -6,7 +6,7 @@ fn switch_option_repr(_1: Bool) -> bool { bb0: { _2 = discriminant(_1); - switchInt(_2) -> [0: bb2, otherwise: bb1]; + switchInt(copy _2) -> [0: bb2, otherwise: bb1]; } bb1: { diff --git a/tests/mir-opt/building/custom/operators.f.built.after.mir b/tests/mir-opt/building/custom/operators.f.built.after.mir index cac82f7b3ea..ed6cddd548f 100644 --- a/tests/mir-opt/building/custom/operators.f.built.after.mir +++ b/tests/mir-opt/building/custom/operators.f.built.after.mir @@ -5,26 +5,26 @@ fn f(_1: i32, _2: bool) -> i32 { let mut _3: (i32, bool); bb0: { - _1 = Neg(_1); - _2 = Not(_2); - _1 = Add(_1, _1); - _1 = Sub(_1, _1); - _1 = Mul(_1, _1); - _1 = Div(_1, _1); - _1 = Rem(_1, _1); - _1 = BitXor(_1, _1); - _1 = BitAnd(_1, _1); - _1 = Shl(_1, _1); - _1 = Shr(_1, _1); - _2 = Eq(_1, _1); - _2 = Lt(_1, _1); - _2 = Le(_1, _1); - _2 = Ge(_1, _1); - _2 = Gt(_1, _1); - _3 = AddWithOverflow(_1, _1); - _2 = (_3.1: bool); - _1 = (_3.0: i32); - _0 = _1; + _1 = Neg(copy _1); + _2 = Not(copy _2); + _1 = Add(copy _1, copy _1); + _1 = Sub(copy _1, copy _1); + _1 = Mul(copy _1, copy _1); + _1 = Div(copy _1, copy _1); + _1 = Rem(copy _1, copy _1); + _1 = BitXor(copy _1, copy _1); + _1 = BitAnd(copy _1, copy _1); + _1 = Shl(copy _1, copy _1); + _1 = Shr(copy _1, copy _1); + _2 = Eq(copy _1, copy _1); + _2 = Lt(copy _1, copy _1); + _2 = Le(copy _1, copy _1); + _2 = Ge(copy _1, copy _1); + _2 = Gt(copy _1, copy _1); + _3 = AddWithOverflow(copy _1, copy _1); + _2 = copy (_3.1: bool); + _1 = copy (_3.0: i32); + _0 = copy _1; return; } } diff --git a/tests/mir-opt/building/custom/operators.g.runtime.after.mir b/tests/mir-opt/building/custom/operators.g.runtime.after.mir index a0ad7d0f93f..7d87fd93278 100644 --- a/tests/mir-opt/building/custom/operators.g.runtime.after.mir +++ b/tests/mir-opt/building/custom/operators.g.runtime.after.mir @@ -6,8 +6,8 @@ fn g(_1: *const i32, _2: *const [i32]) -> () { let mut _4: usize; bb0: { - _3 = PtrMetadata(_1); - _4 = PtrMetadata(_2); + _3 = PtrMetadata(copy _1); + _4 = PtrMetadata(copy _2); return; } } diff --git a/tests/mir-opt/building/custom/projections.copy_for_deref.built.after.mir b/tests/mir-opt/building/custom/projections.copy_for_deref.built.after.mir index b1ba5f9314d..b28e96f10ea 100644 --- a/tests/mir-opt/building/custom/projections.copy_for_deref.built.after.mir +++ b/tests/mir-opt/building/custom/projections.copy_for_deref.built.after.mir @@ -6,7 +6,7 @@ fn copy_for_deref(_1: (&i32, i32)) -> i32 { bb0: { _2 = deref_copy (_1.0: &i32); - _0 = (*_2); + _0 = copy (*_2); return; } } diff --git a/tests/mir-opt/building/custom/projections.simple_index.built.after.mir b/tests/mir-opt/building/custom/projections.simple_index.built.after.mir index f74c61009d3..2cd781696da 100644 --- a/tests/mir-opt/building/custom/projections.simple_index.built.after.mir +++ b/tests/mir-opt/building/custom/projections.simple_index.built.after.mir @@ -6,8 +6,8 @@ fn simple_index(_1: [i32; 10], _2: &[i32]) -> i32 { bb0: { _3 = const 3_usize; - _0 = _1[_3]; - _0 = (*_2)[_3]; + _0 = copy _1[_3]; + _0 = copy (*_2)[_3]; return; } } diff --git a/tests/mir-opt/building/custom/projections.tuples.built.after.mir b/tests/mir-opt/building/custom/projections.tuples.built.after.mir index a370de2ed84..d07269cd0d3 100644 --- a/tests/mir-opt/building/custom/projections.tuples.built.after.mir +++ b/tests/mir-opt/building/custom/projections.tuples.built.after.mir @@ -4,8 +4,8 @@ fn tuples(_1: (u32, i32)) -> (u32, i32) { let mut _0: (u32, i32); bb0: { - (_0.0: u32) = (_1.0: u32); - (_0.1: i32) = (_1.1: i32); + (_0.0: u32) = copy (_1.0: u32); + (_0.1: i32) = copy (_1.1: i32); return; } } diff --git a/tests/mir-opt/building/custom/projections.unions.built.after.mir b/tests/mir-opt/building/custom/projections.unions.built.after.mir index 4189b329e8c..fe4f7acebb5 100644 --- a/tests/mir-opt/building/custom/projections.unions.built.after.mir +++ b/tests/mir-opt/building/custom/projections.unions.built.after.mir @@ -4,7 +4,7 @@ fn unions(_1: U) -> i32 { let mut _0: i32; bb0: { - _0 = (_1.0: i32); + _0 = copy (_1.0: i32); return; } } diff --git a/tests/mir-opt/building/custom/projections.unwrap.built.after.mir b/tests/mir-opt/building/custom/projections.unwrap.built.after.mir index 0c43bdc9d24..ea706e0a97d 100644 --- a/tests/mir-opt/building/custom/projections.unwrap.built.after.mir +++ b/tests/mir-opt/building/custom/projections.unwrap.built.after.mir @@ -4,7 +4,7 @@ fn unwrap(_1: Option) -> i32 { let mut _0: i32; bb0: { - _0 = ((_1 as variant#1).0: i32); + _0 = copy ((_1 as variant#1).0: i32); return; } } diff --git a/tests/mir-opt/building/custom/projections.unwrap_deref.built.after.mir b/tests/mir-opt/building/custom/projections.unwrap_deref.built.after.mir index 39e97851343..eb83dcece3e 100644 --- a/tests/mir-opt/building/custom/projections.unwrap_deref.built.after.mir +++ b/tests/mir-opt/building/custom/projections.unwrap_deref.built.after.mir @@ -4,7 +4,7 @@ fn unwrap_deref(_1: Option<&i32>) -> i32 { let mut _0: i32; bb0: { - _0 = (*((_1 as variant#1).0: &i32)); + _0 = copy (*((_1 as variant#1).0: &i32)); return; } } diff --git a/tests/mir-opt/building/custom/references.raw_pointer_offset.built.after.mir b/tests/mir-opt/building/custom/references.raw_pointer_offset.built.after.mir index 8046b543eef..3893613bff9 100644 --- a/tests/mir-opt/building/custom/references.raw_pointer_offset.built.after.mir +++ b/tests/mir-opt/building/custom/references.raw_pointer_offset.built.after.mir @@ -4,7 +4,7 @@ fn raw_pointer_offset(_1: *const i32) -> *const i32 { let mut _0: *const i32; bb0: { - _0 = Offset(_1, const 1_isize); + _0 = Offset(copy _1, const 1_isize); return; } } diff --git a/tests/mir-opt/building/custom/simple_assign.simple.built.after.mir b/tests/mir-opt/building/custom/simple_assign.simple.built.after.mir index 6f7aaeed979..10ad840f98c 100644 --- a/tests/mir-opt/building/custom/simple_assign.simple.built.after.mir +++ b/tests/mir-opt/building/custom/simple_assign.simple.built.after.mir @@ -7,14 +7,14 @@ fn simple(_1: i32) -> i32 { bb0: { StorageLive(_2); - _2 = _1; + _2 = copy _1; goto -> bb1; } bb1: { _3 = move _2; StorageDead(_2); - _0 = _3; + _0 = copy _3; return; } } diff --git a/tests/mir-opt/building/custom/terminators.assert_nonzero.built.after.mir b/tests/mir-opt/building/custom/terminators.assert_nonzero.built.after.mir index 9cf26dff350..44030abc797 100644 --- a/tests/mir-opt/building/custom/terminators.assert_nonzero.built.after.mir +++ b/tests/mir-opt/building/custom/terminators.assert_nonzero.built.after.mir @@ -4,7 +4,7 @@ fn assert_nonzero(_1: i32) -> () { let mut _0: (); bb0: { - switchInt(_1) -> [0: bb1, otherwise: bb2]; + switchInt(copy _1) -> [0: bb1, otherwise: bb2]; } bb1: { diff --git a/tests/mir-opt/building/custom/terminators.direct_call.built.after.mir b/tests/mir-opt/building/custom/terminators.direct_call.built.after.mir index 07044ceaef4..b29d4ec7095 100644 --- a/tests/mir-opt/building/custom/terminators.direct_call.built.after.mir +++ b/tests/mir-opt/building/custom/terminators.direct_call.built.after.mir @@ -4,7 +4,7 @@ fn direct_call(_1: i32) -> i32 { let mut _0: i32; bb0: { - _0 = ident::(_1) -> [return: bb1, unwind continue]; + _0 = ident::(copy _1) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/building/custom/terminators.indirect_call.built.after.mir b/tests/mir-opt/building/custom/terminators.indirect_call.built.after.mir index 3b849354dcd..b88f6603026 100644 --- a/tests/mir-opt/building/custom/terminators.indirect_call.built.after.mir +++ b/tests/mir-opt/building/custom/terminators.indirect_call.built.after.mir @@ -4,7 +4,7 @@ fn indirect_call(_1: i32, _2: fn(i32) -> i32) -> i32 { let mut _0: i32; bb0: { - _0 = _2(_1) -> [return: bb1, unwind continue]; + _0 = copy _2(copy _1) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/building/custom/terminators.tail_call.built.after.mir b/tests/mir-opt/building/custom/terminators.tail_call.built.after.mir index 4cf6e459aa8..ab3925dae1c 100644 --- a/tests/mir-opt/building/custom/terminators.tail_call.built.after.mir +++ b/tests/mir-opt/building/custom/terminators.tail_call.built.after.mir @@ -5,7 +5,7 @@ fn tail_call(_1: i32) -> i32 { let mut _2: i32; bb0: { - _2 = Add(_1, const 42_i32); - tailcall ident::(Spanned { node: _2, span: $DIR/terminators.rs:32:28: 32:29 (#0) }); + _2 = Add(copy _1, const 42_i32); + tailcall ident::(Spanned { node: copy _2, span: $DIR/terminators.rs:32:28: 32:29 (#0) }); } } diff --git a/tests/mir-opt/building/enum_cast.bar.built.after.mir b/tests/mir-opt/building/enum_cast.bar.built.after.mir index 512c7321619..72d0cf5d1e8 100644 --- a/tests/mir-opt/building/enum_cast.bar.built.after.mir +++ b/tests/mir-opt/building/enum_cast.bar.built.after.mir @@ -12,8 +12,8 @@ fn bar(_1: Bar) -> usize { StorageLive(_2); _2 = move _1; _3 = discriminant(_2); - _4 = _3 as u8 (IntToInt); - _5 = Le(_4, const 1_u8); + _4 = copy _3 as u8 (IntToInt); + _5 = Le(copy _4, const 1_u8); assume(move _5); _0 = move _3 as usize (IntToInt); StorageDead(_2); diff --git a/tests/mir-opt/building/enum_cast.boo.built.after.mir b/tests/mir-opt/building/enum_cast.boo.built.after.mir index ad0adf14e4a..91e06dc8862 100644 --- a/tests/mir-opt/building/enum_cast.boo.built.after.mir +++ b/tests/mir-opt/building/enum_cast.boo.built.after.mir @@ -12,8 +12,8 @@ fn boo(_1: Boo) -> usize { StorageLive(_2); _2 = move _1; _3 = discriminant(_2); - _4 = _3 as u8 (IntToInt); - _5 = Le(_4, const 1_u8); + _4 = copy _3 as u8 (IntToInt); + _5 = Le(copy _4, const 1_u8); assume(move _5); _0 = move _3 as usize (IntToInt); StorageDead(_2); diff --git a/tests/mir-opt/building/enum_cast.droppy.built.after.mir b/tests/mir-opt/building/enum_cast.droppy.built.after.mir index ea0edb610f5..f53c9199a49 100644 --- a/tests/mir-opt/building/enum_cast.droppy.built.after.mir +++ b/tests/mir-opt/building/enum_cast.droppy.built.after.mir @@ -31,8 +31,8 @@ fn droppy() -> () { StorageLive(_4); _4 = move _2; _5 = discriminant(_4); - _6 = _5 as u8 (IntToInt); - _7 = Le(_6, const 2_u8); + _6 = copy _5 as u8 (IntToInt); + _7 = Le(copy _6, const 2_u8); assume(move _7); _3 = move _5 as usize (IntToInt); drop(_4) -> [return: bb1, unwind: bb4]; diff --git a/tests/mir-opt/building/enum_cast.far.built.after.mir b/tests/mir-opt/building/enum_cast.far.built.after.mir index e75803c706d..14eaf344190 100644 --- a/tests/mir-opt/building/enum_cast.far.built.after.mir +++ b/tests/mir-opt/building/enum_cast.far.built.after.mir @@ -12,8 +12,8 @@ fn far(_1: Far) -> isize { StorageLive(_2); _2 = move _1; _3 = discriminant(_2); - _4 = _3 as u16 (IntToInt); - _5 = Le(_4, const 1_u16); + _4 = copy _3 as u16 (IntToInt); + _5 = Le(copy _4, const 1_u16); assume(move _5); _0 = move _3 as isize (IntToInt); StorageDead(_2); diff --git a/tests/mir-opt/building/enum_cast.offsetty.built.after.mir b/tests/mir-opt/building/enum_cast.offsetty.built.after.mir index 282859d7cd0..1c2acbe3023 100644 --- a/tests/mir-opt/building/enum_cast.offsetty.built.after.mir +++ b/tests/mir-opt/building/enum_cast.offsetty.built.after.mir @@ -14,9 +14,9 @@ fn offsetty(_1: NotStartingAtZero) -> u32 { StorageLive(_2); _2 = move _1; _3 = discriminant(_2); - _4 = _3 as u8 (IntToInt); - _5 = Ge(_4, const 4_u8); - _6 = Le(_4, const 8_u8); + _4 = copy _3 as u8 (IntToInt); + _5 = Ge(copy _4, const 4_u8); + _6 = Le(copy _4, const 8_u8); _7 = BitAnd(move _5, move _6); assume(move _7); _0 = move _3 as u32 (IntToInt); diff --git a/tests/mir-opt/building/enum_cast.signy.built.after.mir b/tests/mir-opt/building/enum_cast.signy.built.after.mir index a9f7d6c7800..39b6dfaf005 100644 --- a/tests/mir-opt/building/enum_cast.signy.built.after.mir +++ b/tests/mir-opt/building/enum_cast.signy.built.after.mir @@ -14,9 +14,9 @@ fn signy(_1: SignedAroundZero) -> i16 { StorageLive(_2); _2 = move _1; _3 = discriminant(_2); - _4 = _3 as u16 (IntToInt); - _5 = Ge(_4, const 65534_u16); - _6 = Le(_4, const 2_u16); + _4 = copy _3 as u16 (IntToInt); + _5 = Ge(copy _4, const 65534_u16); + _6 = Le(copy _4, const 2_u16); _7 = BitOr(move _5, move _6); assume(move _7); _0 = move _3 as i16 (IntToInt); diff --git a/tests/mir-opt/building/eq_never_type._f.built.after.mir b/tests/mir-opt/building/eq_never_type._f.built.after.mir index 39438258c2e..4711af46f1c 100644 --- a/tests/mir-opt/building/eq_never_type._f.built.after.mir +++ b/tests/mir-opt/building/eq_never_type._f.built.after.mir @@ -16,7 +16,7 @@ fn _f(_1: !, _2: !) -> () { StorageLive(_4); StorageLive(_5); StorageLive(_6); - _6 = _1; + _6 = copy _1; unreachable; } @@ -25,7 +25,7 @@ fn _f(_1: !, _2: !) -> () { StorageLive(_7); StorageLive(_8); StorageLive(_9); - _9 = _2; + _9 = copy _2; unreachable; } diff --git a/tests/mir-opt/building/issue_101867.main.built.after.mir b/tests/mir-opt/building/issue_101867.main.built.after.mir index 5c50b3db5ca..34e5bedf4ce 100644 --- a/tests/mir-opt/building/issue_101867.main.built.after.mir +++ b/tests/mir-opt/building/issue_101867.main.built.after.mir @@ -55,7 +55,7 @@ fn main() -> () { } bb6: { - _5 = ((_1 as Some).0: u8); + _5 = copy ((_1 as Some).0: u8); _0 = const (); StorageDead(_5); StorageDead(_1); diff --git a/tests/mir-opt/building/issue_49232.main.built.after.mir b/tests/mir-opt/building/issue_49232.main.built.after.mir index d09a1748a8b..b78f6691d54 100644 --- a/tests/mir-opt/building/issue_49232.main.built.after.mir +++ b/tests/mir-opt/building/issue_49232.main.built.after.mir @@ -25,7 +25,7 @@ fn main() -> () { StorageLive(_3); _3 = const true; PlaceMention(_3); - switchInt(_3) -> [0: bb4, otherwise: bb6]; + switchInt(copy _3) -> [0: bb4, otherwise: bb6]; } bb3: { diff --git a/tests/mir-opt/building/logical_or_in_conditional.test_complex.built.after.mir b/tests/mir-opt/building/logical_or_in_conditional.test_complex.built.after.mir index 3e16efe6980..72bd4605b26 100644 --- a/tests/mir-opt/building/logical_or_in_conditional.test_complex.built.after.mir +++ b/tests/mir-opt/building/logical_or_in_conditional.test_complex.built.after.mir @@ -54,7 +54,7 @@ fn test_complex() -> () { StorageLive(_6); StorageLive(_7); _7 = Droppy(const 0_u8); - _6 = (_7.0: u8); + _6 = copy (_7.0: u8); _5 = Gt(move _6, const 0_u8); switchInt(move _5) -> [0: bb10, otherwise: bb9]; } @@ -92,7 +92,7 @@ fn test_complex() -> () { StorageLive(_9); StorageLive(_10); _10 = Droppy(const 1_u8); - _9 = (_10.0: u8); + _9 = copy (_10.0: u8); _8 = Gt(move _9, const 1_u8); switchInt(move _8) -> [0: bb16, otherwise: bb15]; } diff --git a/tests/mir-opt/building/logical_or_in_conditional.test_or.built.after.mir b/tests/mir-opt/building/logical_or_in_conditional.test_or.built.after.mir index 3e7c116016c..2fc19e7e0fd 100644 --- a/tests/mir-opt/building/logical_or_in_conditional.test_or.built.after.mir +++ b/tests/mir-opt/building/logical_or_in_conditional.test_or.built.after.mir @@ -14,7 +14,7 @@ fn test_or() -> () { StorageLive(_2); StorageLive(_3); _3 = Droppy(const 0_u8); - _2 = (_3.0: u8); + _2 = copy (_3.0: u8); _1 = Gt(move _2, const 0_u8); switchInt(move _1) -> [0: bb2, otherwise: bb1]; } @@ -44,7 +44,7 @@ fn test_or() -> () { StorageLive(_5); StorageLive(_6); _6 = Droppy(const 1_u8); - _5 = (_6.0: u8); + _5 = copy (_6.0: u8); _4 = Gt(move _5, const 1_u8); switchInt(move _4) -> [0: bb7, otherwise: bb6]; } diff --git a/tests/mir-opt/building/match/deref-patterns/string.foo.PreCodegen.after.mir b/tests/mir-opt/building/match/deref-patterns/string.foo.PreCodegen.after.mir index 1e4f7485089..9f52a8cd1e5 100644 --- a/tests/mir-opt/building/match/deref-patterns/string.foo.PreCodegen.after.mir +++ b/tests/mir-opt/building/match/deref-patterns/string.foo.PreCodegen.after.mir @@ -26,7 +26,7 @@ fn foo(_1: Option) -> i32 { } bb2: { - _6 = ::eq(_5, const "a") -> [return: bb3, unwind unreachable]; + _6 = ::eq(copy _5, const "a") -> [return: bb3, unwind unreachable]; } bb3: { @@ -52,7 +52,7 @@ fn foo(_1: Option) -> i32 { } bb7: { - switchInt(_2) -> [0: bb9, otherwise: bb8]; + switchInt(copy _2) -> [0: bb9, otherwise: bb8]; } bb8: { diff --git a/tests/mir-opt/building/match/exponential_or.match_tuple.SimplifyCfg-initial.after.mir b/tests/mir-opt/building/match/exponential_or.match_tuple.SimplifyCfg-initial.after.mir index 596dcef85fd..d52241b459e 100644 --- a/tests/mir-opt/building/match/exponential_or.match_tuple.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/building/match/exponential_or.match_tuple.SimplifyCfg-initial.after.mir @@ -19,7 +19,7 @@ fn match_tuple(_1: (u32, bool, Option, u32)) -> u32 { bb0: { PlaceMention(_1); - switchInt((_1.0: u32)) -> [1: bb2, 4: bb2, otherwise: bb1]; + switchInt(copy (_1.0: u32)) -> [1: bb2, 4: bb2, otherwise: bb1]; } bb1: { @@ -33,26 +33,26 @@ fn match_tuple(_1: (u32, bool, Option, u32)) -> u32 { } bb3: { - switchInt((((_1.2: std::option::Option) as Some).0: i32)) -> [1: bb4, 8: bb4, otherwise: bb1]; + switchInt(copy (((_1.2: std::option::Option) as Some).0: i32)) -> [1: bb4, 8: bb4, otherwise: bb1]; } bb4: { - _5 = Le(const 6_u32, (_1.3: u32)); + _5 = Le(const 6_u32, copy (_1.3: u32)); switchInt(move _5) -> [0: bb5, otherwise: bb7]; } bb5: { - _3 = Le(const 13_u32, (_1.3: u32)); + _3 = Le(const 13_u32, copy (_1.3: u32)); switchInt(move _3) -> [0: bb1, otherwise: bb6]; } bb6: { - _4 = Le((_1.3: u32), const 16_u32); + _4 = Le(copy (_1.3: u32), const 16_u32); switchInt(move _4) -> [0: bb1, otherwise: bb8]; } bb7: { - _6 = Le((_1.3: u32), const 9_u32); + _6 = Le(copy (_1.3: u32), const 9_u32); switchInt(move _6) -> [0: bb5, otherwise: bb8]; } @@ -62,13 +62,13 @@ fn match_tuple(_1: (u32, bool, Option, u32)) -> u32 { bb9: { StorageLive(_7); - _7 = (_1.0: u32); + _7 = copy (_1.0: u32); StorageLive(_8); - _8 = (_1.3: u32); + _8 = copy (_1.3: u32); StorageLive(_9); - _9 = _7; + _9 = copy _7; StorageLive(_10); - _10 = _8; + _10 = copy _8; _0 = BitXor(move _9, move _10); StorageDead(_10); StorageDead(_9); diff --git a/tests/mir-opt/building/match/match_false_edges.full_tested_match.built.after.mir b/tests/mir-opt/building/match/match_false_edges.full_tested_match.built.after.mir index a93743edfac..4b0cdcfbb86 100644 --- a/tests/mir-opt/building/match/match_false_edges.full_tested_match.built.after.mir +++ b/tests/mir-opt/building/match/match_false_edges.full_tested_match.built.after.mir @@ -59,9 +59,9 @@ fn full_tested_match() -> () { bb7: { StorageLive(_9); - _9 = ((_2 as Some).0: i32); + _9 = copy ((_2 as Some).0: i32); StorageLive(_10); - _10 = _9; + _10 = copy _9; _1 = (const 2_i32, move _10); StorageDead(_10); StorageDead(_9); @@ -89,9 +89,9 @@ fn full_tested_match() -> () { FakeRead(ForMatchGuard, _3); FakeRead(ForGuardBinding, _6); StorageLive(_5); - _5 = ((_2 as Some).0: i32); + _5 = copy ((_2 as Some).0: i32); StorageLive(_8); - _8 = _5; + _8 = copy _5; _1 = (const 1_i32, move _8); StorageDead(_8); StorageDead(_5); diff --git a/tests/mir-opt/building/match/match_false_edges.full_tested_match2.built.after.mir b/tests/mir-opt/building/match/match_false_edges.full_tested_match2.built.after.mir index 0d0ea2be1b0..63ec71fdf51 100644 --- a/tests/mir-opt/building/match/match_false_edges.full_tested_match2.built.after.mir +++ b/tests/mir-opt/building/match/match_false_edges.full_tested_match2.built.after.mir @@ -42,9 +42,9 @@ fn full_tested_match2() -> () { bb3: { StorageLive(_9); - _9 = ((_2 as Some).0: i32); + _9 = copy ((_2 as Some).0: i32); StorageLive(_10); - _10 = _9; + _10 = copy _9; _1 = (const 2_i32, move _10); StorageDead(_10); StorageDead(_9); @@ -89,9 +89,9 @@ fn full_tested_match2() -> () { FakeRead(ForMatchGuard, _3); FakeRead(ForGuardBinding, _6); StorageLive(_5); - _5 = ((_2 as Some).0: i32); + _5 = copy ((_2 as Some).0: i32); StorageLive(_8); - _8 = _5; + _8 = copy _5; _1 = (const 1_i32, move _8); StorageDead(_8); StorageDead(_5); diff --git a/tests/mir-opt/building/match/match_false_edges.main.built.after.mir b/tests/mir-opt/building/match/match_false_edges.main.built.after.mir index 87b7e29848f..3b10adb499c 100644 --- a/tests/mir-opt/building/match/match_false_edges.main.built.after.mir +++ b/tests/mir-opt/building/match/match_false_edges.main.built.after.mir @@ -61,7 +61,7 @@ fn main() -> () { bb5: { StorageLive(_14); - _14 = _2; + _14 = copy _2; _1 = const 4_i32; StorageDead(_14); goto -> bb22; @@ -86,7 +86,7 @@ fn main() -> () { _3 = &fake shallow _2; StorageLive(_12); StorageLive(_13); - _13 = (*_11); + _13 = copy (*_11); _12 = guard2(move _13) -> [return: bb18, unwind: bb24]; } @@ -96,7 +96,7 @@ fn main() -> () { bb11: { StorageLive(_9); - _9 = _2; + _9 = copy _2; _1 = const 2_i32; StorageDead(_9); goto -> bb22; @@ -123,7 +123,7 @@ fn main() -> () { FakeRead(ForMatchGuard, _3); FakeRead(ForGuardBinding, _7); StorageLive(_6); - _6 = ((_2 as Some).0: i32); + _6 = copy ((_2 as Some).0: i32); _1 = const 1_i32; StorageDead(_6); StorageDead(_7); @@ -150,7 +150,7 @@ fn main() -> () { FakeRead(ForMatchGuard, _3); FakeRead(ForGuardBinding, _11); StorageLive(_10); - _10 = ((_2 as Some).0: i32); + _10 = copy ((_2 as Some).0: i32); _1 = const 3_i32; StorageDead(_10); StorageDead(_11); diff --git a/tests/mir-opt/building/match/simple_match.match_bool.built.after.mir b/tests/mir-opt/building/match/simple_match.match_bool.built.after.mir index b0ebdc37b06..0e82d9591a6 100644 --- a/tests/mir-opt/building/match/simple_match.match_bool.built.after.mir +++ b/tests/mir-opt/building/match/simple_match.match_bool.built.after.mir @@ -6,7 +6,7 @@ fn match_bool(_1: bool) -> usize { bb0: { PlaceMention(_1); - switchInt(_1) -> [0: bb1, otherwise: bb2]; + switchInt(copy _1) -> [0: bb1, otherwise: bb2]; } bb1: { diff --git a/tests/mir-opt/building/match/sort_candidates.constant_eq.SimplifyCfg-initial.after.mir b/tests/mir-opt/building/match/sort_candidates.constant_eq.SimplifyCfg-initial.after.mir index 2bce79a3ae7..b8f54fef0fa 100644 --- a/tests/mir-opt/building/match/sort_candidates.constant_eq.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/building/match/sort_candidates.constant_eq.SimplifyCfg-initial.after.mir @@ -16,18 +16,18 @@ fn constant_eq(_1: &str, _2: bool) -> u32 { bb0: { StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; StorageLive(_5); - _5 = _2; + _5 = copy _2; _3 = (move _4, move _5); StorageDead(_5); StorageDead(_4); PlaceMention(_3); - _9 = ::eq((_3.0: &str), const "a") -> [return: bb9, unwind: bb19]; + _9 = ::eq(copy (_3.0: &str), const "a") -> [return: bb9, unwind: bb19]; } bb1: { - switchInt((_3.1: bool)) -> [0: bb10, otherwise: bb11]; + switchInt(copy (_3.1: bool)) -> [0: bb10, otherwise: bb11]; } bb2: { @@ -35,7 +35,7 @@ fn constant_eq(_1: &str, _2: bool) -> u32 { } bb3: { - switchInt((_3.1: bool)) -> [0: bb1, otherwise: bb4]; + switchInt(copy (_3.1: bool)) -> [0: bb1, otherwise: bb4]; } bb4: { @@ -43,11 +43,11 @@ fn constant_eq(_1: &str, _2: bool) -> u32 { } bb5: { - _8 = ::eq((_3.0: &str), const "b") -> [return: bb8, unwind: bb19]; + _8 = ::eq(copy (_3.0: &str), const "b") -> [return: bb8, unwind: bb19]; } bb6: { - switchInt((_3.1: bool)) -> [0: bb1, otherwise: bb7]; + switchInt(copy (_3.1: bool)) -> [0: bb1, otherwise: bb7]; } bb7: { diff --git a/tests/mir-opt/building/match/sort_candidates.disjoint_ranges.SimplifyCfg-initial.after.mir b/tests/mir-opt/building/match/sort_candidates.disjoint_ranges.SimplifyCfg-initial.after.mir index e521fb4509a..d6251680814 100644 --- a/tests/mir-opt/building/match/sort_candidates.disjoint_ranges.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/building/match/sort_candidates.disjoint_ranges.SimplifyCfg-initial.after.mir @@ -13,7 +13,7 @@ fn disjoint_ranges(_1: i32, _2: bool) -> u32 { bb0: { PlaceMention(_1); - _6 = Le(const 0_i32, _1); + _6 = Le(const 0_i32, copy _1); switchInt(move _6) -> [0: bb3, otherwise: bb8]; } @@ -27,7 +27,7 @@ fn disjoint_ranges(_1: i32, _2: bool) -> u32 { } bb3: { - _4 = Le(const 10_i32, _1); + _4 = Le(const 10_i32, copy _1); switchInt(move _4) -> [0: bb5, otherwise: bb7]; } @@ -36,7 +36,7 @@ fn disjoint_ranges(_1: i32, _2: bool) -> u32 { } bb5: { - switchInt(_1) -> [4294967295: bb6, otherwise: bb1]; + switchInt(copy _1) -> [4294967295: bb6, otherwise: bb1]; } bb6: { @@ -44,12 +44,12 @@ fn disjoint_ranges(_1: i32, _2: bool) -> u32 { } bb7: { - _5 = Le(_1, const 20_i32); + _5 = Le(copy _1, const 20_i32); switchInt(move _5) -> [0: bb5, otherwise: bb4]; } bb8: { - _7 = Lt(_1, const 10_i32); + _7 = Lt(copy _1, const 10_i32); switchInt(move _7) -> [0: bb3, otherwise: bb2]; } @@ -66,7 +66,7 @@ fn disjoint_ranges(_1: i32, _2: bool) -> u32 { bb11: { _3 = &fake shallow _1; StorageLive(_8); - _8 = _2; + _8 = copy _2; switchInt(move _8) -> [0: bb13, otherwise: bb12]; } diff --git a/tests/mir-opt/building/match/sort_candidates.rs b/tests/mir-opt/building/match/sort_candidates.rs index 593a975a7a4..d7dd82791ff 100644 --- a/tests/mir-opt/building/match/sort_candidates.rs +++ b/tests/mir-opt/building/match/sort_candidates.rs @@ -25,7 +25,7 @@ fn disjoint_ranges(x: i32, b: bool) -> u32 { // CHECK-LABEL: fn disjoint_ranges( // CHECK: debug b => _2; // CHECK: bb0: { - // CHECK: switchInt(_2) -> [0: [[jump:bb.*]], otherwise: {{bb.*}}]; + // CHECK: switchInt(copy _2) -> [0: [[jump:bb.*]], otherwise: {{bb.*}}]; // CHECK: [[jump]]: { // CHECK-NEXT: _0 = const 3_u32; // CHECK-NEXT: return; diff --git a/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir b/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir index 1855bb0787d..296d71a319d 100644 --- a/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir +++ b/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir @@ -38,7 +38,7 @@ fn main() -> () { StorageLive(_2); StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; _3 = move _4 as *const Test (PointerCoercion(MutToConstPointer)); StorageDead(_4); _2 = Test::x(move _3) -> [return: bb2, unwind: bb4]; @@ -63,7 +63,7 @@ fn main() -> () { StorageLive(_10); StorageLive(_11); StorageLive(_12); - _12 = (*(*(*(*_5)))); + _12 = copy (*(*(*(*_5)))); _11 = move _12 as *const Test (PointerCoercion(MutToConstPointer)); StorageDead(_12); _10 = Test::x(move _11) -> [return: bb3, unwind: bb4]; diff --git a/tests/mir-opt/building/shifts.shift_signed.built.after.mir b/tests/mir-opt/building/shifts.shift_signed.built.after.mir index 8706ee9d446..65e2db300cd 100644 --- a/tests/mir-opt/building/shifts.shift_signed.built.after.mir +++ b/tests/mir-opt/building/shifts.shift_signed.built.after.mir @@ -44,12 +44,12 @@ fn shift_signed(_1: i8, _2: u128, _3: i8, _4: i32, _5: i128) -> ([i8; 3], [u128; StorageLive(_6); StorageLive(_7); StorageLive(_8); - _8 = _1; + _8 = copy _1; StorageLive(_9); - _9 = _3; - _10 = _9 as u8 (IntToInt); + _9 = copy _3; + _10 = copy _9 as u8 (IntToInt); _11 = Lt(move _10, const 8_u8); - assert(move _11, "attempt to shift right by `{}`, which would overflow", _9) -> [success: bb1, unwind: bb7]; + assert(move _11, "attempt to shift right by `{}`, which would overflow", copy _9) -> [success: bb1, unwind: bb7]; } bb1: { @@ -58,12 +58,12 @@ fn shift_signed(_1: i8, _2: u128, _3: i8, _4: i32, _5: i128) -> ([i8; 3], [u128; StorageDead(_8); StorageLive(_12); StorageLive(_13); - _13 = _1; + _13 = copy _1; StorageLive(_14); - _14 = _4; - _15 = _14 as u32 (IntToInt); + _14 = copy _4; + _15 = copy _14 as u32 (IntToInt); _16 = Lt(move _15, const 8_u32); - assert(move _16, "attempt to shift right by `{}`, which would overflow", _14) -> [success: bb2, unwind: bb7]; + assert(move _16, "attempt to shift right by `{}`, which would overflow", copy _14) -> [success: bb2, unwind: bb7]; } bb2: { @@ -72,12 +72,12 @@ fn shift_signed(_1: i8, _2: u128, _3: i8, _4: i32, _5: i128) -> ([i8; 3], [u128; StorageDead(_13); StorageLive(_17); StorageLive(_18); - _18 = _1; + _18 = copy _1; StorageLive(_19); - _19 = _5; - _20 = _19 as u128 (IntToInt); + _19 = copy _5; + _20 = copy _19 as u128 (IntToInt); _21 = Lt(move _20, const 8_u128); - assert(move _21, "attempt to shift right by `{}`, which would overflow", _19) -> [success: bb3, unwind: bb7]; + assert(move _21, "attempt to shift right by `{}`, which would overflow", copy _19) -> [success: bb3, unwind: bb7]; } bb3: { @@ -91,12 +91,12 @@ fn shift_signed(_1: i8, _2: u128, _3: i8, _4: i32, _5: i128) -> ([i8; 3], [u128; StorageLive(_22); StorageLive(_23); StorageLive(_24); - _24 = _2; + _24 = copy _2; StorageLive(_25); - _25 = _3; - _26 = _25 as u8 (IntToInt); + _25 = copy _3; + _26 = copy _25 as u8 (IntToInt); _27 = Lt(move _26, const 128_u8); - assert(move _27, "attempt to shift left by `{}`, which would overflow", _25) -> [success: bb4, unwind: bb7]; + assert(move _27, "attempt to shift left by `{}`, which would overflow", copy _25) -> [success: bb4, unwind: bb7]; } bb4: { @@ -105,12 +105,12 @@ fn shift_signed(_1: i8, _2: u128, _3: i8, _4: i32, _5: i128) -> ([i8; 3], [u128; StorageDead(_24); StorageLive(_28); StorageLive(_29); - _29 = _2; + _29 = copy _2; StorageLive(_30); - _30 = _4; - _31 = _30 as u32 (IntToInt); + _30 = copy _4; + _31 = copy _30 as u32 (IntToInt); _32 = Lt(move _31, const 128_u32); - assert(move _32, "attempt to shift left by `{}`, which would overflow", _30) -> [success: bb5, unwind: bb7]; + assert(move _32, "attempt to shift left by `{}`, which would overflow", copy _30) -> [success: bb5, unwind: bb7]; } bb5: { @@ -119,12 +119,12 @@ fn shift_signed(_1: i8, _2: u128, _3: i8, _4: i32, _5: i128) -> ([i8; 3], [u128; StorageDead(_29); StorageLive(_33); StorageLive(_34); - _34 = _2; + _34 = copy _2; StorageLive(_35); - _35 = _5; - _36 = _35 as u128 (IntToInt); + _35 = copy _5; + _36 = copy _35 as u128 (IntToInt); _37 = Lt(move _36, const 128_u128); - assert(move _37, "attempt to shift left by `{}`, which would overflow", _35) -> [success: bb6, unwind: bb7]; + assert(move _37, "attempt to shift left by `{}`, which would overflow", copy _35) -> [success: bb6, unwind: bb7]; } bb6: { diff --git a/tests/mir-opt/building/shifts.shift_unsigned.built.after.mir b/tests/mir-opt/building/shifts.shift_unsigned.built.after.mir index dfd3b5b35ad..62536833e49 100644 --- a/tests/mir-opt/building/shifts.shift_unsigned.built.after.mir +++ b/tests/mir-opt/building/shifts.shift_unsigned.built.after.mir @@ -38,11 +38,11 @@ fn shift_unsigned(_1: u8, _2: i128, _3: u8, _4: u32, _5: u128) -> ([u8; 3], [i12 StorageLive(_6); StorageLive(_7); StorageLive(_8); - _8 = _1; + _8 = copy _1; StorageLive(_9); - _9 = _3; - _10 = Lt(_9, const 8_u8); - assert(move _10, "attempt to shift right by `{}`, which would overflow", _9) -> [success: bb1, unwind: bb7]; + _9 = copy _3; + _10 = Lt(copy _9, const 8_u8); + assert(move _10, "attempt to shift right by `{}`, which would overflow", copy _9) -> [success: bb1, unwind: bb7]; } bb1: { @@ -51,11 +51,11 @@ fn shift_unsigned(_1: u8, _2: i128, _3: u8, _4: u32, _5: u128) -> ([u8; 3], [i12 StorageDead(_8); StorageLive(_11); StorageLive(_12); - _12 = _1; + _12 = copy _1; StorageLive(_13); - _13 = _4; - _14 = Lt(_13, const 8_u32); - assert(move _14, "attempt to shift right by `{}`, which would overflow", _13) -> [success: bb2, unwind: bb7]; + _13 = copy _4; + _14 = Lt(copy _13, const 8_u32); + assert(move _14, "attempt to shift right by `{}`, which would overflow", copy _13) -> [success: bb2, unwind: bb7]; } bb2: { @@ -64,11 +64,11 @@ fn shift_unsigned(_1: u8, _2: i128, _3: u8, _4: u32, _5: u128) -> ([u8; 3], [i12 StorageDead(_12); StorageLive(_15); StorageLive(_16); - _16 = _1; + _16 = copy _1; StorageLive(_17); - _17 = _5; - _18 = Lt(_17, const 8_u128); - assert(move _18, "attempt to shift right by `{}`, which would overflow", _17) -> [success: bb3, unwind: bb7]; + _17 = copy _5; + _18 = Lt(copy _17, const 8_u128); + assert(move _18, "attempt to shift right by `{}`, which would overflow", copy _17) -> [success: bb3, unwind: bb7]; } bb3: { @@ -82,11 +82,11 @@ fn shift_unsigned(_1: u8, _2: i128, _3: u8, _4: u32, _5: u128) -> ([u8; 3], [i12 StorageLive(_19); StorageLive(_20); StorageLive(_21); - _21 = _2; + _21 = copy _2; StorageLive(_22); - _22 = _3; - _23 = Lt(_22, const 128_u8); - assert(move _23, "attempt to shift left by `{}`, which would overflow", _22) -> [success: bb4, unwind: bb7]; + _22 = copy _3; + _23 = Lt(copy _22, const 128_u8); + assert(move _23, "attempt to shift left by `{}`, which would overflow", copy _22) -> [success: bb4, unwind: bb7]; } bb4: { @@ -95,11 +95,11 @@ fn shift_unsigned(_1: u8, _2: i128, _3: u8, _4: u32, _5: u128) -> ([u8; 3], [i12 StorageDead(_21); StorageLive(_24); StorageLive(_25); - _25 = _2; + _25 = copy _2; StorageLive(_26); - _26 = _4; - _27 = Lt(_26, const 128_u32); - assert(move _27, "attempt to shift left by `{}`, which would overflow", _26) -> [success: bb5, unwind: bb7]; + _26 = copy _4; + _27 = Lt(copy _26, const 128_u32); + assert(move _27, "attempt to shift left by `{}`, which would overflow", copy _26) -> [success: bb5, unwind: bb7]; } bb5: { @@ -108,11 +108,11 @@ fn shift_unsigned(_1: u8, _2: i128, _3: u8, _4: u32, _5: u128) -> ([u8; 3], [i12 StorageDead(_25); StorageLive(_28); StorageLive(_29); - _29 = _2; + _29 = copy _2; StorageLive(_30); - _30 = _5; - _31 = Lt(_30, const 128_u128); - assert(move _31, "attempt to shift left by `{}`, which would overflow", _30) -> [success: bb6, unwind: bb7]; + _30 = copy _5; + _31 = Lt(copy _30, const 128_u128); + assert(move _31, "attempt to shift left by `{}`, which would overflow", copy _30) -> [success: bb6, unwind: bb7]; } bb6: { diff --git a/tests/mir-opt/building/while_storage.rs b/tests/mir-opt/building/while_storage.rs index 83095316f00..cd226eb0c1e 100644 --- a/tests/mir-opt/building/while_storage.rs +++ b/tests/mir-opt/building/while_storage.rs @@ -15,7 +15,7 @@ fn while_loop(c: bool) { // CHECK: bb1: { // CHECK-NEXT: StorageLive(_3); // CHECK-NEXT: StorageLive(_2); - // CHECK-NEXT: _2 = _1; + // CHECK-NEXT: _2 = copy _1; // CHECK-NEXT: _3 = get_bool(move _2) -> [return: bb2, unwind // CHECK: bb2: { // CHECK-NEXT: switchInt(move _3) -> [0: bb3, otherwise: bb4]; @@ -29,7 +29,7 @@ fn while_loop(c: bool) { // CHECK-NEXT: StorageDead(_2); // CHECK-NEXT: StorageLive(_5); // CHECK-NEXT: StorageLive(_4); - // CHECK-NEXT: _4 = _1; + // CHECK-NEXT: _4 = copy _1; // CHECK-NEXT: _5 = get_bool(move _4) -> [return: bb5, unwind // CHECK: bb5: { // CHECK-NEXT: switchInt(move _5) -> [0: bb6, otherwise: bb7]; diff --git a/tests/mir-opt/building/while_storage.while_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/building/while_storage.while_loop.PreCodegen.after.panic-abort.mir index 26c82edf2d5..44a8b7342b2 100644 --- a/tests/mir-opt/building/while_storage.while_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/building/while_storage.while_loop.PreCodegen.after.panic-abort.mir @@ -20,7 +20,7 @@ fn while_loop(_1: bool) -> () { bb1: { StorageLive(_3); StorageLive(_2); - _2 = _1; + _2 = copy _1; _3 = get_bool(move _2) -> [return: bb2, unwind unreachable]; } @@ -40,7 +40,7 @@ fn while_loop(_1: bool) -> () { StorageDead(_2); StorageLive(_5); StorageLive(_4); - _4 = _1; + _4 = copy _1; _5 = get_bool(move _4) -> [return: bb5, unwind unreachable]; } diff --git a/tests/mir-opt/building/while_storage.while_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/building/while_storage.while_loop.PreCodegen.after.panic-unwind.mir index 1bb72074846..9a640300674 100644 --- a/tests/mir-opt/building/while_storage.while_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/building/while_storage.while_loop.PreCodegen.after.panic-unwind.mir @@ -20,7 +20,7 @@ fn while_loop(_1: bool) -> () { bb1: { StorageLive(_3); StorageLive(_2); - _2 = _1; + _2 = copy _1; _3 = get_bool(move _2) -> [return: bb2, unwind continue]; } @@ -40,7 +40,7 @@ fn while_loop(_1: bool) -> () { StorageDead(_2); StorageLive(_5); StorageLive(_4); - _4 = _1; + _4 = copy _1; _5 = get_bool(move _4) -> [return: bb5, unwind continue]; } diff --git a/tests/mir-opt/const_allocation.main.GVN.after.32bit.mir b/tests/mir-opt/const_allocation.main.GVN.after.32bit.mir index 10d99a13463..a2bd2bc0d92 100644 --- a/tests/mir-opt/const_allocation.main.GVN.after.32bit.mir +++ b/tests/mir-opt/const_allocation.main.GVN.after.32bit.mir @@ -9,7 +9,7 @@ fn main() -> () { StorageLive(_1); StorageLive(_2); _2 = const {ALLOC9: &&[(Option, &[&str])]}; - _1 = (*_2); + _1 = copy (*_2); StorageDead(_2); StorageDead(_1); _0 = const (); diff --git a/tests/mir-opt/const_allocation.main.GVN.after.64bit.mir b/tests/mir-opt/const_allocation.main.GVN.after.64bit.mir index 2f23dbe9ee4..a431104d08b 100644 --- a/tests/mir-opt/const_allocation.main.GVN.after.64bit.mir +++ b/tests/mir-opt/const_allocation.main.GVN.after.64bit.mir @@ -9,7 +9,7 @@ fn main() -> () { StorageLive(_1); StorageLive(_2); _2 = const {ALLOC9: &&[(Option, &[&str])]}; - _1 = (*_2); + _1 = copy (*_2); StorageDead(_2); StorageDead(_1); _0 = const (); diff --git a/tests/mir-opt/const_allocation2.main.GVN.after.32bit.mir b/tests/mir-opt/const_allocation2.main.GVN.after.32bit.mir index 6499e3676aa..6fae163f107 100644 --- a/tests/mir-opt/const_allocation2.main.GVN.after.32bit.mir +++ b/tests/mir-opt/const_allocation2.main.GVN.after.32bit.mir @@ -9,7 +9,7 @@ fn main() -> () { StorageLive(_1); StorageLive(_2); _2 = const {ALLOC9: &&[(Option, &[&u8])]}; - _1 = (*_2); + _1 = copy (*_2); StorageDead(_2); StorageDead(_1); _0 = const (); diff --git a/tests/mir-opt/const_allocation2.main.GVN.after.64bit.mir b/tests/mir-opt/const_allocation2.main.GVN.after.64bit.mir index 02f5ebab847..f2bb5f46b16 100644 --- a/tests/mir-opt/const_allocation2.main.GVN.after.64bit.mir +++ b/tests/mir-opt/const_allocation2.main.GVN.after.64bit.mir @@ -9,7 +9,7 @@ fn main() -> () { StorageLive(_1); StorageLive(_2); _2 = const {ALLOC9: &&[(Option, &[&u8])]}; - _1 = (*_2); + _1 = copy (*_2); StorageDead(_2); StorageDead(_1); _0 = const (); diff --git a/tests/mir-opt/const_allocation3.main.GVN.after.32bit.mir b/tests/mir-opt/const_allocation3.main.GVN.after.32bit.mir index c95e696946a..58776b446fa 100644 --- a/tests/mir-opt/const_allocation3.main.GVN.after.32bit.mir +++ b/tests/mir-opt/const_allocation3.main.GVN.after.32bit.mir @@ -9,7 +9,7 @@ fn main() -> () { StorageLive(_1); StorageLive(_2); _2 = const {ALLOC4: &&Packed}; - _1 = (*_2); + _1 = copy (*_2); StorageDead(_2); StorageDead(_1); _0 = const (); diff --git a/tests/mir-opt/const_allocation3.main.GVN.after.64bit.mir b/tests/mir-opt/const_allocation3.main.GVN.after.64bit.mir index 198bc8bd07e..3ccf4211971 100644 --- a/tests/mir-opt/const_allocation3.main.GVN.after.64bit.mir +++ b/tests/mir-opt/const_allocation3.main.GVN.after.64bit.mir @@ -9,7 +9,7 @@ fn main() -> () { StorageLive(_1); StorageLive(_2); _2 = const {ALLOC2: &&Packed}; - _1 = (*_2); + _1 = copy (*_2); StorageDead(_2); StorageDead(_1); _0 = const (); diff --git a/tests/mir-opt/const_goto_const_eval_fail.f.JumpThreading.diff b/tests/mir-opt/const_goto_const_eval_fail.f.JumpThreading.diff index 4fc9254b7ba..086abeba0f8 100644 --- a/tests/mir-opt/const_goto_const_eval_fail.f.JumpThreading.diff +++ b/tests/mir-opt/const_goto_const_eval_fail.f.JumpThreading.diff @@ -22,7 +22,7 @@ } bb3: { - switchInt(_1) -> [0: bb5, otherwise: bb4]; + switchInt(copy _1) -> [0: bb5, otherwise: bb4]; } bb4: { diff --git a/tests/mir-opt/const_prop/address_of_pair.fn0.GVN.diff b/tests/mir-opt/const_prop/address_of_pair.fn0.GVN.diff index ac372f83726..e33185f17bc 100644 --- a/tests/mir-opt/const_prop/address_of_pair.fn0.GVN.diff +++ b/tests/mir-opt/const_prop/address_of_pair.fn0.GVN.diff @@ -34,10 +34,10 @@ - StorageLive(_5); + nop; StorageLive(_6); - _6 = (_2.1: bool); + _6 = copy (_2.1: bool); _5 = Not(move _6); StorageDead(_6); - _0 = _5; + _0 = copy _5; - StorageDead(_5); + nop; StorageDead(_3); diff --git a/tests/mir-opt/const_prop/address_of_pair.rs b/tests/mir-opt/const_prop/address_of_pair.rs index 9acaaa0ccaf..df1ab229d6e 100644 --- a/tests/mir-opt/const_prop/address_of_pair.rs +++ b/tests/mir-opt/const_prop/address_of_pair.rs @@ -10,13 +10,13 @@ pub fn fn0() -> bool { // CHECK: (*[[ptr]]) = const true; // CHECK-NOT: = const false; // CHECK-NOT: = const true; - // CHECK: [[tmp:_.*]] = ([[pair]].1: bool); + // CHECK: [[tmp:_.*]] = copy ([[pair]].1: bool); // CHECK-NOT: = const false; // CHECK-NOT: = const true; // CHECK: [[ret]] = Not(move [[tmp]]); // CHECK-NOT: = const false; // CHECK-NOT: = const true; - // CHECK: _0 = [[ret]]; + // CHECK: _0 = copy [[ret]]; let mut pair = (1, false); let ptr = core::ptr::addr_of_mut!(pair.1); pair = (1, false); diff --git a/tests/mir-opt/const_prop/aggregate.foo.GVN.panic-abort.diff b/tests/mir-opt/const_prop/aggregate.foo.GVN.panic-abort.diff index 4f0f7fa8fa2..c6d3bad0790 100644 --- a/tests/mir-opt/const_prop/aggregate.foo.GVN.panic-abort.diff +++ b/tests/mir-opt/const_prop/aggregate.foo.GVN.panic-abort.diff @@ -24,11 +24,11 @@ StorageLive(_3); StorageLive(_4); StorageLive(_5); - _5 = _1; + _5 = copy _1; - _4 = (const 0_i32, move _5); -+ _4 = (const 0_i32, _1); ++ _4 = (const 0_i32, copy _1); StorageDead(_5); -- _3 = (_4.0: i32); +- _3 = copy (_4.0: i32); - _2 = Add(move _3, const 1_i32); + _3 = const 0_i32; + _2 = const 1_i32; @@ -38,11 +38,11 @@ StorageLive(_7); StorageLive(_8); StorageLive(_9); - _9 = _1; + _9 = copy _1; - _8 = (move _9, const 1_i32); -+ _8 = (_1, const 1_i32); ++ _8 = (copy _1, const 1_i32); StorageDead(_9); -- _7 = (_8.1: i32); +- _7 = copy (_8.1: i32); - _6 = Add(move _7, const 2_i32); + _7 = const 1_i32; + _6 = const 3_i32; diff --git a/tests/mir-opt/const_prop/aggregate.foo.GVN.panic-unwind.diff b/tests/mir-opt/const_prop/aggregate.foo.GVN.panic-unwind.diff index 4f0f7fa8fa2..c6d3bad0790 100644 --- a/tests/mir-opt/const_prop/aggregate.foo.GVN.panic-unwind.diff +++ b/tests/mir-opt/const_prop/aggregate.foo.GVN.panic-unwind.diff @@ -24,11 +24,11 @@ StorageLive(_3); StorageLive(_4); StorageLive(_5); - _5 = _1; + _5 = copy _1; - _4 = (const 0_i32, move _5); -+ _4 = (const 0_i32, _1); ++ _4 = (const 0_i32, copy _1); StorageDead(_5); -- _3 = (_4.0: i32); +- _3 = copy (_4.0: i32); - _2 = Add(move _3, const 1_i32); + _3 = const 0_i32; + _2 = const 1_i32; @@ -38,11 +38,11 @@ StorageLive(_7); StorageLive(_8); StorageLive(_9); - _9 = _1; + _9 = copy _1; - _8 = (move _9, const 1_i32); -+ _8 = (_1, const 1_i32); ++ _8 = (copy _1, const 1_i32); StorageDead(_9); -- _7 = (_8.1: i32); +- _7 = copy (_8.1: i32); - _6 = Add(move _7, const 2_i32); + _7 = const 1_i32; + _6 = const 3_i32; diff --git a/tests/mir-opt/const_prop/aggregate.main.GVN.panic-abort.diff b/tests/mir-opt/const_prop/aggregate.main.GVN.panic-abort.diff index 854e27445af..0a59c59c2ed 100644 --- a/tests/mir-opt/const_prop/aggregate.main.GVN.panic-abort.diff +++ b/tests/mir-opt/const_prop/aggregate.main.GVN.panic-abort.diff @@ -18,7 +18,7 @@ StorageLive(_2); StorageLive(_3); _3 = (const 0_i32, const 1_u8, const 2_i32); -- _2 = (_3.1: u8); +- _2 = copy (_3.1: u8); - _1 = Add(move _2, const 0_u8); + _2 = const 1_u8; + _1 = const 1_u8; @@ -26,7 +26,7 @@ StorageDead(_3); StorageLive(_4); StorageLive(_5); -- _5 = _1; +- _5 = copy _1; - _4 = foo(move _5) -> [return: bb1, unwind unreachable]; + _5 = const 1_u8; + _4 = foo(const 1_u8) -> [return: bb1, unwind unreachable]; diff --git a/tests/mir-opt/const_prop/aggregate.main.GVN.panic-unwind.diff b/tests/mir-opt/const_prop/aggregate.main.GVN.panic-unwind.diff index f6c4b2c9240..100369a2eee 100644 --- a/tests/mir-opt/const_prop/aggregate.main.GVN.panic-unwind.diff +++ b/tests/mir-opt/const_prop/aggregate.main.GVN.panic-unwind.diff @@ -18,7 +18,7 @@ StorageLive(_2); StorageLive(_3); _3 = (const 0_i32, const 1_u8, const 2_i32); -- _2 = (_3.1: u8); +- _2 = copy (_3.1: u8); - _1 = Add(move _2, const 0_u8); + _2 = const 1_u8; + _1 = const 1_u8; @@ -26,7 +26,7 @@ StorageDead(_3); StorageLive(_4); StorageLive(_5); -- _5 = _1; +- _5 = copy _1; - _4 = foo(move _5) -> [return: bb1, unwind continue]; + _5 = const 1_u8; + _4 = foo(const 1_u8) -> [return: bb1, unwind continue]; diff --git a/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-abort.diff index 6d00dd5b212..e754af95ce3 100644 --- a/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-abort.diff @@ -19,15 +19,15 @@ StorageLive(_3); _3 = const 2_usize; - _4 = Len(_2); -- _5 = Lt(_3, _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind unreachable]; +- _5 = Lt(copy _3, copy _4); +- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind unreachable]; + _4 = const 4_usize; + _5 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } bb1: { -- _1 = _2[_3]; +- _1 = copy _2[_3]; + _1 = const 2_u32; StorageDead(_3); StorageDead(_2); diff --git a/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-unwind.diff index 7e2f72ab31b..e15a35c7fe9 100644 --- a/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-unwind.diff @@ -19,15 +19,15 @@ StorageLive(_3); _3 = const 2_usize; - _4 = Len(_2); -- _5 = Lt(_3, _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind continue]; +- _5 = Lt(copy _3, copy _4); +- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind continue]; + _4 = const 4_usize; + _5 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind continue]; } bb1: { -- _1 = _2[_3]; +- _1 = copy _2[_3]; + _1 = const 2_u32; StorageDead(_3); StorageDead(_2); diff --git a/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-abort.diff index 6d00dd5b212..e754af95ce3 100644 --- a/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-abort.diff @@ -19,15 +19,15 @@ StorageLive(_3); _3 = const 2_usize; - _4 = Len(_2); -- _5 = Lt(_3, _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind unreachable]; +- _5 = Lt(copy _3, copy _4); +- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind unreachable]; + _4 = const 4_usize; + _5 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } bb1: { -- _1 = _2[_3]; +- _1 = copy _2[_3]; + _1 = const 2_u32; StorageDead(_3); StorageDead(_2); diff --git a/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-unwind.diff index 7e2f72ab31b..e15a35c7fe9 100644 --- a/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-unwind.diff @@ -19,15 +19,15 @@ StorageLive(_3); _3 = const 2_usize; - _4 = Len(_2); -- _5 = Lt(_3, _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind continue]; +- _5 = Lt(copy _3, copy _4); +- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind continue]; + _4 = const 4_usize; + _5 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind continue]; } bb1: { -- _1 = _2[_3]; +- _1 = copy _2[_3]; + _1 = const 2_u32; StorageDead(_3); StorageDead(_2); diff --git a/tests/mir-opt/const_prop/bad_op_div_by_zero.main.GVN.panic-abort.diff b/tests/mir-opt/const_prop/bad_op_div_by_zero.main.GVN.panic-abort.diff index 4838efba6f9..8c535b567c3 100644 --- a/tests/mir-opt/const_prop/bad_op_div_by_zero.main.GVN.panic-abort.diff +++ b/tests/mir-opt/const_prop/bad_op_div_by_zero.main.GVN.panic-abort.diff @@ -23,8 +23,8 @@ _1 = const 0_i32; StorageLive(_2); StorageLive(_3); -- _3 = _1; -- _4 = Eq(_3, const 0_i32); +- _3 = copy _1; +- _4 = Eq(copy _3, const 0_i32); - assert(!move _4, "attempt to divide `{}` by zero", const 1_i32) -> [success: bb1, unwind unreachable]; + _3 = const 0_i32; + _4 = const true; @@ -32,10 +32,10 @@ } bb1: { -- _5 = Eq(_3, const -1_i32); +- _5 = Eq(copy _3, const -1_i32); - _6 = Eq(const 1_i32, const i32::MIN); - _7 = BitAnd(move _5, move _6); -- assert(!move _7, "attempt to compute `{} / {}`, which would overflow", const 1_i32, _3) -> [success: bb2, unwind unreachable]; +- assert(!move _7, "attempt to compute `{} / {}`, which would overflow", const 1_i32, copy _3) -> [success: bb2, unwind unreachable]; + _5 = const false; + _6 = const false; + _7 = const false; diff --git a/tests/mir-opt/const_prop/bad_op_div_by_zero.main.GVN.panic-unwind.diff b/tests/mir-opt/const_prop/bad_op_div_by_zero.main.GVN.panic-unwind.diff index 7f403d6efc1..045f4d81db6 100644 --- a/tests/mir-opt/const_prop/bad_op_div_by_zero.main.GVN.panic-unwind.diff +++ b/tests/mir-opt/const_prop/bad_op_div_by_zero.main.GVN.panic-unwind.diff @@ -23,8 +23,8 @@ _1 = const 0_i32; StorageLive(_2); StorageLive(_3); -- _3 = _1; -- _4 = Eq(_3, const 0_i32); +- _3 = copy _1; +- _4 = Eq(copy _3, const 0_i32); - assert(!move _4, "attempt to divide `{}` by zero", const 1_i32) -> [success: bb1, unwind continue]; + _3 = const 0_i32; + _4 = const true; @@ -32,10 +32,10 @@ } bb1: { -- _5 = Eq(_3, const -1_i32); +- _5 = Eq(copy _3, const -1_i32); - _6 = Eq(const 1_i32, const i32::MIN); - _7 = BitAnd(move _5, move _6); -- assert(!move _7, "attempt to compute `{} / {}`, which would overflow", const 1_i32, _3) -> [success: bb2, unwind continue]; +- assert(!move _7, "attempt to compute `{} / {}`, which would overflow", const 1_i32, copy _3) -> [success: bb2, unwind continue]; + _5 = const false; + _6 = const false; + _7 = const false; diff --git a/tests/mir-opt/const_prop/bad_op_mod_by_zero.main.GVN.panic-abort.diff b/tests/mir-opt/const_prop/bad_op_mod_by_zero.main.GVN.panic-abort.diff index 59f2eb86f50..e5a8726b855 100644 --- a/tests/mir-opt/const_prop/bad_op_mod_by_zero.main.GVN.panic-abort.diff +++ b/tests/mir-opt/const_prop/bad_op_mod_by_zero.main.GVN.panic-abort.diff @@ -23,8 +23,8 @@ _1 = const 0_i32; StorageLive(_2); StorageLive(_3); -- _3 = _1; -- _4 = Eq(_3, const 0_i32); +- _3 = copy _1; +- _4 = Eq(copy _3, const 0_i32); - assert(!move _4, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_i32) -> [success: bb1, unwind unreachable]; + _3 = const 0_i32; + _4 = const true; @@ -32,10 +32,10 @@ } bb1: { -- _5 = Eq(_3, const -1_i32); +- _5 = Eq(copy _3, const -1_i32); - _6 = Eq(const 1_i32, const i32::MIN); - _7 = BitAnd(move _5, move _6); -- assert(!move _7, "attempt to compute the remainder of `{} % {}`, which would overflow", const 1_i32, _3) -> [success: bb2, unwind unreachable]; +- assert(!move _7, "attempt to compute the remainder of `{} % {}`, which would overflow", const 1_i32, copy _3) -> [success: bb2, unwind unreachable]; + _5 = const false; + _6 = const false; + _7 = const false; diff --git a/tests/mir-opt/const_prop/bad_op_mod_by_zero.main.GVN.panic-unwind.diff b/tests/mir-opt/const_prop/bad_op_mod_by_zero.main.GVN.panic-unwind.diff index 9b866082788..1110ff186dc 100644 --- a/tests/mir-opt/const_prop/bad_op_mod_by_zero.main.GVN.panic-unwind.diff +++ b/tests/mir-opt/const_prop/bad_op_mod_by_zero.main.GVN.panic-unwind.diff @@ -23,8 +23,8 @@ _1 = const 0_i32; StorageLive(_2); StorageLive(_3); -- _3 = _1; -- _4 = Eq(_3, const 0_i32); +- _3 = copy _1; +- _4 = Eq(copy _3, const 0_i32); - assert(!move _4, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_i32) -> [success: bb1, unwind continue]; + _3 = const 0_i32; + _4 = const true; @@ -32,10 +32,10 @@ } bb1: { -- _5 = Eq(_3, const -1_i32); +- _5 = Eq(copy _3, const -1_i32); - _6 = Eq(const 1_i32, const i32::MIN); - _7 = BitAnd(move _5, move _6); -- assert(!move _7, "attempt to compute the remainder of `{} % {}`, which would overflow", const 1_i32, _3) -> [success: bb2, unwind continue]; +- assert(!move _7, "attempt to compute the remainder of `{} % {}`, which would overflow", const 1_i32, copy _3) -> [success: bb2, unwind continue]; + _5 = const false; + _6 = const false; + _7 = const false; diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-abort.diff index 826f4c34277..52aa4da49ef 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-abort.diff @@ -33,15 +33,15 @@ StorageLive(_6); _6 = const 3_usize; _7 = Len((*_1)); -- _8 = Lt(_6, _7); -- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb1, unwind unreachable]; -+ _8 = Lt(const 3_usize, _7); +- _8 = Lt(copy _6, copy _7); +- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind unreachable]; ++ _8 = Lt(const 3_usize, copy _7); + assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 3_usize) -> [success: bb1, unwind unreachable]; } bb1: { -- _5 = (*_1)[_6]; -+ _5 = (*_1)[3 of 4]; +- _5 = copy (*_1)[_6]; ++ _5 = copy (*_1)[3 of 4]; StorageDead(_6); _0 = const (); StorageDead(_5); diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-unwind.diff index 0e2ec65652f..242ff0e664f 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-unwind.diff @@ -33,15 +33,15 @@ StorageLive(_6); _6 = const 3_usize; _7 = Len((*_1)); -- _8 = Lt(_6, _7); -- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb1, unwind continue]; -+ _8 = Lt(const 3_usize, _7); +- _8 = Lt(copy _6, copy _7); +- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind continue]; ++ _8 = Lt(const 3_usize, copy _7); + assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 3_usize) -> [success: bb1, unwind continue]; } bb1: { -- _5 = (*_1)[_6]; -+ _5 = (*_1)[3 of 4]; +- _5 = copy (*_1)[_6]; ++ _5 = copy (*_1)[3 of 4]; StorageDead(_6); _0 = const (); StorageDead(_5); diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-abort.diff index 826f4c34277..52aa4da49ef 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-abort.diff @@ -33,15 +33,15 @@ StorageLive(_6); _6 = const 3_usize; _7 = Len((*_1)); -- _8 = Lt(_6, _7); -- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb1, unwind unreachable]; -+ _8 = Lt(const 3_usize, _7); +- _8 = Lt(copy _6, copy _7); +- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind unreachable]; ++ _8 = Lt(const 3_usize, copy _7); + assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 3_usize) -> [success: bb1, unwind unreachable]; } bb1: { -- _5 = (*_1)[_6]; -+ _5 = (*_1)[3 of 4]; +- _5 = copy (*_1)[_6]; ++ _5 = copy (*_1)[3 of 4]; StorageDead(_6); _0 = const (); StorageDead(_5); diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-unwind.diff index 0e2ec65652f..242ff0e664f 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-unwind.diff @@ -33,15 +33,15 @@ StorageLive(_6); _6 = const 3_usize; _7 = Len((*_1)); -- _8 = Lt(_6, _7); -- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb1, unwind continue]; -+ _8 = Lt(const 3_usize, _7); +- _8 = Lt(copy _6, copy _7); +- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind continue]; ++ _8 = Lt(const 3_usize, copy _7); + assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 3_usize) -> [success: bb1, unwind continue]; } bb1: { -- _5 = (*_1)[_6]; -+ _5 = (*_1)[3 of 4]; +- _5 = copy (*_1)[_6]; ++ _5 = copy (*_1)[3 of 4]; StorageDead(_6); _0 = const (); StorageDead(_5); diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs index 0f8d278535d..139d0fa2e0f 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs @@ -8,7 +8,7 @@ fn main() { // CHECK-LABEL: fn main( // CHECK: debug a => [[a:_.*]]; // CHECK: debug _b => [[b:_.*]]; - // CHECK: [[b]] = (*[[a]])[3 of 4]; + // CHECK: [[b]] = copy (*[[a]])[3 of 4]; let a: *const [_] = &[1, 2, 3]; unsafe { let _b = (*a)[3]; diff --git a/tests/mir-opt/const_prop/boolean_identities.test.GVN.diff b/tests/mir-opt/const_prop/boolean_identities.test.GVN.diff index 0bd8413289e..3fe70302b21 100644 --- a/tests/mir-opt/const_prop/boolean_identities.test.GVN.diff +++ b/tests/mir-opt/const_prop/boolean_identities.test.GVN.diff @@ -22,22 +22,22 @@ - StorageLive(_3); + nop; StorageLive(_4); - _4 = _2; + _4 = copy _2; - _3 = BitOr(move _4, const true); + _3 = const true; StorageDead(_4); - StorageLive(_5); + nop; StorageLive(_6); - _6 = _1; + _6 = copy _1; - _5 = BitAnd(move _6, const false); + _5 = const false; StorageDead(_6); StorageLive(_7); -- _7 = _3; +- _7 = copy _3; + _7 = const true; StorageLive(_8); -- _8 = _5; +- _8 = copy _5; - _0 = BitAnd(move _7, move _8); + _8 = const false; + _0 = const false; diff --git a/tests/mir-opt/const_prop/boxes.main.GVN.panic-abort.diff b/tests/mir-opt/const_prop/boxes.main.GVN.panic-abort.diff index a408c197fd1..d5f15b750d4 100644 --- a/tests/mir-opt/const_prop/boxes.main.GVN.panic-abort.diff +++ b/tests/mir-opt/const_prop/boxes.main.GVN.panic-abort.diff @@ -32,15 +32,15 @@ bb1: { StorageLive(_7); _7 = ShallowInitBox(move _6, i32); - _8 = (((_7.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const i32); + _8 = copy (((_7.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const i32); (*_8) = const 42_i32; _3 = move _7; StorageDead(_7); - _9 = (((_3.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const i32); - _2 = (*_9); + _9 = copy (((_3.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const i32); + _2 = copy (*_9); - _1 = Add(move _2, const 0_i32); - StorageDead(_2); -+ _1 = _2; ++ _1 = copy _2; + nop; drop(_3) -> [return: bb2, unwind unreachable]; } diff --git a/tests/mir-opt/const_prop/boxes.main.GVN.panic-unwind.diff b/tests/mir-opt/const_prop/boxes.main.GVN.panic-unwind.diff index 5706a739602..d4d4f21be6e 100644 --- a/tests/mir-opt/const_prop/boxes.main.GVN.panic-unwind.diff +++ b/tests/mir-opt/const_prop/boxes.main.GVN.panic-unwind.diff @@ -32,15 +32,15 @@ bb1: { StorageLive(_7); _7 = ShallowInitBox(move _6, i32); - _8 = (((_7.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const i32); + _8 = copy (((_7.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const i32); (*_8) = const 42_i32; _3 = move _7; StorageDead(_7); - _9 = (((_3.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const i32); - _2 = (*_9); + _9 = copy (((_3.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const i32); + _2 = copy (*_9); - _1 = Add(move _2, const 0_i32); - StorageDead(_2); -+ _1 = _2; ++ _1 = copy _2; + nop; drop(_3) -> [return: bb2, unwind: bb3]; } diff --git a/tests/mir-opt/const_prop/boxes.rs b/tests/mir-opt/const_prop/boxes.rs index 7813352261e..f04db260e27 100644 --- a/tests/mir-opt/const_prop/boxes.rs +++ b/tests/mir-opt/const_prop/boxes.rs @@ -11,8 +11,8 @@ fn main() { // CHECK-LABEL: fn main( // CHECK: debug x => [[x:_.*]]; // CHECK: (*{{_.*}}) = const 42_i32; - // CHECK: [[tmp:_.*]] = (*{{_.*}}); - // CHECK: [[x]] = [[tmp]]; + // CHECK: [[tmp:_.*]] = copy (*{{_.*}}); + // CHECK: [[x]] = copy [[tmp]]; let x = *(#[rustc_box] Box::new(42)) + 0; diff --git a/tests/mir-opt/const_prop/discriminant.main.GVN.32bit.diff b/tests/mir-opt/const_prop/discriminant.main.GVN.32bit.diff index 70c3c3fe7e4..2543cf6257d 100644 --- a/tests/mir-opt/const_prop/discriminant.main.GVN.32bit.diff +++ b/tests/mir-opt/const_prop/discriminant.main.GVN.32bit.diff @@ -26,7 +26,7 @@ } bb1: { -- switchInt(((_3 as Some).0: bool)) -> [0: bb3, otherwise: bb2]; +- switchInt(copy ((_3 as Some).0: bool)) -> [0: bb3, otherwise: bb2]; + switchInt(const true) -> [0: bb3, otherwise: bb2]; } diff --git a/tests/mir-opt/const_prop/discriminant.main.GVN.64bit.diff b/tests/mir-opt/const_prop/discriminant.main.GVN.64bit.diff index 70c3c3fe7e4..2543cf6257d 100644 --- a/tests/mir-opt/const_prop/discriminant.main.GVN.64bit.diff +++ b/tests/mir-opt/const_prop/discriminant.main.GVN.64bit.diff @@ -26,7 +26,7 @@ } bb1: { -- switchInt(((_3 as Some).0: bool)) -> [0: bb3, otherwise: bb2]; +- switchInt(copy ((_3 as Some).0: bool)) -> [0: bb3, otherwise: bb2]; + switchInt(const true) -> [0: bb3, otherwise: bb2]; } diff --git a/tests/mir-opt/const_prop/indirect.main.GVN.panic-abort.diff b/tests/mir-opt/const_prop/indirect.main.GVN.panic-abort.diff index f24b9755eae..208845942c7 100644 --- a/tests/mir-opt/const_prop/indirect.main.GVN.panic-abort.diff +++ b/tests/mir-opt/const_prop/indirect.main.GVN.panic-abort.diff @@ -14,7 +14,7 @@ StorageLive(_1); StorageLive(_2); - _2 = const 2_u32 as u8 (IntToInt); -- _3 = AddWithOverflow(_2, const 1_u8); +- _3 = AddWithOverflow(copy _2, const 1_u8); - assert(!move (_3.1: bool), "attempt to compute `{} + {}`, which would overflow", move _2, const 1_u8) -> [success: bb1, unwind unreachable]; + _2 = const 2_u8; + _3 = const (3_u8, false); diff --git a/tests/mir-opt/const_prop/indirect.main.GVN.panic-unwind.diff b/tests/mir-opt/const_prop/indirect.main.GVN.panic-unwind.diff index 44ff313b532..4a7c69bae3c 100644 --- a/tests/mir-opt/const_prop/indirect.main.GVN.panic-unwind.diff +++ b/tests/mir-opt/const_prop/indirect.main.GVN.panic-unwind.diff @@ -14,7 +14,7 @@ StorageLive(_1); StorageLive(_2); - _2 = const 2_u32 as u8 (IntToInt); -- _3 = AddWithOverflow(_2, const 1_u8); +- _3 = AddWithOverflow(copy _2, const 1_u8); - assert(!move (_3.1: bool), "attempt to compute `{} + {}`, which would overflow", move _2, const 1_u8) -> [success: bb1, unwind continue]; + _2 = const 2_u8; + _3 = const (3_u8, false); diff --git a/tests/mir-opt/const_prop/indirect_mutation.bar.GVN.diff b/tests/mir-opt/const_prop/indirect_mutation.bar.GVN.diff index 99a6ba7d08a..849a57e2030 100644 --- a/tests/mir-opt/const_prop/indirect_mutation.bar.GVN.diff +++ b/tests/mir-opt/const_prop/indirect_mutation.bar.GVN.diff @@ -28,7 +28,7 @@ StorageDead(_2); StorageLive(_4); StorageLive(_5); - _5 = (_1.0: i32); + _5 = copy (_1.0: i32); _4 = Eq(move _5, const 5_i32); StorageDead(_5); _0 = const (); diff --git a/tests/mir-opt/const_prop/indirect_mutation.foo.GVN.diff b/tests/mir-opt/const_prop/indirect_mutation.foo.GVN.diff index c21869dece6..2435f81206b 100644 --- a/tests/mir-opt/const_prop/indirect_mutation.foo.GVN.diff +++ b/tests/mir-opt/const_prop/indirect_mutation.foo.GVN.diff @@ -24,7 +24,7 @@ StorageDead(_2); StorageLive(_3); StorageLive(_4); - _4 = (_1.0: i32); + _4 = copy (_1.0: i32); _3 = Eq(move _4, const 5_i32); StorageDead(_4); _0 = const (); diff --git a/tests/mir-opt/const_prop/indirect_mutation.rs b/tests/mir-opt/const_prop/indirect_mutation.rs index 32ff8f142b1..e82be0a8388 100644 --- a/tests/mir-opt/const_prop/indirect_mutation.rs +++ b/tests/mir-opt/const_prop/indirect_mutation.rs @@ -1,6 +1,5 @@ //@ test-mir-pass: GVN // Check that we do not propagate past an indirect mutation. -#![feature(raw_ref_op)] // EMIT_MIR indirect_mutation.foo.GVN.diff fn foo() { @@ -10,7 +9,7 @@ fn foo() { // CHECK: _1 = const (1_i32,); // CHECK: _2 = &mut (_1.0: i32); // CHECK: (*_2) = const 5_i32; - // CHECK: _4 = (_1.0: i32); + // CHECK: _4 = copy (_1.0: i32); // CHECK: _3 = Eq(move _4, const 5_i32); let mut u = (1,); @@ -25,7 +24,7 @@ fn bar() { // CHECK: debug y => _4; // CHECK: _3 = &raw mut (_1.0: i32); // CHECK: (*_3) = const 5_i32; - // CHECK: _5 = (_1.0: i32); + // CHECK: _5 = copy (_1.0: i32); // CHECK: _4 = Eq(move _5, const 5_i32); let mut v = (1,); diff --git a/tests/mir-opt/const_prop/inherit_overflow.main.GVN.panic-abort.diff b/tests/mir-opt/const_prop/inherit_overflow.main.GVN.panic-abort.diff index de9cb7a47a2..ab39c5be4e3 100644 --- a/tests/mir-opt/const_prop/inherit_overflow.main.GVN.panic-abort.diff +++ b/tests/mir-opt/const_prop/inherit_overflow.main.GVN.panic-abort.diff @@ -19,8 +19,8 @@ StorageLive(_3); _3 = const 1_u8; StorageLive(_4); -- _4 = AddWithOverflow(_2, _3); -- assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind unreachable]; +- _4 = AddWithOverflow(copy _2, copy _3); +- assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", copy _2, copy _3) -> [success: bb1, unwind unreachable]; + _4 = const (0_u8, true); + assert(!const true, "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> [success: bb1, unwind unreachable]; } diff --git a/tests/mir-opt/const_prop/inherit_overflow.main.GVN.panic-unwind.diff b/tests/mir-opt/const_prop/inherit_overflow.main.GVN.panic-unwind.diff index 1f19a13c1e8..1aea0dbb5d5 100644 --- a/tests/mir-opt/const_prop/inherit_overflow.main.GVN.panic-unwind.diff +++ b/tests/mir-opt/const_prop/inherit_overflow.main.GVN.panic-unwind.diff @@ -19,8 +19,8 @@ StorageLive(_3); _3 = const 1_u8; StorageLive(_4); -- _4 = AddWithOverflow(_2, _3); -- assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind continue]; +- _4 = AddWithOverflow(copy _2, copy _3); +- assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", copy _2, copy _3) -> [success: bb1, unwind continue]; + _4 = const (0_u8, true); + assert(!const true, "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> [success: bb1, unwind continue]; } diff --git a/tests/mir-opt/const_prop/invalid_constant.main.GVN.diff b/tests/mir-opt/const_prop/invalid_constant.main.GVN.diff index f5041365604..5e843da8679 100644 --- a/tests/mir-opt/const_prop/invalid_constant.main.GVN.diff +++ b/tests/mir-opt/const_prop/invalid_constant.main.GVN.diff @@ -29,13 +29,13 @@ StorageLive(_1); StorageLive(_2); _2 = InvalidChar { int: const 1114113_u32 }; - _1 = (_2.1: char); + _1 = copy (_2.1: char); StorageDead(_2); StorageLive(_3); StorageLive(_4); StorageLive(_5); _5 = InvalidTag { int: const 4_u32 }; - _4 = (_5.1: E); + _4 = copy (_5.1: E); _3 = [move _4]; StorageDead(_4); StorageDead(_5); diff --git a/tests/mir-opt/const_prop/invalid_constant.main.RemoveZsts.diff b/tests/mir-opt/const_prop/invalid_constant.main.RemoveZsts.diff index 6e5ad8d6b81..6593b329756 100644 --- a/tests/mir-opt/const_prop/invalid_constant.main.RemoveZsts.diff +++ b/tests/mir-opt/const_prop/invalid_constant.main.RemoveZsts.diff @@ -31,13 +31,13 @@ StorageLive(_1); StorageLive(_2); _2 = InvalidChar { int: const 1114113_u32 }; - _1 = (_2.1: char); + _1 = copy (_2.1: char); StorageDead(_2); StorageLive(_3); StorageLive(_4); StorageLive(_5); _5 = InvalidTag { int: const 4_u32 }; - _4 = (_5.1: E); + _4 = copy (_5.1: E); _3 = [move _4]; StorageDead(_4); StorageDead(_5); @@ -47,7 +47,7 @@ + nop; StorageLive(_8); _8 = NoVariants { int: const 0_u32 }; -- _7 = (_8.1: Empty); +- _7 = copy (_8.1: Empty); - _6 = [move _7]; - StorageDead(_7); + nop; diff --git a/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-abort.diff index bd987c01ab1..49ea51deed6 100644 --- a/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-abort.diff @@ -19,15 +19,15 @@ StorageLive(_3); _3 = const 2_usize; - _4 = Len(_2); -- _5 = Lt(_3, _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind unreachable]; +- _5 = Lt(copy _3, copy _4); +- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind unreachable]; + _4 = const 5000_usize; + _5 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } bb1: { -- _1 = _2[_3]; +- _1 = copy _2[_3]; + _1 = const 0_u8; StorageDead(_3); StorageDead(_2); diff --git a/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-unwind.diff index e9ebef84ae0..103bfbcaf64 100644 --- a/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-unwind.diff @@ -19,15 +19,15 @@ StorageLive(_3); _3 = const 2_usize; - _4 = Len(_2); -- _5 = Lt(_3, _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind continue]; +- _5 = Lt(copy _3, copy _4); +- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind continue]; + _4 = const 5000_usize; + _5 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind continue]; } bb1: { -- _1 = _2[_3]; +- _1 = copy _2[_3]; + _1 = const 0_u8; StorageDead(_3); StorageDead(_2); diff --git a/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-abort.diff index bd987c01ab1..49ea51deed6 100644 --- a/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-abort.diff @@ -19,15 +19,15 @@ StorageLive(_3); _3 = const 2_usize; - _4 = Len(_2); -- _5 = Lt(_3, _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind unreachable]; +- _5 = Lt(copy _3, copy _4); +- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind unreachable]; + _4 = const 5000_usize; + _5 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } bb1: { -- _1 = _2[_3]; +- _1 = copy _2[_3]; + _1 = const 0_u8; StorageDead(_3); StorageDead(_2); diff --git a/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-unwind.diff index e9ebef84ae0..103bfbcaf64 100644 --- a/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-unwind.diff @@ -19,15 +19,15 @@ StorageLive(_3); _3 = const 2_usize; - _4 = Len(_2); -- _5 = Lt(_3, _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind continue]; +- _5 = Lt(copy _3, copy _4); +- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind continue]; + _4 = const 5000_usize; + _5 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind continue]; } bb1: { -- _1 = _2[_3]; +- _1 = copy _2[_3]; + _1 = const 0_u8; StorageDead(_3); StorageDead(_2); diff --git a/tests/mir-opt/const_prop/mult_by_zero.test.GVN.diff b/tests/mir-opt/const_prop/mult_by_zero.test.GVN.diff index 6c2aab45d48..290d9d62ce0 100644 --- a/tests/mir-opt/const_prop/mult_by_zero.test.GVN.diff +++ b/tests/mir-opt/const_prop/mult_by_zero.test.GVN.diff @@ -8,7 +8,7 @@ bb0: { StorageLive(_2); - _2 = _1; + _2 = copy _1; - _0 = Mul(move _2, const 0_i32); + _0 = const 0_i32; StorageDead(_2); diff --git a/tests/mir-opt/const_prop/mutable_variable.main.GVN.diff b/tests/mir-opt/const_prop/mutable_variable.main.GVN.diff index 11464e32400..cc25b6caf90 100644 --- a/tests/mir-opt/const_prop/mutable_variable.main.GVN.diff +++ b/tests/mir-opt/const_prop/mutable_variable.main.GVN.diff @@ -17,7 +17,7 @@ _1 = const 42_i32; _1 = const 99_i32; StorageLive(_2); - _2 = _1; + _2 = copy _1; _0 = const (); StorageDead(_2); StorageDead(_1); diff --git a/tests/mir-opt/const_prop/mutable_variable.rs b/tests/mir-opt/const_prop/mutable_variable.rs index 9698fba6a11..3aa1b1bcd21 100644 --- a/tests/mir-opt/const_prop/mutable_variable.rs +++ b/tests/mir-opt/const_prop/mutable_variable.rs @@ -7,7 +7,7 @@ fn main() { // CHECK: debug y => [[y:_.*]]; // CHECK: [[x]] = const 42_i32; // CHECK: [[x]] = const 99_i32; - // CHECK: [[y]] = [[x]]; + // CHECK: [[y]] = copy [[x]]; let mut x = 42; x = 99; let y = x; diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate.main.GVN.diff b/tests/mir-opt/const_prop/mutable_variable_aggregate.main.GVN.diff index 7584353620e..3cc71eee710 100644 --- a/tests/mir-opt/const_prop/mutable_variable_aggregate.main.GVN.diff +++ b/tests/mir-opt/const_prop/mutable_variable_aggregate.main.GVN.diff @@ -18,7 +18,7 @@ + _1 = const (42_i32, 43_i32); (_1.1: i32) = const 99_i32; StorageLive(_2); - _2 = _1; + _2 = copy _1; _0 = const (); StorageDead(_2); StorageDead(_1); diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate.rs b/tests/mir-opt/const_prop/mutable_variable_aggregate.rs index 80cd75215c1..bb8bf7f7164 100644 --- a/tests/mir-opt/const_prop/mutable_variable_aggregate.rs +++ b/tests/mir-opt/const_prop/mutable_variable_aggregate.rs @@ -8,7 +8,7 @@ fn main() { // CHECK: debug y => [[y:_.*]]; // CHECK: [[x]] = const (42_i32, 43_i32); // CHECK: ([[x]].1: i32) = const 99_i32; - // CHECK: [[y]] = [[x]]; + // CHECK: [[y]] = copy [[x]]; let mut x = (42, 43); x.1 = 99; let y = x; diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.GVN.diff b/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.GVN.diff index e16e2969eb8..569ad62b5cc 100644 --- a/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.GVN.diff +++ b/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.GVN.diff @@ -24,7 +24,7 @@ _2 = &mut _1; ((*_2).1: i32) = const 99_i32; StorageLive(_3); - _3 = _1; + _3 = copy _1; _0 = const (); StorageDead(_3); StorageDead(_2); diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs b/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs index 856afd53ab4..332cac96f75 100644 --- a/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs +++ b/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs @@ -10,7 +10,7 @@ fn main() { // CHECK: [[x]] = const (42_i32, 43_i32); // CHECK: [[z]] = &mut [[x]]; // CHECK: ((*[[z]]).1: i32) = const 99_i32; - // CHECK: [[y]] = [[x]]; + // CHECK: [[y]] = copy [[x]]; let mut x = (42, 43); let z = &mut x; z.1 = 99; diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.GVN.panic-abort.diff b/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.GVN.panic-abort.diff index 6480e480f8c..5b4d18a3c07 100644 --- a/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.GVN.panic-abort.diff +++ b/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.GVN.panic-abort.diff @@ -21,7 +21,7 @@ (_1.1: i32) = const 99_i32; (_1.0: i32) = const 42_i32; StorageLive(_2); - _2 = (_1.1: i32); + _2 = copy (_1.1: i32); _0 = const (); StorageDead(_2); StorageDead(_1); diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.GVN.panic-unwind.diff b/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.GVN.panic-unwind.diff index fb757801082..d58febe368d 100644 --- a/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.GVN.panic-unwind.diff +++ b/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.GVN.panic-unwind.diff @@ -21,7 +21,7 @@ (_1.1: i32) = const 99_i32; (_1.0: i32) = const 42_i32; StorageLive(_2); - _2 = (_1.1: i32); + _2 = copy (_1.1: i32); _0 = const (); StorageDead(_2); StorageDead(_1); diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs b/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs index 6f99e6be246..e27437a1c75 100644 --- a/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs +++ b/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs @@ -9,7 +9,7 @@ fn main() { // CHECK: [[x]] = foo() // CHECK: ([[x]].1: i32) = const 99_i32; // CHECK: ([[x]].0: i32) = const 42_i32; - // CHECK: [[y]] = ([[x]].1: i32); + // CHECK: [[y]] = copy ([[x]].1: i32); let mut x: (i32, i32) = foo(); x.1 = 99; x.0 = 42; diff --git a/tests/mir-opt/const_prop/mutable_variable_no_prop.main.GVN.diff b/tests/mir-opt/const_prop/mutable_variable_no_prop.main.GVN.diff index 31c839f6749..3f8dc12f4ae 100644 --- a/tests/mir-opt/const_prop/mutable_variable_no_prop.main.GVN.diff +++ b/tests/mir-opt/const_prop/mutable_variable_no_prop.main.GVN.diff @@ -22,14 +22,14 @@ StorageLive(_3); StorageLive(_4); _4 = const {ALLOC0: *mut u32}; - _3 = (*_4); + _3 = copy (*_4); _1 = move _3; StorageDead(_3); StorageDead(_4); _2 = const (); StorageDead(_2); StorageLive(_5); - _5 = _1; + _5 = copy _1; _0 = const (); StorageDead(_5); StorageDead(_1); diff --git a/tests/mir-opt/const_prop/mutable_variable_no_prop.rs b/tests/mir-opt/const_prop/mutable_variable_no_prop.rs index 8289832f81e..66af5bf1d5d 100644 --- a/tests/mir-opt/const_prop/mutable_variable_no_prop.rs +++ b/tests/mir-opt/const_prop/mutable_variable_no_prop.rs @@ -9,9 +9,9 @@ fn main() { // CHECK: debug x => [[x:_.*]]; // CHECK: debug y => [[y:_.*]]; // CHECK: [[x]] = const 42_u32; - // CHECK: [[tmp:_.*]] = (*{{_.*}}); + // CHECK: [[tmp:_.*]] = copy (*{{_.*}}); // CHECK: [[x]] = move [[tmp]]; - // CHECK: [[y]] = [[x]]; + // CHECK: [[y]] = copy [[x]]; let mut x = 42; unsafe { x = STATIC; diff --git a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.GVN.panic-abort.diff b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.GVN.panic-abort.diff index 19d79694666..7ca1b39d771 100644 --- a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.GVN.panic-abort.diff +++ b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.GVN.panic-abort.diff @@ -32,14 +32,14 @@ - _2 = (const 1_i32, const 2_i32); + _2 = const (1_i32, 2_i32); StorageLive(_3); - _3 = _1; + _3 = copy _1; - (_2.1: i32) = move _3; -+ (_2.1: i32) = _1; ++ (_2.1: i32) = copy _1; StorageDead(_3); StorageLive(_4); - _4 = (_2.1: i32); + _4 = copy (_2.1: i32); StorageLive(_5); - _5 = (_2.0: i32); + _5 = copy (_2.0: i32); _0 = const (); StorageDead(_5); StorageDead(_4); diff --git a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.GVN.panic-unwind.diff b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.GVN.panic-unwind.diff index 2bb277bf27f..f6379513806 100644 --- a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.GVN.panic-unwind.diff +++ b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.GVN.panic-unwind.diff @@ -32,14 +32,14 @@ - _2 = (const 1_i32, const 2_i32); + _2 = const (1_i32, 2_i32); StorageLive(_3); - _3 = _1; + _3 = copy _1; - (_2.1: i32) = move _3; -+ (_2.1: i32) = _1; ++ (_2.1: i32) = copy _1; StorageDead(_3); StorageLive(_4); - _4 = (_2.1: i32); + _4 = copy (_2.1: i32); StorageLive(_5); - _5 = (_2.0: i32); + _5 = copy (_2.0: i32); _0 = const (); StorageDead(_5); StorageDead(_4); diff --git a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.rs b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.rs index 2c6cc0db6b2..1f4421331bc 100644 --- a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.rs +++ b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.rs @@ -11,9 +11,9 @@ fn main() { // CHECK: debug z => [[z:_.*]]; // CHECK: [[a]] = foo() // CHECK: [[x]] = const (1_i32, 2_i32); - // CHECK: ([[x]].1: i32) = [[a]]; - // CHECK: [[y]] = ([[x]].1: i32); - // CHECK: [[z]] = ([[x]].0: i32); + // CHECK: ([[x]].1: i32) = copy [[a]]; + // CHECK: [[y]] = copy ([[x]].1: i32); + // CHECK: [[z]] = copy ([[x]].0: i32); let a = foo(); let mut x: (i32, i32) = (1, 2); x.1 = a; diff --git a/tests/mir-opt/const_prop/overwrite_with_const_with_params.rs b/tests/mir-opt/const_prop/overwrite_with_const_with_params.rs index a43558223fe..1d8890bf369 100644 --- a/tests/mir-opt/const_prop/overwrite_with_const_with_params.rs +++ b/tests/mir-opt/const_prop/overwrite_with_const_with_params.rs @@ -15,7 +15,7 @@ fn size_of() -> usize { // CHECK-LABEL: fn size_of( // CHECK: _1 = const 0_usize; // CHECK-NEXT: _1 = const SizeOfConst::::SIZE; - // CHECK-NEXT: _0 = _1; + // CHECK-NEXT: _0 = copy _1; let mut a = 0; a = SizeOfConst::::SIZE; a diff --git a/tests/mir-opt/const_prop/overwrite_with_const_with_params.size_of.GVN.diff b/tests/mir-opt/const_prop/overwrite_with_const_with_params.size_of.GVN.diff index 1eadffa4f36..da6ef0a978b 100644 --- a/tests/mir-opt/const_prop/overwrite_with_const_with_params.size_of.GVN.diff +++ b/tests/mir-opt/const_prop/overwrite_with_const_with_params.size_of.GVN.diff @@ -12,7 +12,7 @@ StorageLive(_1); _1 = const 0_usize; _1 = const SizeOfConst::::SIZE; - _0 = _1; + _0 = copy _1; StorageDead(_1); return; } diff --git a/tests/mir-opt/const_prop/pointer_expose_provenance.main.GVN.panic-abort.diff b/tests/mir-opt/const_prop/pointer_expose_provenance.main.GVN.panic-abort.diff index 79a95b618d1..657fa7a5fea 100644 --- a/tests/mir-opt/const_prop/pointer_expose_provenance.main.GVN.panic-abort.diff +++ b/tests/mir-opt/const_prop/pointer_expose_provenance.main.GVN.panic-abort.diff @@ -24,9 +24,9 @@ StorageDead(_3); StorageLive(_4); StorageLive(_5); - _5 = _1; + _5 = copy _1; - _4 = read(move _5) -> [return: bb1, unwind unreachable]; -+ _4 = read(_1) -> [return: bb1, unwind unreachable]; ++ _4 = read(copy _1) -> [return: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/const_prop/pointer_expose_provenance.main.GVN.panic-unwind.diff b/tests/mir-opt/const_prop/pointer_expose_provenance.main.GVN.panic-unwind.diff index 9d1bcd92fef..8fef6591d41 100644 --- a/tests/mir-opt/const_prop/pointer_expose_provenance.main.GVN.panic-unwind.diff +++ b/tests/mir-opt/const_prop/pointer_expose_provenance.main.GVN.panic-unwind.diff @@ -24,9 +24,9 @@ StorageDead(_3); StorageLive(_4); StorageLive(_5); - _5 = _1; + _5 = copy _1; - _4 = read(move _5) -> [return: bb1, unwind continue]; -+ _4 = read(_1) -> [return: bb1, unwind continue]; ++ _4 = read(copy _1) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/pointer_expose_provenance.rs b/tests/mir-opt/const_prop/pointer_expose_provenance.rs index a76fead9859..bee8a985f8f 100644 --- a/tests/mir-opt/const_prop/pointer_expose_provenance.rs +++ b/tests/mir-opt/const_prop/pointer_expose_provenance.rs @@ -10,7 +10,7 @@ fn main() { // CHECK: [[ptr:_.*]] = const main::FOO; // CHECK: [[ref:_.*]] = &raw const (*[[ptr]]); // CHECK: [[x:_.*]] = move [[ref]] as usize (PointerExposeProvenance); - // CHECK: = read([[x]]) + // CHECK: = read(copy [[x]]) const FOO: &i32 = &1; let x = FOO as *const i32 as usize; read(x); diff --git a/tests/mir-opt/const_prop/read_immutable_static.main.GVN.diff b/tests/mir-opt/const_prop/read_immutable_static.main.GVN.diff index 38f23505230..8df262b351f 100644 --- a/tests/mir-opt/const_prop/read_immutable_static.main.GVN.diff +++ b/tests/mir-opt/const_prop/read_immutable_static.main.GVN.diff @@ -19,12 +19,12 @@ + nop; + nop; _3 = const {ALLOC0: &u8}; -- _2 = (*_3); +- _2 = copy (*_3); + _2 = const 2_u8; StorageLive(_4); StorageLive(_5); _5 = const {ALLOC0: &u8}; -- _4 = (*_5); +- _4 = copy (*_5); - _1 = Add(move _2, move _4); + _4 = const 2_u8; + _1 = const 4_u8; diff --git a/tests/mir-opt/const_prop/ref_deref.main.GVN.diff b/tests/mir-opt/const_prop/ref_deref.main.GVN.diff index 509924a91c5..b9e269266b0 100644 --- a/tests/mir-opt/const_prop/ref_deref.main.GVN.diff +++ b/tests/mir-opt/const_prop/ref_deref.main.GVN.diff @@ -16,7 +16,7 @@ StorageLive(_2); _4 = const main::promoted[0]; _2 = &(*_4); -- _1 = (*_2); +- _1 = copy (*_2); + _1 = const 4_i32; StorageDead(_2); _0 = const (); diff --git a/tests/mir-opt/const_prop/ref_deref_project.main.GVN.diff b/tests/mir-opt/const_prop/ref_deref_project.main.GVN.diff index 820c6cc0680..dcc13c9251c 100644 --- a/tests/mir-opt/const_prop/ref_deref_project.main.GVN.diff +++ b/tests/mir-opt/const_prop/ref_deref_project.main.GVN.diff @@ -16,7 +16,7 @@ StorageLive(_2); _4 = const main::promoted[0]; _2 = &((*_4).1: i32); -- _1 = (*_2); +- _1 = copy (*_2); + _1 = const 5_i32; StorageDead(_2); _0 = const (); diff --git a/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-abort.diff index 71635b8e9c3..f7c1c2da01f 100644 --- a/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-abort.diff @@ -21,15 +21,15 @@ StorageLive(_4); _4 = const 2_usize; - _5 = Len(_3); -- _6 = Lt(_4, _5); -- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind unreachable]; +- _6 = Lt(copy _4, copy _5); +- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, copy _4) -> [success: bb1, unwind unreachable]; + _5 = const 8_usize; + _6 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } bb1: { -- _2 = _3[_4]; +- _2 = copy _3[_4]; - _1 = Add(move _2, const 0_u32); + _2 = const 42_u32; + _1 = const 42_u32; diff --git a/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-unwind.diff index 84205028d6d..436773c8556 100644 --- a/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-unwind.diff @@ -21,15 +21,15 @@ StorageLive(_4); _4 = const 2_usize; - _5 = Len(_3); -- _6 = Lt(_4, _5); -- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind continue]; +- _6 = Lt(copy _4, copy _5); +- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, copy _4) -> [success: bb1, unwind continue]; + _5 = const 8_usize; + _6 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind continue]; } bb1: { -- _2 = _3[_4]; +- _2 = copy _3[_4]; - _1 = Add(move _2, const 0_u32); + _2 = const 42_u32; + _1 = const 42_u32; diff --git a/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-abort.diff index 71635b8e9c3..f7c1c2da01f 100644 --- a/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-abort.diff @@ -21,15 +21,15 @@ StorageLive(_4); _4 = const 2_usize; - _5 = Len(_3); -- _6 = Lt(_4, _5); -- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind unreachable]; +- _6 = Lt(copy _4, copy _5); +- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, copy _4) -> [success: bb1, unwind unreachable]; + _5 = const 8_usize; + _6 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } bb1: { -- _2 = _3[_4]; +- _2 = copy _3[_4]; - _1 = Add(move _2, const 0_u32); + _2 = const 42_u32; + _1 = const 42_u32; diff --git a/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-unwind.diff index 84205028d6d..436773c8556 100644 --- a/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-unwind.diff @@ -21,15 +21,15 @@ StorageLive(_4); _4 = const 2_usize; - _5 = Len(_3); -- _6 = Lt(_4, _5); -- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind continue]; +- _6 = Lt(copy _4, copy _5); +- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, copy _4) -> [success: bb1, unwind continue]; + _5 = const 8_usize; + _6 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind continue]; } bb1: { -- _2 = _3[_4]; +- _2 = copy _3[_4]; - _1 = Add(move _2, const 0_u32); + _2 = const 42_u32; + _1 = const 42_u32; diff --git a/tests/mir-opt/const_prop/scalar_literal_propagation.main.GVN.panic-abort.diff b/tests/mir-opt/const_prop/scalar_literal_propagation.main.GVN.panic-abort.diff index 0a20fb0e59e..3c73d34474c 100644 --- a/tests/mir-opt/const_prop/scalar_literal_propagation.main.GVN.panic-abort.diff +++ b/tests/mir-opt/const_prop/scalar_literal_propagation.main.GVN.panic-abort.diff @@ -16,7 +16,7 @@ _1 = const 1_u32; StorageLive(_2); StorageLive(_3); -- _3 = _1; +- _3 = copy _1; - _2 = consume(move _3) -> [return: bb1, unwind unreachable]; + _3 = const 1_u32; + _2 = consume(const 1_u32) -> [return: bb1, unwind unreachable]; diff --git a/tests/mir-opt/const_prop/scalar_literal_propagation.main.GVN.panic-unwind.diff b/tests/mir-opt/const_prop/scalar_literal_propagation.main.GVN.panic-unwind.diff index 8b9519d3adc..0a7fddee39b 100644 --- a/tests/mir-opt/const_prop/scalar_literal_propagation.main.GVN.panic-unwind.diff +++ b/tests/mir-opt/const_prop/scalar_literal_propagation.main.GVN.panic-unwind.diff @@ -16,7 +16,7 @@ _1 = const 1_u32; StorageLive(_2); StorageLive(_3); -- _3 = _1; +- _3 = copy _1; - _2 = consume(move _3) -> [return: bb1, unwind continue]; + _3 = const 1_u32; + _2 = consume(const 1_u32) -> [return: bb1, unwind continue]; diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff index 21d91d0320a..e834a5802c3 100644 --- a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff @@ -22,24 +22,24 @@ StorageLive(_3); StorageLive(_4); _9 = const main::promoted[0]; - _4 = _9; -- _3 = _4; + _4 = copy _9; +- _3 = copy _4; - _2 = move _3 as &[u32] (PointerCoercion(Unsize)); -+ _3 = _9; -+ _2 = _9 as &[u32] (PointerCoercion(Unsize)); ++ _3 = copy _9; ++ _2 = copy _9 as &[u32] (PointerCoercion(Unsize)); StorageDead(_3); StorageLive(_6); _6 = const 1_usize; - _7 = Len((*_2)); -- _8 = Lt(_6, _7); -- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb1, unwind unreachable]; +- _8 = Lt(copy _6, copy _7); +- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind unreachable]; + _7 = const 3_usize; + _8 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind unreachable]; } bb1: { -- _1 = (*_2)[_6]; +- _1 = copy (*_2)[_6]; + _1 = const 2_u32; StorageDead(_6); StorageDead(_4); diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff index 889114c9862..55ffc501805 100644 --- a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff @@ -22,24 +22,24 @@ StorageLive(_3); StorageLive(_4); _9 = const main::promoted[0]; - _4 = _9; -- _3 = _4; + _4 = copy _9; +- _3 = copy _4; - _2 = move _3 as &[u32] (PointerCoercion(Unsize)); -+ _3 = _9; -+ _2 = _9 as &[u32] (PointerCoercion(Unsize)); ++ _3 = copy _9; ++ _2 = copy _9 as &[u32] (PointerCoercion(Unsize)); StorageDead(_3); StorageLive(_6); _6 = const 1_usize; - _7 = Len((*_2)); -- _8 = Lt(_6, _7); -- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb1, unwind continue]; +- _8 = Lt(copy _6, copy _7); +- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind continue]; + _7 = const 3_usize; + _8 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind continue]; } bb1: { -- _1 = (*_2)[_6]; +- _1 = copy (*_2)[_6]; + _1 = const 2_u32; StorageDead(_6); StorageDead(_4); diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff index 21d91d0320a..e834a5802c3 100644 --- a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff @@ -22,24 +22,24 @@ StorageLive(_3); StorageLive(_4); _9 = const main::promoted[0]; - _4 = _9; -- _3 = _4; + _4 = copy _9; +- _3 = copy _4; - _2 = move _3 as &[u32] (PointerCoercion(Unsize)); -+ _3 = _9; -+ _2 = _9 as &[u32] (PointerCoercion(Unsize)); ++ _3 = copy _9; ++ _2 = copy _9 as &[u32] (PointerCoercion(Unsize)); StorageDead(_3); StorageLive(_6); _6 = const 1_usize; - _7 = Len((*_2)); -- _8 = Lt(_6, _7); -- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb1, unwind unreachable]; +- _8 = Lt(copy _6, copy _7); +- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind unreachable]; + _7 = const 3_usize; + _8 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind unreachable]; } bb1: { -- _1 = (*_2)[_6]; +- _1 = copy (*_2)[_6]; + _1 = const 2_u32; StorageDead(_6); StorageDead(_4); diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff index 889114c9862..55ffc501805 100644 --- a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff @@ -22,24 +22,24 @@ StorageLive(_3); StorageLive(_4); _9 = const main::promoted[0]; - _4 = _9; -- _3 = _4; + _4 = copy _9; +- _3 = copy _4; - _2 = move _3 as &[u32] (PointerCoercion(Unsize)); -+ _3 = _9; -+ _2 = _9 as &[u32] (PointerCoercion(Unsize)); ++ _3 = copy _9; ++ _2 = copy _9 as &[u32] (PointerCoercion(Unsize)); StorageDead(_3); StorageLive(_6); _6 = const 1_usize; - _7 = Len((*_2)); -- _8 = Lt(_6, _7); -- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb1, unwind continue]; +- _8 = Lt(copy _6, copy _7); +- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind continue]; + _7 = const 3_usize; + _8 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind continue]; } bb1: { -- _1 = (*_2)[_6]; +- _1 = copy (*_2)[_6]; + _1 = const 2_u32; StorageDead(_6); StorageDead(_4); diff --git a/tests/mir-opt/const_prop/slice_len.rs b/tests/mir-opt/const_prop/slice_len.rs index 3d1b58965ac..46604cfe1e0 100644 --- a/tests/mir-opt/const_prop/slice_len.rs +++ b/tests/mir-opt/const_prop/slice_len.rs @@ -7,7 +7,7 @@ fn main() { // CHECK-LABEL: fn main( // CHECK: debug a => [[a:_.*]]; - // CHECK: [[slice:_.*]] = {{.*}} as &[u32] (PointerCoercion(Unsize)); + // CHECK: [[slice:_.*]] = copy {{.*}} as &[u32] (PointerCoercion(Unsize)); // CHECK: assert(const true, // CHECK: [[a]] = const 2_u32; let a = (&[1u32, 2, 3] as &[u32])[1]; diff --git a/tests/mir-opt/const_prop/switch_int.main.GVN.panic-abort.diff b/tests/mir-opt/const_prop/switch_int.main.GVN.panic-abort.diff index ee9f2d5c7f5..2339f110f5a 100644 --- a/tests/mir-opt/const_prop/switch_int.main.GVN.panic-abort.diff +++ b/tests/mir-opt/const_prop/switch_int.main.GVN.panic-abort.diff @@ -8,7 +8,7 @@ bb0: { StorageLive(_1); _1 = const 1_i32; -- switchInt(_1) -> [1: bb2, otherwise: bb1]; +- switchInt(copy _1) -> [1: bb2, otherwise: bb1]; + switchInt(const 1_i32) -> [1: bb2, otherwise: bb1]; } diff --git a/tests/mir-opt/const_prop/switch_int.main.GVN.panic-unwind.diff b/tests/mir-opt/const_prop/switch_int.main.GVN.panic-unwind.diff index 143d04ac984..49082e6ba52 100644 --- a/tests/mir-opt/const_prop/switch_int.main.GVN.panic-unwind.diff +++ b/tests/mir-opt/const_prop/switch_int.main.GVN.panic-unwind.diff @@ -8,7 +8,7 @@ bb0: { StorageLive(_1); _1 = const 1_i32; -- switchInt(_1) -> [1: bb2, otherwise: bb1]; +- switchInt(copy _1) -> [1: bb2, otherwise: bb1]; + switchInt(const 1_i32) -> [1: bb2, otherwise: bb1]; } diff --git a/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.32bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.32bit.diff index 7a289563c50..de0b1a57f80 100644 --- a/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.32bit.diff +++ b/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.32bit.diff @@ -12,7 +12,7 @@ bb0: { StorageLive(_1); - _1 = const 1_usize as std::boxed::Box (Transmute); -- _2 = (((_1.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const Never); +- _2 = copy (((_1.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const Never); + _1 = const Box::(Unique:: {{ pointer: NonNull:: {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData:: }}, std::alloc::Global); + _2 = const {0x1 as *const Never}; unreachable; diff --git a/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.64bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.64bit.diff index 7a289563c50..de0b1a57f80 100644 --- a/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.64bit.diff +++ b/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.64bit.diff @@ -12,7 +12,7 @@ bb0: { StorageLive(_1); - _1 = const 1_usize as std::boxed::Box (Transmute); -- _2 = (((_1.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const Never); +- _2 = copy (((_1.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const Never); + _1 = const Box::(Unique:: {{ pointer: NonNull:: {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData:: }}, std::alloc::Global); + _2 = const {0x1 as *const Never}; unreachable; diff --git a/tests/mir-opt/const_prop/tuple_literal_propagation.main.GVN.panic-abort.diff b/tests/mir-opt/const_prop/tuple_literal_propagation.main.GVN.panic-abort.diff index bf8fece3d37..01d86ce8717 100644 --- a/tests/mir-opt/const_prop/tuple_literal_propagation.main.GVN.panic-abort.diff +++ b/tests/mir-opt/const_prop/tuple_literal_propagation.main.GVN.panic-abort.diff @@ -17,7 +17,7 @@ + _1 = const (1_u32, 2_u32); StorageLive(_2); StorageLive(_3); -- _3 = _1; +- _3 = copy _1; - _2 = consume(move _3) -> [return: bb1, unwind unreachable]; + _3 = const (1_u32, 2_u32); + _2 = consume(const (1_u32, 2_u32)) -> [return: bb1, unwind unreachable]; diff --git a/tests/mir-opt/const_prop/tuple_literal_propagation.main.GVN.panic-unwind.diff b/tests/mir-opt/const_prop/tuple_literal_propagation.main.GVN.panic-unwind.diff index 02a75849d88..bd7d494212c 100644 --- a/tests/mir-opt/const_prop/tuple_literal_propagation.main.GVN.panic-unwind.diff +++ b/tests/mir-opt/const_prop/tuple_literal_propagation.main.GVN.panic-unwind.diff @@ -17,7 +17,7 @@ + _1 = const (1_u32, 2_u32); StorageLive(_2); StorageLive(_3); -- _3 = _1; +- _3 = copy _1; - _2 = consume(move _3) -> [return: bb1, unwind continue]; + _3 = const (1_u32, 2_u32); + _2 = consume(const (1_u32, 2_u32)) -> [return: bb1, unwind continue]; diff --git a/tests/mir-opt/const_prop/while_let_loops.change_loop_body.GVN.diff b/tests/mir-opt/const_prop/while_let_loops.change_loop_body.GVN.diff index 9548afc9d40..f830624cae7 100644 --- a/tests/mir-opt/const_prop/while_let_loops.change_loop_body.GVN.diff +++ b/tests/mir-opt/const_prop/while_let_loops.change_loop_body.GVN.diff @@ -30,7 +30,7 @@ } bb1: { -- switchInt(((_3 as Some).0: u32)) -> [0: bb2, otherwise: bb3]; +- switchInt(copy ((_3 as Some).0: u32)) -> [0: bb2, otherwise: bb3]; + switchInt(const Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: u32) -> [0: bb2, otherwise: bb3]; } diff --git a/tests/mir-opt/copy-prop/borrowed_local.borrowed.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/borrowed_local.borrowed.CopyProp.panic-abort.diff index 897592a0e2f..40e8c06f357 100644 --- a/tests/mir-opt/copy-prop/borrowed_local.borrowed.CopyProp.panic-abort.diff +++ b/tests/mir-opt/copy-prop/borrowed_local.borrowed.CopyProp.panic-abort.diff @@ -7,14 +7,14 @@ let mut _3: &T; bb0: { -- _2 = _1; +- _2 = copy _1; _3 = &_1; - _0 = opaque::<&T>(_3) -> [return: bb1, unwind unreachable]; + _0 = opaque::<&T>(copy _3) -> [return: bb1, unwind unreachable]; } bb1: { -- _0 = opaque::(_2) -> [return: bb2, unwind unreachable]; -+ _0 = opaque::(_1) -> [return: bb2, unwind unreachable]; +- _0 = opaque::(copy _2) -> [return: bb2, unwind unreachable]; ++ _0 = opaque::(copy _1) -> [return: bb2, unwind unreachable]; } bb2: { diff --git a/tests/mir-opt/copy-prop/borrowed_local.borrowed.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/borrowed_local.borrowed.CopyProp.panic-unwind.diff index 33c05af91a1..d09c96c0f2b 100644 --- a/tests/mir-opt/copy-prop/borrowed_local.borrowed.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/borrowed_local.borrowed.CopyProp.panic-unwind.diff @@ -7,14 +7,14 @@ let mut _3: &T; bb0: { -- _2 = _1; +- _2 = copy _1; _3 = &_1; - _0 = opaque::<&T>(_3) -> [return: bb1, unwind continue]; + _0 = opaque::<&T>(copy _3) -> [return: bb1, unwind continue]; } bb1: { -- _0 = opaque::(_2) -> [return: bb2, unwind continue]; -+ _0 = opaque::(_1) -> [return: bb2, unwind continue]; +- _0 = opaque::(copy _2) -> [return: bb2, unwind continue]; ++ _0 = opaque::(copy _1) -> [return: bb2, unwind continue]; } bb2: { diff --git a/tests/mir-opt/copy-prop/borrowed_local.compare_address.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/borrowed_local.compare_address.CopyProp.panic-abort.diff index 3d6b5dffba4..7e63911d843 100644 --- a/tests/mir-opt/copy-prop/borrowed_local.compare_address.CopyProp.panic-abort.diff +++ b/tests/mir-opt/copy-prop/borrowed_local.compare_address.CopyProp.panic-abort.diff @@ -11,13 +11,13 @@ bb0: { _1 = const 5_u8; _2 = &_1; - _3 = _1; + _3 = copy _1; _4 = &_3; - _0 = cmp_ref(_2, _4) -> [return: bb1, unwind unreachable]; + _0 = cmp_ref(copy _2, copy _4) -> [return: bb1, unwind unreachable]; } bb1: { - _0 = opaque::(_3) -> [return: bb2, unwind unreachable]; + _0 = opaque::(copy _3) -> [return: bb2, unwind unreachable]; } bb2: { diff --git a/tests/mir-opt/copy-prop/borrowed_local.compare_address.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/borrowed_local.compare_address.CopyProp.panic-unwind.diff index 0f29d2681de..8e5f8b21fe7 100644 --- a/tests/mir-opt/copy-prop/borrowed_local.compare_address.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/borrowed_local.compare_address.CopyProp.panic-unwind.diff @@ -11,13 +11,13 @@ bb0: { _1 = const 5_u8; _2 = &_1; - _3 = _1; + _3 = copy _1; _4 = &_3; - _0 = cmp_ref(_2, _4) -> [return: bb1, unwind continue]; + _0 = cmp_ref(copy _2, copy _4) -> [return: bb1, unwind continue]; } bb1: { - _0 = opaque::(_3) -> [return: bb2, unwind continue]; + _0 = opaque::(copy _3) -> [return: bb2, unwind continue]; } bb2: { diff --git a/tests/mir-opt/copy-prop/borrowed_local.non_freeze.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/borrowed_local.non_freeze.CopyProp.panic-abort.diff index af2aeb0dcab..99dda2a95ff 100644 --- a/tests/mir-opt/copy-prop/borrowed_local.non_freeze.CopyProp.panic-abort.diff +++ b/tests/mir-opt/copy-prop/borrowed_local.non_freeze.CopyProp.panic-abort.diff @@ -7,13 +7,13 @@ let mut _3: &T; bb0: { - _2 = _1; + _2 = copy _1; _3 = &_1; - _0 = opaque::<&T>(_3) -> [return: bb1, unwind unreachable]; + _0 = opaque::<&T>(copy _3) -> [return: bb1, unwind unreachable]; } bb1: { - _0 = opaque::(_2) -> [return: bb2, unwind unreachable]; + _0 = opaque::(copy _2) -> [return: bb2, unwind unreachable]; } bb2: { diff --git a/tests/mir-opt/copy-prop/borrowed_local.non_freeze.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/borrowed_local.non_freeze.CopyProp.panic-unwind.diff index 040ed0aec16..6eb48cd8dbc 100644 --- a/tests/mir-opt/copy-prop/borrowed_local.non_freeze.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/borrowed_local.non_freeze.CopyProp.panic-unwind.diff @@ -7,13 +7,13 @@ let mut _3: &T; bb0: { - _2 = _1; + _2 = copy _1; _3 = &_1; - _0 = opaque::<&T>(_3) -> [return: bb1, unwind continue]; + _0 = opaque::<&T>(copy _3) -> [return: bb1, unwind continue]; } bb1: { - _0 = opaque::(_2) -> [return: bb2, unwind continue]; + _0 = opaque::(copy _2) -> [return: bb2, unwind continue]; } bb2: { diff --git a/tests/mir-opt/copy-prop/borrowed_local.rs b/tests/mir-opt/copy-prop/borrowed_local.rs index dd1679513f6..8db19fbd377 100644 --- a/tests/mir-opt/copy-prop/borrowed_local.rs +++ b/tests/mir-opt/copy-prop/borrowed_local.rs @@ -21,11 +21,11 @@ fn compare_address() -> bool { // CHECK: bb0: { // CHECK-NEXT: _1 = const 5_u8; // CHECK-NEXT: _2 = &_1; - // CHECK-NEXT: _3 = _1; + // CHECK-NEXT: _3 = copy _1; // CHECK-NEXT: _4 = &_3; - // CHECK-NEXT: _0 = cmp_ref(_2, _4) + // CHECK-NEXT: _0 = cmp_ref(copy _2, copy _4) // CHECK: bb1: { - // CHECK-NEXT: _0 = opaque::(_3) + // CHECK-NEXT: _0 = opaque::(copy _3) mir! { { let a = 5_u8; @@ -51,9 +51,9 @@ fn borrowed(x: T) -> bool { // CHECK-LABEL: fn borrowed( // CHECK: bb0: { // CHECK-NEXT: _3 = &_1; - // CHECK-NEXT: _0 = opaque::<&T>(_3) + // CHECK-NEXT: _0 = opaque::<&T>(copy _3) // CHECK: bb1: { - // CHECK-NEXT: _0 = opaque::(_1) + // CHECK-NEXT: _0 = opaque::(copy _1) mir! { { let a = x; @@ -74,11 +74,11 @@ fn borrowed(x: T) -> bool { fn non_freeze(x: T) -> bool { // CHECK-LABEL: fn non_freeze( // CHECK: bb0: { - // CHECK-NEXT: _2 = _1; + // CHECK-NEXT: _2 = copy _1; // CHECK-NEXT: _3 = &_1; - // CHECK-NEXT: _0 = opaque::<&T>(_3) + // CHECK-NEXT: _0 = opaque::<&T>(copy _3) // CHECK: bb1: { - // CHECK-NEXT: _0 = opaque::(_2) + // CHECK-NEXT: _0 = opaque::(copy _2) mir! { { let a = x; diff --git a/tests/mir-opt/copy-prop/branch.foo.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/branch.foo.CopyProp.panic-abort.diff index 3334cdf92e7..c8889ee716f 100644 --- a/tests/mir-opt/copy-prop/branch.foo.CopyProp.panic-abort.diff +++ b/tests/mir-opt/copy-prop/branch.foo.CopyProp.panic-abort.diff @@ -30,7 +30,7 @@ } bb3: { - _2 = _1; + _2 = copy _1; goto -> bb6; } @@ -41,13 +41,13 @@ bb5: { StorageDead(_4); - _2 = _1; + _2 = copy _1; goto -> bb6; } bb6: { StorageDead(_3); - _0 = _2; + _0 = copy _2; StorageDead(_2); StorageDead(_1); return; diff --git a/tests/mir-opt/copy-prop/branch.foo.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/branch.foo.CopyProp.panic-unwind.diff index 2f92d8818cf..a41c28cb8c8 100644 --- a/tests/mir-opt/copy-prop/branch.foo.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/branch.foo.CopyProp.panic-unwind.diff @@ -30,7 +30,7 @@ } bb3: { - _2 = _1; + _2 = copy _1; goto -> bb6; } @@ -41,13 +41,13 @@ bb5: { StorageDead(_4); - _2 = _1; + _2 = copy _1; goto -> bb6; } bb6: { StorageDead(_3); - _0 = _2; + _0 = copy _2; StorageDead(_2); StorageDead(_1); return; diff --git a/tests/mir-opt/copy-prop/calls.multiple_edges.CopyProp.diff b/tests/mir-opt/copy-prop/calls.multiple_edges.CopyProp.diff index 4d56a8b25d3..9d0a1644ae4 100644 --- a/tests/mir-opt/copy-prop/calls.multiple_edges.CopyProp.diff +++ b/tests/mir-opt/copy-prop/calls.multiple_edges.CopyProp.diff @@ -6,7 +6,7 @@ let mut _2: u8; bb0: { - switchInt(_1) -> [1: bb1, otherwise: bb2]; + switchInt(copy _1) -> [1: bb1, otherwise: bb2]; } bb1: { @@ -14,7 +14,7 @@ } bb2: { - _0 = _2; + _0 = copy _2; return; } } diff --git a/tests/mir-opt/copy-prop/calls.nrvo.CopyProp.diff b/tests/mir-opt/copy-prop/calls.nrvo.CopyProp.diff index b5d56909b0d..29d9ec3f2fc 100644 --- a/tests/mir-opt/copy-prop/calls.nrvo.CopyProp.diff +++ b/tests/mir-opt/copy-prop/calls.nrvo.CopyProp.diff @@ -16,7 +16,7 @@ } bb1: { -- _0 = _1; +- _0 = copy _1; - StorageDead(_1); return; } diff --git a/tests/mir-opt/copy-prop/copy_propagation_arg.arg_src.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/copy_propagation_arg.arg_src.CopyProp.panic-abort.diff index 70674a912ed..280908ac63a 100644 --- a/tests/mir-opt/copy-prop/copy_propagation_arg.arg_src.CopyProp.panic-abort.diff +++ b/tests/mir-opt/copy-prop/copy_propagation_arg.arg_src.CopyProp.panic-abort.diff @@ -12,10 +12,10 @@ bb0: { - StorageLive(_2); -- _2 = _1; -+ _0 = _1; +- _2 = copy _1; ++ _0 = copy _1; _1 = const 123_i32; -- _0 = _2; +- _0 = copy _2; - StorageDead(_2); return; } diff --git a/tests/mir-opt/copy-prop/copy_propagation_arg.arg_src.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/copy_propagation_arg.arg_src.CopyProp.panic-unwind.diff index 70674a912ed..280908ac63a 100644 --- a/tests/mir-opt/copy-prop/copy_propagation_arg.arg_src.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/copy_propagation_arg.arg_src.CopyProp.panic-unwind.diff @@ -12,10 +12,10 @@ bb0: { - StorageLive(_2); -- _2 = _1; -+ _0 = _1; +- _2 = copy _1; ++ _0 = copy _1; _1 = const 123_i32; -- _0 = _2; +- _0 = copy _2; - StorageDead(_2); return; } diff --git a/tests/mir-opt/copy-prop/copy_propagation_arg.bar.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/copy_propagation_arg.bar.CopyProp.panic-abort.diff index 9ec014e2b25..eea07d5839d 100644 --- a/tests/mir-opt/copy-prop/copy_propagation_arg.bar.CopyProp.panic-abort.diff +++ b/tests/mir-opt/copy-prop/copy_propagation_arg.bar.CopyProp.panic-abort.diff @@ -10,7 +10,7 @@ bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; _2 = dummy(move _3) -> [return: bb1, unwind unreachable]; } diff --git a/tests/mir-opt/copy-prop/copy_propagation_arg.bar.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/copy_propagation_arg.bar.CopyProp.panic-unwind.diff index ef9c343a264..b0e5219913a 100644 --- a/tests/mir-opt/copy-prop/copy_propagation_arg.bar.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/copy_propagation_arg.bar.CopyProp.panic-unwind.diff @@ -10,7 +10,7 @@ bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; _2 = dummy(move _3) -> [return: bb1, unwind continue]; } diff --git a/tests/mir-opt/copy-prop/copy_propagation_arg.baz.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/copy_propagation_arg.baz.CopyProp.panic-abort.diff index 71facf91df7..5fb14902fef 100644 --- a/tests/mir-opt/copy-prop/copy_propagation_arg.baz.CopyProp.panic-abort.diff +++ b/tests/mir-opt/copy-prop/copy_propagation_arg.baz.CopyProp.panic-abort.diff @@ -8,10 +8,10 @@ bb0: { StorageLive(_2); - _2 = _1; + _2 = copy _1; _1 = move _2; StorageDead(_2); - _0 = _1; + _0 = copy _1; return; } } diff --git a/tests/mir-opt/copy-prop/copy_propagation_arg.baz.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/copy_propagation_arg.baz.CopyProp.panic-unwind.diff index 71facf91df7..5fb14902fef 100644 --- a/tests/mir-opt/copy-prop/copy_propagation_arg.baz.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/copy_propagation_arg.baz.CopyProp.panic-unwind.diff @@ -8,10 +8,10 @@ bb0: { StorageLive(_2); - _2 = _1; + _2 = copy _1; _1 = move _2; StorageDead(_2); - _0 = _1; + _0 = copy _1; return; } } diff --git a/tests/mir-opt/copy-prop/copy_propagation_arg.foo.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/copy_propagation_arg.foo.CopyProp.panic-abort.diff index 81b73e18763..685a290492e 100644 --- a/tests/mir-opt/copy-prop/copy_propagation_arg.foo.CopyProp.panic-abort.diff +++ b/tests/mir-opt/copy-prop/copy_propagation_arg.foo.CopyProp.panic-abort.diff @@ -10,7 +10,7 @@ bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; _2 = dummy(move _3) -> [return: bb1, unwind unreachable]; } diff --git a/tests/mir-opt/copy-prop/copy_propagation_arg.foo.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/copy_propagation_arg.foo.CopyProp.panic-unwind.diff index 769089e16f3..4a0601431ab 100644 --- a/tests/mir-opt/copy-prop/copy_propagation_arg.foo.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/copy_propagation_arg.foo.CopyProp.panic-unwind.diff @@ -10,7 +10,7 @@ bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; _2 = dummy(move _3) -> [return: bb1, unwind continue]; } diff --git a/tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.panic-abort.diff index 7ba85301051..1445b899dee 100644 --- a/tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.panic-abort.diff +++ b/tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.panic-abort.diff @@ -7,15 +7,15 @@ let mut _3: NotCopy; bb0: { -- _2 = _1; +- _2 = copy _1; - _0 = opaque::(move _1) -> [return: bb1, unwind unreachable]; -+ _0 = opaque::(_1) -> [return: bb1, unwind unreachable]; ++ _0 = opaque::(copy _1) -> [return: bb1, unwind unreachable]; } bb1: { - _3 = move _2; -- _0 = opaque::(_3) -> [return: bb2, unwind unreachable]; -+ _0 = opaque::(_1) -> [return: bb2, unwind unreachable]; +- _0 = opaque::(copy _3) -> [return: bb2, unwind unreachable]; ++ _0 = opaque::(copy _1) -> [return: bb2, unwind unreachable]; } bb2: { diff --git a/tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.panic-unwind.diff index 7ba85301051..1445b899dee 100644 --- a/tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.panic-unwind.diff @@ -7,15 +7,15 @@ let mut _3: NotCopy; bb0: { -- _2 = _1; +- _2 = copy _1; - _0 = opaque::(move _1) -> [return: bb1, unwind unreachable]; -+ _0 = opaque::(_1) -> [return: bb1, unwind unreachable]; ++ _0 = opaque::(copy _1) -> [return: bb1, unwind unreachable]; } bb1: { - _3 = move _2; -- _0 = opaque::(_3) -> [return: bb2, unwind unreachable]; -+ _0 = opaque::(_1) -> [return: bb2, unwind unreachable]; +- _0 = opaque::(copy _3) -> [return: bb2, unwind unreachable]; ++ _0 = opaque::(copy _1) -> [return: bb2, unwind unreachable]; } bb2: { diff --git a/tests/mir-opt/copy-prop/cycle.main.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/cycle.main.CopyProp.panic-abort.diff index 8f97c4e439e..d133091e6a4 100644 --- a/tests/mir-opt/copy-prop/cycle.main.CopyProp.panic-abort.diff +++ b/tests/mir-opt/copy-prop/cycle.main.CopyProp.panic-abort.diff @@ -27,17 +27,17 @@ bb1: { - StorageLive(_2); - _2 = _1; + _2 = copy _1; - StorageLive(_3); -- _3 = _2; +- _3 = copy _2; - StorageLive(_4); -- _4 = _3; +- _4 = copy _3; - _1 = move _4; - StorageDead(_4); -+ _1 = _2; ++ _1 = copy _2; StorageLive(_5); StorageLive(_6); - _6 = _1; + _6 = copy _1; _5 = std::mem::drop::(move _6) -> [return: bb2, unwind unreachable]; } diff --git a/tests/mir-opt/copy-prop/cycle.main.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/cycle.main.CopyProp.panic-unwind.diff index e343b78924a..bd4ad737cec 100644 --- a/tests/mir-opt/copy-prop/cycle.main.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/cycle.main.CopyProp.panic-unwind.diff @@ -27,17 +27,17 @@ bb1: { - StorageLive(_2); - _2 = _1; + _2 = copy _1; - StorageLive(_3); -- _3 = _2; +- _3 = copy _2; - StorageLive(_4); -- _4 = _3; +- _4 = copy _3; - _1 = move _4; - StorageDead(_4); -+ _1 = _2; ++ _1 = copy _2; StorageLive(_5); StorageLive(_6); - _6 = _1; + _6 = copy _1; _5 = std::mem::drop::(move _6) -> [return: bb2, unwind continue]; } diff --git a/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.panic-abort.mir b/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.panic-abort.mir index 02b88d14003..4781fdfd902 100644 --- a/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.panic-abort.mir +++ b/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.panic-abort.mir @@ -11,11 +11,11 @@ fn f(_1: usize) -> usize { } bb0: { - _2 = _1; + _2 = copy _1; _1 = const 5_usize; - _1 = _2; + _1 = copy _2; StorageLive(_4); - _4 = _1; + _4 = copy _1; _0 = id::(move _4) -> [return: bb1, unwind unreachable]; } diff --git a/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.panic-unwind.mir b/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.panic-unwind.mir index f8c285ff384..f5fded45c13 100644 --- a/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.panic-unwind.mir +++ b/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.panic-unwind.mir @@ -11,11 +11,11 @@ fn f(_1: usize) -> usize { } bb0: { - _2 = _1; + _2 = copy _1; _1 = const 5_usize; - _1 = _2; + _1 = copy _2; StorageLive(_4); - _4 = _1; + _4 = copy _1; _0 = id::(move _4) -> [return: bb1, unwind continue]; } diff --git a/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.panic-abort.mir b/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.panic-abort.mir index 02b88d14003..4781fdfd902 100644 --- a/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.panic-abort.mir +++ b/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.panic-abort.mir @@ -11,11 +11,11 @@ fn f(_1: usize) -> usize { } bb0: { - _2 = _1; + _2 = copy _1; _1 = const 5_usize; - _1 = _2; + _1 = copy _2; StorageLive(_4); - _4 = _1; + _4 = copy _1; _0 = id::(move _4) -> [return: bb1, unwind unreachable]; } diff --git a/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.panic-unwind.mir b/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.panic-unwind.mir index f8c285ff384..f5fded45c13 100644 --- a/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.panic-unwind.mir +++ b/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.panic-unwind.mir @@ -11,11 +11,11 @@ fn f(_1: usize) -> usize { } bb0: { - _2 = _1; + _2 = copy _1; _1 = const 5_usize; - _1 = _2; + _1 = copy _2; StorageLive(_4); - _4 = _1; + _4 = copy _1; _0 = id::(move _4) -> [return: bb1, unwind continue]; } diff --git a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-abort.diff index 51390e2abbe..f4411886f9a 100644 --- a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-abort.diff +++ b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-abort.diff @@ -88,15 +88,15 @@ bb6: { - StorageLive(_16); - _16 = ((_11 as Some).0: usize); + _16 = copy ((_11 as Some).0: usize); StorageLive(_17); - StorageLive(_18); -- _18 = _16; +- _18 = copy _16; _19 = Len(_2); -- _20 = Lt(_18, _19); -- assert(move _20, "index out of bounds: the length is {} but the index is {}", move _19, _18) -> [success: bb8, unwind unreachable]; -+ _20 = Lt(_16, _19); -+ assert(move _20, "index out of bounds: the length is {} but the index is {}", move _19, _16) -> [success: bb8, unwind unreachable]; +- _20 = Lt(copy _18, copy _19); +- assert(move _20, "index out of bounds: the length is {} but the index is {}", move _19, copy _18) -> [success: bb8, unwind unreachable]; ++ _20 = Lt(copy _16, copy _19); ++ assert(move _20, "index out of bounds: the length is {} but the index is {}", move _19, copy _16) -> [success: bb8, unwind unreachable]; } bb7: { @@ -112,9 +112,9 @@ } bb8: { -- _17 = _2[_18]; -+ _17 = _2[_16]; - _1 = Add(_1, move _17); +- _17 = copy _2[_18]; ++ _17 = copy _2[_16]; + _1 = Add(copy _1, move _17); StorageDead(_17); - StorageDead(_18); - _10 = const (); diff --git a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-unwind.diff index 8a2cbb68824..833588aa4e9 100644 --- a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-unwind.diff @@ -88,15 +88,15 @@ bb6: { - StorageLive(_16); - _16 = ((_11 as Some).0: usize); + _16 = copy ((_11 as Some).0: usize); StorageLive(_17); - StorageLive(_18); -- _18 = _16; +- _18 = copy _16; _19 = Len(_2); -- _20 = Lt(_18, _19); -- assert(move _20, "index out of bounds: the length is {} but the index is {}", move _19, _18) -> [success: bb8, unwind continue]; -+ _20 = Lt(_16, _19); -+ assert(move _20, "index out of bounds: the length is {} but the index is {}", move _19, _16) -> [success: bb8, unwind continue]; +- _20 = Lt(copy _18, copy _19); +- assert(move _20, "index out of bounds: the length is {} but the index is {}", move _19, copy _18) -> [success: bb8, unwind continue]; ++ _20 = Lt(copy _16, copy _19); ++ assert(move _20, "index out of bounds: the length is {} but the index is {}", move _19, copy _16) -> [success: bb8, unwind continue]; } bb7: { @@ -112,9 +112,9 @@ } bb8: { -- _17 = _2[_18]; -+ _17 = _2[_16]; - _1 = Add(_1, move _17); +- _17 = copy _2[_18]; ++ _17 = copy _2[_16]; + _1 = Add(copy _1, move _17); StorageDead(_17); - StorageDead(_18); - _10 = const (); diff --git a/tests/mir-opt/copy-prop/move_arg.f.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/move_arg.f.CopyProp.panic-abort.diff index cf04f213efb..da9904bfa01 100644 --- a/tests/mir-opt/copy-prop/move_arg.f.CopyProp.panic-abort.diff +++ b/tests/mir-opt/copy-prop/move_arg.f.CopyProp.panic-abort.diff @@ -15,14 +15,14 @@ bb0: { - StorageLive(_2); -- _2 = _1; +- _2 = copy _1; StorageLive(_3); - StorageLive(_4); -- _4 = _1; +- _4 = copy _1; - StorageLive(_5); -- _5 = _2; +- _5 = copy _2; - _3 = g::(move _4, move _5) -> [return: bb1, unwind unreachable]; -+ _3 = g::(_1, _1) -> [return: bb1, unwind unreachable]; ++ _3 = g::(copy _1, copy _1) -> [return: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/copy-prop/move_arg.f.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/move_arg.f.CopyProp.panic-unwind.diff index 0c6a3c6d5c9..9b0de655bd2 100644 --- a/tests/mir-opt/copy-prop/move_arg.f.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/move_arg.f.CopyProp.panic-unwind.diff @@ -15,14 +15,14 @@ bb0: { - StorageLive(_2); -- _2 = _1; +- _2 = copy _1; StorageLive(_3); - StorageLive(_4); -- _4 = _1; +- _4 = copy _1; - StorageLive(_5); -- _5 = _2; +- _5 = copy _2; - _3 = g::(move _4, move _5) -> [return: bb1, unwind continue]; -+ _3 = g::(_1, _1) -> [return: bb1, unwind continue]; ++ _3 = g::(copy _1, copy _1) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/copy-prop/move_projection.f.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/move_projection.f.CopyProp.panic-abort.diff index b2b89968d70..973bcd6de83 100644 --- a/tests/mir-opt/copy-prop/move_projection.f.CopyProp.panic-abort.diff +++ b/tests/mir-opt/copy-prop/move_projection.f.CopyProp.panic-abort.diff @@ -7,11 +7,11 @@ let mut _3: u8; bb0: { -- _2 = _1; +- _2 = copy _1; - _3 = move (_2.0: u8); - _0 = opaque::(move _1) -> [return: bb1, unwind unreachable]; -+ _3 = (_1.0: u8); -+ _0 = opaque::(_1) -> [return: bb1, unwind unreachable]; ++ _3 = copy (_1.0: u8); ++ _0 = opaque::(copy _1) -> [return: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/copy-prop/move_projection.f.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/move_projection.f.CopyProp.panic-unwind.diff index b2b89968d70..973bcd6de83 100644 --- a/tests/mir-opt/copy-prop/move_projection.f.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/move_projection.f.CopyProp.panic-unwind.diff @@ -7,11 +7,11 @@ let mut _3: u8; bb0: { -- _2 = _1; +- _2 = copy _1; - _3 = move (_2.0: u8); - _0 = opaque::(move _1) -> [return: bb1, unwind unreachable]; -+ _3 = (_1.0: u8); -+ _0 = opaque::(_1) -> [return: bb1, unwind unreachable]; ++ _3 = copy (_1.0: u8); ++ _0 = opaque::(copy _1) -> [return: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/copy-prop/mutate_through_pointer.f.CopyProp.diff b/tests/mir-opt/copy-prop/mutate_through_pointer.f.CopyProp.diff index 7f6802beeae..f96be627129 100644 --- a/tests/mir-opt/copy-prop/mutate_through_pointer.f.CopyProp.diff +++ b/tests/mir-opt/copy-prop/mutate_through_pointer.f.CopyProp.diff @@ -8,11 +8,11 @@ let mut _4: *mut bool; bb0: { - _2 = _1; + _2 = copy _1; _3 = &raw const _2; _4 = &raw mut (*_3); (*_4) = const false; - _0 = _1; + _0 = copy _1; return; } } diff --git a/tests/mir-opt/copy-prop/non_dominate.f.CopyProp.diff b/tests/mir-opt/copy-prop/non_dominate.f.CopyProp.diff index 5bf2335943c..6955d694e5a 100644 --- a/tests/mir-opt/copy-prop/non_dominate.f.CopyProp.diff +++ b/tests/mir-opt/copy-prop/non_dominate.f.CopyProp.diff @@ -11,18 +11,18 @@ } bb1: { - _3 = _1; - switchInt(_3) -> [0: bb3, otherwise: bb2]; + _3 = copy _1; + switchInt(copy _3) -> [0: bb3, otherwise: bb2]; } bb2: { - _2 = _3; + _2 = copy _3; _1 = const false; goto -> bb1; } bb3: { - _0 = _2; + _0 = copy _2; return; } } diff --git a/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.panic-abort.diff index ef30ac2fc8c..676c5cee343 100644 --- a/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.panic-abort.diff +++ b/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.panic-abort.diff @@ -30,12 +30,12 @@ _3 = &mut (*_4); StorageDead(_4); - StorageLive(_5); -- _5 = _2; +- _5 = copy _2; StorageLive(_6); - StorageLive(_7); -- _7 = _5; +- _7 = copy _5; - _6 = opaque::<*mut u8>(move _7) -> [return: bb1, unwind unreachable]; -+ _6 = opaque::<*mut u8>(_2) -> [return: bb1, unwind unreachable]; ++ _6 = opaque::<*mut u8>(copy _2) -> [return: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.panic-unwind.diff index a743a3e829a..ca2232ce54a 100644 --- a/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.panic-unwind.diff @@ -30,12 +30,12 @@ _3 = &mut (*_4); StorageDead(_4); - StorageLive(_5); -- _5 = _2; +- _5 = copy _2; StorageLive(_6); - StorageLive(_7); -- _7 = _5; +- _7 = copy _5; - _6 = opaque::<*mut u8>(move _7) -> [return: bb1, unwind continue]; -+ _6 = opaque::<*mut u8>(_2) -> [return: bb1, unwind continue]; ++ _6 = opaque::<*mut u8>(copy _2) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.panic-abort.diff index 2de6f85ce64..1968696905f 100644 --- a/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.panic-abort.diff +++ b/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.panic-abort.diff @@ -26,12 +26,12 @@ StorageLive(_3); _3 = &raw mut (*_2); - StorageLive(_4); -- _4 = _2; +- _4 = copy _2; StorageLive(_5); - StorageLive(_6); -- _6 = _4; +- _6 = copy _4; - _5 = opaque::<*mut u8>(move _6) -> [return: bb1, unwind unreachable]; -+ _5 = opaque::<*mut u8>(_2) -> [return: bb1, unwind unreachable]; ++ _5 = opaque::<*mut u8>(copy _2) -> [return: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.panic-unwind.diff index 2afec4898bc..9a3c9665bc8 100644 --- a/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.panic-unwind.diff @@ -26,12 +26,12 @@ StorageLive(_3); _3 = &raw mut (*_2); - StorageLive(_4); -- _4 = _2; +- _4 = copy _2; StorageLive(_5); - StorageLive(_6); -- _6 = _4; +- _6 = copy _4; - _5 = opaque::<*mut u8>(move _6) -> [return: bb1, unwind continue]; -+ _5 = opaque::<*mut u8>(_2) -> [return: bb1, unwind continue]; ++ _5 = opaque::<*mut u8>(copy _2) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/copy-prop/reborrow.rs b/tests/mir-opt/copy-prop/reborrow.rs index 2f1720556cd..51a1f92cde2 100644 --- a/tests/mir-opt/copy-prop/reborrow.rs +++ b/tests/mir-opt/copy-prop/reborrow.rs @@ -3,8 +3,6 @@ // Check that CopyProp considers reborrows as not mutating the pointer. //@ test-mir-pass: CopyProp -#![feature(raw_ref_op)] - #[inline(never)] fn opaque(_: impl Sized) {} diff --git a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff index 3d791734f46..eeeac70b5b8 100644 --- a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff @@ -71,33 +71,33 @@ bb5: { + Coverage::ExpressionUsed(2); StorageLive(_9); - _9 = ((_1 as A).0: u32); + _9 = copy ((_1 as A).0: u32); StorageLive(_10); - _10 = _9; + _10 = copy _9; _0 = consume(move _10) -> [return: bb12, unwind: bb14]; } bb6: { StorageLive(_7); - _7 = ((_1 as B).0: u32); + _7 = copy ((_1 as B).0: u32); StorageLive(_8); - _8 = _7; + _8 = copy _7; _0 = consume(move _8) -> [return: bb11, unwind: bb14]; } bb7: { StorageLive(_5); - _5 = ((_1 as C).0: u32); + _5 = copy ((_1 as C).0: u32); StorageLive(_6); - _6 = _5; + _6 = copy _5; _0 = consume(move _6) -> [return: bb10, unwind: bb14]; } bb8: { StorageLive(_3); - _3 = ((_1 as D).0: u32); + _3 = copy ((_1 as D).0: u32); StorageLive(_4); - _4 = _3; + _4 = copy _3; _0 = consume(move _4) -> [return: bb9, unwind: bb14]; } diff --git a/tests/mir-opt/dataflow-const-prop/aggregate_copy.foo.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/aggregate_copy.foo.DataflowConstProp.diff index 3b739a25cb8..8dd34d84580 100644 --- a/tests/mir-opt/dataflow-const-prop/aggregate_copy.foo.DataflowConstProp.diff +++ b/tests/mir-opt/dataflow-const-prop/aggregate_copy.foo.DataflowConstProp.diff @@ -22,14 +22,14 @@ StorageLive(_1); _1 = const Foo; StorageLive(_2); -- _2 = _1; +- _2 = copy _1; + _2 = const (5_u32, 3_u32); StorageLive(_3); -- _3 = (_2.1: u32); +- _3 = copy (_2.1: u32); + _3 = const 3_u32; StorageLive(_4); StorageLive(_5); -- _5 = _3; +- _5 = copy _3; - _4 = Ge(move _5, const 2_u32); - switchInt(move _4) -> [0: bb2, otherwise: bb1]; + _5 = const 3_u32; @@ -39,7 +39,7 @@ bb1: { StorageDead(_5); -- _0 = (_2.0: u32); +- _0 = copy (_2.0: u32); + _0 = const 5_u32; goto -> bb3; } diff --git a/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.32bit.panic-abort.diff index 212ddc5b154..a46daef435f 100644 --- a/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.32bit.panic-abort.diff @@ -19,16 +19,16 @@ StorageLive(_3); _3 = const 2_usize; - _4 = Len(_2); -- _5 = Lt(_3, _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind unreachable]; +- _5 = Lt(copy _3, copy _4); +- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind unreachable]; + _4 = const 4_usize; + _5 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } bb1: { -- _1 = _2[_3]; -+ _1 = _2[2 of 3]; +- _1 = copy _2[_3]; ++ _1 = copy _2[2 of 3]; StorageDead(_3); StorageDead(_2); _0 = const (); diff --git a/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.32bit.panic-unwind.diff index 5c53d4f4461..1a4e15b45fa 100644 --- a/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.32bit.panic-unwind.diff @@ -19,16 +19,16 @@ StorageLive(_3); _3 = const 2_usize; - _4 = Len(_2); -- _5 = Lt(_3, _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind continue]; +- _5 = Lt(copy _3, copy _4); +- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind continue]; + _4 = const 4_usize; + _5 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind continue]; } bb1: { -- _1 = _2[_3]; -+ _1 = _2[2 of 3]; +- _1 = copy _2[_3]; ++ _1 = copy _2[2 of 3]; StorageDead(_3); StorageDead(_2); _0 = const (); diff --git a/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.64bit.panic-abort.diff index 212ddc5b154..a46daef435f 100644 --- a/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.64bit.panic-abort.diff @@ -19,16 +19,16 @@ StorageLive(_3); _3 = const 2_usize; - _4 = Len(_2); -- _5 = Lt(_3, _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind unreachable]; +- _5 = Lt(copy _3, copy _4); +- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind unreachable]; + _4 = const 4_usize; + _5 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } bb1: { -- _1 = _2[_3]; -+ _1 = _2[2 of 3]; +- _1 = copy _2[_3]; ++ _1 = copy _2[2 of 3]; StorageDead(_3); StorageDead(_2); _0 = const (); diff --git a/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.64bit.panic-unwind.diff index 5c53d4f4461..1a4e15b45fa 100644 --- a/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.64bit.panic-unwind.diff @@ -19,16 +19,16 @@ StorageLive(_3); _3 = const 2_usize; - _4 = Len(_2); -- _5 = Lt(_3, _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind continue]; +- _5 = Lt(copy _3, copy _4); +- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind continue]; + _4 = const 4_usize; + _5 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind continue]; } bb1: { -- _1 = _2[_3]; -+ _1 = _2[2 of 3]; +- _1 = copy _2[_3]; ++ _1 = copy _2[2 of 3]; StorageDead(_3); StorageDead(_2); _0 = const (); diff --git a/tests/mir-opt/dataflow-const-prop/array_index.rs b/tests/mir-opt/dataflow-const-prop/array_index.rs index daf9c7729c6..e442ef99f79 100644 --- a/tests/mir-opt/dataflow-const-prop/array_index.rs +++ b/tests/mir-opt/dataflow-const-prop/array_index.rs @@ -16,6 +16,6 @@ fn main() { // CHECK: {{_.*}} = const 4_usize; // CHECK: {{_.*}} = const true; // CHECK: assert(const true - // CHECK: [[x]] = [[array_lit]][2 of 3]; + // CHECK: [[x]] = copy [[array_lit]][2 of 3]; let x: u32 = [0, 1, 2, 3][2]; } diff --git a/tests/mir-opt/dataflow-const-prop/boolean_identities.test.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/boolean_identities.test.DataflowConstProp.diff index 5440c38ce4b..89175fbad5c 100644 --- a/tests/mir-opt/dataflow-const-prop/boolean_identities.test.DataflowConstProp.diff +++ b/tests/mir-opt/dataflow-const-prop/boolean_identities.test.DataflowConstProp.diff @@ -13,13 +13,13 @@ bb0: { StorageLive(_3); StorageLive(_4); - _4 = _2; + _4 = copy _2; - _3 = BitOr(move _4, const true); + _3 = const true; StorageDead(_4); StorageLive(_5); StorageLive(_6); - _6 = _1; + _6 = copy _1; - _5 = BitAnd(move _6, const false); + _5 = const false; StorageDead(_6); diff --git a/tests/mir-opt/dataflow-const-prop/cast.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/cast.main.DataflowConstProp.diff index 0ca446c89f2..f2c262f9fe2 100644 --- a/tests/mir-opt/dataflow-const-prop/cast.main.DataflowConstProp.diff +++ b/tests/mir-opt/dataflow-const-prop/cast.main.DataflowConstProp.diff @@ -20,7 +20,7 @@ StorageLive(_2); StorageLive(_3); StorageLive(_4); -- _4 = _1; +- _4 = copy _1; - _3 = move _4 as u8 (IntToInt); + _4 = const 257_i32; + _3 = const 1_u8; diff --git a/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-abort.diff index 79ea5561748..867e768790f 100644 --- a/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-abort.diff @@ -36,11 +36,11 @@ _2 = const 2_i32; StorageLive(_3); StorageLive(_4); -- _4 = _1; +- _4 = copy _1; + _4 = const 1_i32; StorageLive(_5); -- _5 = _2; -- _6 = AddWithOverflow(_4, _5); +- _5 = copy _2; +- _6 = AddWithOverflow(copy _4, copy _5); - assert(!move (_6.1: bool), "attempt to compute `{} + {}`, which would overflow", move _4, move _5) -> [success: bb1, unwind unreachable]; + _5 = const 2_i32; + _6 = const (3_i32, false); @@ -56,8 +56,8 @@ _7 = const core::num::::MAX; StorageLive(_8); StorageLive(_9); -- _9 = _7; -- _10 = AddWithOverflow(_9, const 1_i32); +- _9 = copy _7; +- _10 = AddWithOverflow(copy _9, const 1_i32); - assert(!move (_10.1: bool), "attempt to compute `{} + {}`, which would overflow", move _9, const 1_i32) -> [success: bb2, unwind unreachable]; + _9 = const i32::MAX; + _10 = const (i32::MIN, true); diff --git a/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-unwind.diff index bd22c50dd8f..c22edaaec40 100644 --- a/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-unwind.diff @@ -36,11 +36,11 @@ _2 = const 2_i32; StorageLive(_3); StorageLive(_4); -- _4 = _1; +- _4 = copy _1; + _4 = const 1_i32; StorageLive(_5); -- _5 = _2; -- _6 = AddWithOverflow(_4, _5); +- _5 = copy _2; +- _6 = AddWithOverflow(copy _4, copy _5); - assert(!move (_6.1: bool), "attempt to compute `{} + {}`, which would overflow", move _4, move _5) -> [success: bb1, unwind continue]; + _5 = const 2_i32; + _6 = const (3_i32, false); @@ -56,8 +56,8 @@ _7 = const core::num::::MAX; StorageLive(_8); StorageLive(_9); -- _9 = _7; -- _10 = AddWithOverflow(_9, const 1_i32); +- _9 = copy _7; +- _10 = AddWithOverflow(copy _9, const 1_i32); - assert(!move (_10.1: bool), "attempt to compute `{} + {}`, which would overflow", move _9, const 1_i32) -> [success: bb2, unwind continue]; + _9 = const i32::MAX; + _10 = const (i32::MIN, true); diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff index 9d96e895c8a..c7870a7902b 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff @@ -50,7 +50,7 @@ StorageLive(_6); StorageLive(_7); - _7 = AlignOf([bool; 0]); -- _6 = _7 as *mut [bool; 0] (Transmute); +- _6 = copy _7 as *mut [bool; 0] (Transmute); + _7 = const 1_usize; + _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); @@ -67,7 +67,7 @@ bb2: { StorageLive(_10); -- _10 = _6 as *mut () (PtrToPtr); +- _10 = copy _6 as *mut () (PtrToPtr); - _9 = NonNull::::new_unchecked::precondition_check(move _10) -> [return: bb3, unwind unreachable]; + _10 = const {0x1 as *mut ()}; + _9 = NonNull::::new_unchecked::precondition_check(const {0x1 as *mut ()}) -> [return: bb3, unwind unreachable]; @@ -80,8 +80,8 @@ bb4: { StorageDead(_8); -- _11 = _6 as *const [bool; 0] (PtrToPtr); -- _5 = NonNull::<[bool; 0]> { pointer: _11 }; +- _11 = copy _6 as *const [bool; 0] (PtrToPtr); +- _5 = NonNull::<[bool; 0]> { pointer: copy _11 }; + _11 = const {0x1 as *const [bool; 0]}; + _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; StorageDead(_11); @@ -92,7 +92,7 @@ - _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); + _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; StorageDead(_4); -- _2 = Box::<[bool]>(_3, const std::alloc::Global); +- _2 = Box::<[bool]>(copy _3, const std::alloc::Global); + _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); StorageDead(_9); StorageDead(_3); diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff index 0bdff584b01..f5de7a361bc 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff @@ -50,7 +50,7 @@ StorageLive(_6); StorageLive(_7); - _7 = AlignOf([bool; 0]); -- _6 = _7 as *mut [bool; 0] (Transmute); +- _6 = copy _7 as *mut [bool; 0] (Transmute); + _7 = const 1_usize; + _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); @@ -71,7 +71,7 @@ bb3: { StorageLive(_10); -- _10 = _6 as *mut () (PtrToPtr); +- _10 = copy _6 as *mut () (PtrToPtr); - _9 = NonNull::::new_unchecked::precondition_check(move _10) -> [return: bb4, unwind unreachable]; + _10 = const {0x1 as *mut ()}; + _9 = NonNull::::new_unchecked::precondition_check(const {0x1 as *mut ()}) -> [return: bb4, unwind unreachable]; @@ -84,8 +84,8 @@ bb5: { StorageDead(_8); -- _11 = _6 as *const [bool; 0] (PtrToPtr); -- _5 = NonNull::<[bool; 0]> { pointer: _11 }; +- _11 = copy _6 as *const [bool; 0] (PtrToPtr); +- _5 = NonNull::<[bool; 0]> { pointer: copy _11 }; + _11 = const {0x1 as *const [bool; 0]}; + _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; StorageDead(_11); @@ -96,7 +96,7 @@ - _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); + _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; StorageDead(_4); -- _2 = Box::<[bool]>(_3, const std::alloc::Global); +- _2 = Box::<[bool]>(copy _3, const std::alloc::Global); + _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); StorageDead(_9); StorageDead(_3); diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff index 99e96fe5d70..3b0bc6377da 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff @@ -50,7 +50,7 @@ StorageLive(_6); StorageLive(_7); - _7 = AlignOf([bool; 0]); -- _6 = _7 as *mut [bool; 0] (Transmute); +- _6 = copy _7 as *mut [bool; 0] (Transmute); + _7 = const 1_usize; + _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); @@ -67,7 +67,7 @@ bb2: { StorageLive(_10); -- _10 = _6 as *mut () (PtrToPtr); +- _10 = copy _6 as *mut () (PtrToPtr); - _9 = NonNull::::new_unchecked::precondition_check(move _10) -> [return: bb3, unwind unreachable]; + _10 = const {0x1 as *mut ()}; + _9 = NonNull::::new_unchecked::precondition_check(const {0x1 as *mut ()}) -> [return: bb3, unwind unreachable]; @@ -80,8 +80,8 @@ bb4: { StorageDead(_8); -- _11 = _6 as *const [bool; 0] (PtrToPtr); -- _5 = NonNull::<[bool; 0]> { pointer: _11 }; +- _11 = copy _6 as *const [bool; 0] (PtrToPtr); +- _5 = NonNull::<[bool; 0]> { pointer: copy _11 }; + _11 = const {0x1 as *const [bool; 0]}; + _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; StorageDead(_11); @@ -92,7 +92,7 @@ - _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); + _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; StorageDead(_4); -- _2 = Box::<[bool]>(_3, const std::alloc::Global); +- _2 = Box::<[bool]>(copy _3, const std::alloc::Global); + _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); StorageDead(_9); StorageDead(_3); diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff index 5eefabeac38..5dd7ad9a117 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff @@ -50,7 +50,7 @@ StorageLive(_6); StorageLive(_7); - _7 = AlignOf([bool; 0]); -- _6 = _7 as *mut [bool; 0] (Transmute); +- _6 = copy _7 as *mut [bool; 0] (Transmute); + _7 = const 1_usize; + _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); @@ -71,7 +71,7 @@ bb3: { StorageLive(_10); -- _10 = _6 as *mut () (PtrToPtr); +- _10 = copy _6 as *mut () (PtrToPtr); - _9 = NonNull::::new_unchecked::precondition_check(move _10) -> [return: bb4, unwind unreachable]; + _10 = const {0x1 as *mut ()}; + _9 = NonNull::::new_unchecked::precondition_check(const {0x1 as *mut ()}) -> [return: bb4, unwind unreachable]; @@ -84,8 +84,8 @@ bb5: { StorageDead(_8); -- _11 = _6 as *const [bool; 0] (PtrToPtr); -- _5 = NonNull::<[bool; 0]> { pointer: _11 }; +- _11 = copy _6 as *const [bool; 0] (PtrToPtr); +- _5 = NonNull::<[bool; 0]> { pointer: copy _11 }; + _11 = const {0x1 as *const [bool; 0]}; + _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; StorageDead(_11); @@ -96,7 +96,7 @@ - _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); + _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; StorageDead(_4); -- _2 = Box::<[bool]>(_3, const std::alloc::Global); +- _2 = Box::<[bool]>(copy _3, const std::alloc::Global); + _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); StorageDead(_9); StorageDead(_3); diff --git a/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.32bit.diff index 9da1caf9004..ef3b24cd440 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.32bit.diff @@ -37,16 +37,16 @@ bb2: { StorageLive(_5); - _5 = ((_1 as V2).0: i32); - _2 = _5; + _5 = copy ((_1 as V2).0: i32); + _2 = copy _5; StorageDead(_5); goto -> bb4; } bb3: { StorageLive(_4); -- _4 = ((_1 as V1).0: i32); -- _2 = _4; +- _4 = copy ((_1 as V1).0: i32); +- _2 = copy _4; + _4 = const 0_i32; + _2 = const 0_i32; StorageDead(_4); diff --git a/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.64bit.diff index 9da1caf9004..ef3b24cd440 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.64bit.diff @@ -37,16 +37,16 @@ bb2: { StorageLive(_5); - _5 = ((_1 as V2).0: i32); - _2 = _5; + _5 = copy ((_1 as V2).0: i32); + _2 = copy _5; StorageDead(_5); goto -> bb4; } bb3: { StorageLive(_4); -- _4 = ((_1 as V1).0: i32); -- _2 = _4; +- _4 = copy ((_1 as V1).0: i32); +- _2 = copy _4; + _4 = const 0_i32; + _2 = const 0_i32; StorageDead(_4); diff --git a/tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.32bit.diff index 10d33767c90..db8352bcbcf 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.32bit.diff @@ -28,13 +28,13 @@ bb0: { StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; switchInt(move _4) -> [0: bb2, otherwise: bb1]; } bb1: { StorageLive(_5); - _5 = _2; + _5 = copy _2; _3 = Option::::Some(move _5); StorageDead(_5); goto -> bb3; @@ -63,15 +63,15 @@ bb6: { StorageLive(_8); - _8 = ((_3 as Some).0: u8); - _6 = _8; + _8 = copy ((_3 as Some).0: u8); + _6 = copy _8; StorageDead(_8); goto -> bb7; } bb7: { StorageLive(_9); - _9 = _6; + _9 = copy _6; _0 = const (); StorageDead(_9); StorageDead(_6); diff --git a/tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.64bit.diff index 10d33767c90..db8352bcbcf 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.64bit.diff @@ -28,13 +28,13 @@ bb0: { StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; switchInt(move _4) -> [0: bb2, otherwise: bb1]; } bb1: { StorageLive(_5); - _5 = _2; + _5 = copy _2; _3 = Option::::Some(move _5); StorageDead(_5); goto -> bb3; @@ -63,15 +63,15 @@ bb6: { StorageLive(_8); - _8 = ((_3 as Some).0: u8); - _6 = _8; + _8 = copy ((_3 as Some).0: u8); + _6 = copy _8; StorageDead(_8); goto -> bb7; } bb7: { StorageLive(_9); - _9 = _6; + _9 = copy _6; _0 = const (); StorageDead(_9); StorageDead(_6); diff --git a/tests/mir-opt/dataflow-const-prop/enum.mutate_discriminant.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/enum.mutate_discriminant.DataflowConstProp.32bit.diff index 960e69ee916..e2cd73404be 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.mutate_discriminant.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.mutate_discriminant.DataflowConstProp.32bit.diff @@ -10,7 +10,7 @@ discriminant(_1) = 1; (((_1 as variant#1).0: NonZeroUsize).0: usize) = const 0_usize; _2 = discriminant(_1); - switchInt(_2) -> [0: bb1, otherwise: bb2]; + switchInt(copy _2) -> [0: bb1, otherwise: bb2]; } bb1: { diff --git a/tests/mir-opt/dataflow-const-prop/enum.mutate_discriminant.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/enum.mutate_discriminant.DataflowConstProp.64bit.diff index 960e69ee916..e2cd73404be 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.mutate_discriminant.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.mutate_discriminant.DataflowConstProp.64bit.diff @@ -10,7 +10,7 @@ discriminant(_1) = 1; (((_1 as variant#1).0: NonZeroUsize).0: usize) = const 0_usize; _2 = discriminant(_1); - switchInt(_2) -> [0: bb1, otherwise: bb2]; + switchInt(copy _2) -> [0: bb1, otherwise: bb2]; } bb1: { diff --git a/tests/mir-opt/dataflow-const-prop/enum.rs b/tests/mir-opt/dataflow-const-prop/enum.rs index 37304e3a270..207e29e63df 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.rs +++ b/tests/mir-opt/dataflow-const-prop/enum.rs @@ -73,7 +73,7 @@ fn statics() { static RC: &E = &E::V2(4); // CHECK: [[t:_.*]] = const {alloc5: &&E}; - // CHECK: [[e2]] = (*[[t]]); + // CHECK: [[e2]] = copy (*[[t]]); let e2 = RC; // CHECK: switchInt({{move _.*}}) -> {{.*}} @@ -108,7 +108,7 @@ fn mutate_discriminant() -> u8 { // CHECK: [[a:_.*]] = discriminant({{_.*}}); let a = Discriminant(x); - // CHECK: switchInt([[a]]) -> [0: {{bb.*}}, otherwise: {{bb.*}}]; + // CHECK: switchInt(copy [[a]]) -> [0: {{bb.*}}, otherwise: {{bb.*}}]; match a { 0 => bb1, _ => bad, @@ -143,8 +143,8 @@ fn multiple(x: bool, i: u8) { // discriminant(e) => Top // (e as Some).0 => Top // CHECK: [[x2]] = const 0_u8; - // CHECK: [[some:_.*]] = (({{_.*}} as Some).0: u8) - // CHECK: [[x2]] = [[some]]; + // CHECK: [[some:_.*]] = copy (({{_.*}} as Some).0: u8) + // CHECK: [[x2]] = copy [[some]]; let x2 = match e { Some(i) => i, None => 0, @@ -153,7 +153,7 @@ fn multiple(x: bool, i: u8) { // Therefore, `x2` should be `Top` here, and no replacement shall happen. // CHECK-NOT: [[y]] = const - // CHECK: [[y]] = [[x2]]; + // CHECK: [[y]] = copy [[x2]]; // CHECK-NOT: [[y]] = const let y = x2; } diff --git a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff index a64dda0d06c..d79c163effc 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff @@ -38,16 +38,16 @@ bb2: { StorageLive(_5); - _5 = ((_1 as V2).0: i32); - _2 = _5; + _5 = copy ((_1 as V2).0: i32); + _2 = copy _5; StorageDead(_5); goto -> bb4; } bb3: { StorageLive(_4); -- _4 = ((_1 as V1).0: i32); -- _2 = _4; +- _4 = copy ((_1 as V1).0: i32); +- _2 = copy _4; + _4 = const 0_i32; + _2 = const 0_i32; StorageDead(_4); diff --git a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff index a64dda0d06c..d79c163effc 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff @@ -38,16 +38,16 @@ bb2: { StorageLive(_5); - _5 = ((_1 as V2).0: i32); - _2 = _5; + _5 = copy ((_1 as V2).0: i32); + _2 = copy _5; StorageDead(_5); goto -> bb4; } bb3: { StorageLive(_4); -- _4 = ((_1 as V1).0: i32); -- _2 = _4; +- _4 = copy ((_1 as V1).0: i32); +- _2 = copy _4; + _4 = const 0_i32; + _2 = const 0_i32; StorageDead(_4); diff --git a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff index b4d14f25fe2..9823a48785a 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff @@ -44,7 +44,7 @@ StorageLive(_1); StorageLive(_2); _2 = const {ALLOC0: &E}; -- _1 = (*_2); +- _1 = copy (*_2); + _1 = const E::V1(0_i32); StorageDead(_2); StorageLive(_3); @@ -60,16 +60,16 @@ bb2: { StorageLive(_6); - _6 = ((_1 as V2).0: i32); - _3 = _6; + _6 = copy ((_1 as V2).0: i32); + _3 = copy _6; StorageDead(_6); goto -> bb4; } bb3: { StorageLive(_5); -- _5 = ((_1 as V1).0: i32); -- _3 = _5; +- _5 = copy ((_1 as V1).0: i32); +- _3 = copy _5; + _5 = const 0_i32; + _3 = const 0_i32; StorageDead(_5); @@ -80,7 +80,7 @@ StorageLive(_7); StorageLive(_8); _8 = const {ALLOC1: &&E}; - _7 = (*_8); + _7 = copy (*_8); StorageDead(_8); StorageLive(_9); _10 = discriminant((*_7)); @@ -98,7 +98,7 @@ bb6: { StorageLive(_11); _11 = &(((*_7) as V1).0: i32); - _9 = _11; + _9 = copy _11; StorageDead(_11); goto -> bb7; } diff --git a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff index 57d02b87d13..e4e68483f25 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff @@ -44,7 +44,7 @@ StorageLive(_1); StorageLive(_2); _2 = const {ALLOC0: &E}; -- _1 = (*_2); +- _1 = copy (*_2); + _1 = const E::V1(0_i32); StorageDead(_2); StorageLive(_3); @@ -60,16 +60,16 @@ bb2: { StorageLive(_6); - _6 = ((_1 as V2).0: i32); - _3 = _6; + _6 = copy ((_1 as V2).0: i32); + _3 = copy _6; StorageDead(_6); goto -> bb4; } bb3: { StorageLive(_5); -- _5 = ((_1 as V1).0: i32); -- _3 = _5; +- _5 = copy ((_1 as V1).0: i32); +- _3 = copy _5; + _5 = const 0_i32; + _3 = const 0_i32; StorageDead(_5); @@ -80,7 +80,7 @@ StorageLive(_7); StorageLive(_8); _8 = const {ALLOC1: &&E}; - _7 = (*_8); + _7 = copy (*_8); StorageDead(_8); StorageLive(_9); _10 = discriminant((*_7)); @@ -98,7 +98,7 @@ bb6: { StorageLive(_11); _11 = &(((*_7) as V1).0: i32); - _9 = _11; + _9 = copy _11; StorageDead(_11); goto -> bb7; } diff --git a/tests/mir-opt/dataflow-const-prop/if.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/if.main.DataflowConstProp.diff index 355f28b03db..5f013b1d134 100644 --- a/tests/mir-opt/dataflow-const-prop/if.main.DataflowConstProp.diff +++ b/tests/mir-opt/dataflow-const-prop/if.main.DataflowConstProp.diff @@ -37,7 +37,7 @@ StorageLive(_2); StorageLive(_3); StorageLive(_4); -- _4 = _1; +- _4 = copy _1; - _3 = Eq(move _4, const 1_i32); - switchInt(move _3) -> [0: bb2, otherwise: bb1]; + _4 = const 1_i32; @@ -61,7 +61,7 @@ StorageDead(_3); StorageLive(_5); StorageLive(_6); -- _6 = _2; +- _6 = copy _2; - _5 = Add(move _6, const 1_i32); + _6 = const 2_i32; + _5 = const 3_i32; @@ -69,7 +69,7 @@ StorageLive(_7); StorageLive(_8); StorageLive(_9); -- _9 = _1; +- _9 = copy _1; - _8 = Eq(move _9, const 1_i32); - switchInt(move _8) -> [0: bb5, otherwise: bb4]; + _9 = const 1_i32; @@ -79,7 +79,7 @@ bb4: { StorageDead(_9); -- _7 = _1; +- _7 = copy _1; + _7 = const 1_i32; goto -> bb6; } @@ -87,7 +87,7 @@ bb5: { StorageDead(_9); StorageLive(_10); - _10 = _1; + _10 = copy _1; _7 = Add(move _10, const 1_i32); StorageDead(_10); goto -> bb6; @@ -97,7 +97,7 @@ StorageDead(_8); StorageLive(_11); StorageLive(_12); -- _12 = _7; +- _12 = copy _7; - _11 = Add(move _12, const 1_i32); + _12 = const 1_i32; + _11 = const 2_i32; diff --git a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff index 8d62de0c821..1b695e4b53c 100644 --- a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff @@ -19,8 +19,8 @@ StorageLive(_3); _3 = const 1_u8; StorageLive(_4); -- _4 = AddWithOverflow(_2, _3); -- assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind unreachable]; +- _4 = AddWithOverflow(copy _2, copy _3); +- assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", copy _2, copy _3) -> [success: bb1, unwind unreachable]; + _4 = const (0_u8, true); + assert(!const true, "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> [success: bb1, unwind unreachable]; } diff --git a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff index 25624851cb3..a0bd8e17d8c 100644 --- a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff @@ -19,8 +19,8 @@ StorageLive(_3); _3 = const 1_u8; StorageLive(_4); -- _4 = AddWithOverflow(_2, _3); -- assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind continue]; +- _4 = AddWithOverflow(copy _2, copy _3); +- assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", copy _2, copy _3) -> [success: bb1, unwind continue]; + _4 = const (0_u8, true); + assert(!const true, "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> [success: bb1, unwind continue]; } diff --git a/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.32bit.panic-abort.diff index 6c612d46725..b7ff0b671f7 100644 --- a/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.32bit.panic-abort.diff @@ -19,16 +19,16 @@ StorageLive(_3); _3 = const 2_usize; - _4 = Len(_2); -- _5 = Lt(_3, _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind unreachable]; +- _5 = Lt(copy _3, copy _4); +- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind unreachable]; + _4 = const 5000_usize; + _5 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } bb1: { -- _1 = _2[_3]; -+ _1 = _2[2 of 3]; +- _1 = copy _2[_3]; ++ _1 = copy _2[2 of 3]; StorageDead(_3); StorageDead(_2); _0 = const (); diff --git a/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.32bit.panic-unwind.diff index 87024da2628..af6e3626142 100644 --- a/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.32bit.panic-unwind.diff @@ -19,16 +19,16 @@ StorageLive(_3); _3 = const 2_usize; - _4 = Len(_2); -- _5 = Lt(_3, _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind continue]; +- _5 = Lt(copy _3, copy _4); +- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind continue]; + _4 = const 5000_usize; + _5 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind continue]; } bb1: { -- _1 = _2[_3]; -+ _1 = _2[2 of 3]; +- _1 = copy _2[_3]; ++ _1 = copy _2[2 of 3]; StorageDead(_3); StorageDead(_2); _0 = const (); diff --git a/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.64bit.panic-abort.diff index 6c612d46725..b7ff0b671f7 100644 --- a/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.64bit.panic-abort.diff @@ -19,16 +19,16 @@ StorageLive(_3); _3 = const 2_usize; - _4 = Len(_2); -- _5 = Lt(_3, _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind unreachable]; +- _5 = Lt(copy _3, copy _4); +- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind unreachable]; + _4 = const 5000_usize; + _5 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } bb1: { -- _1 = _2[_3]; -+ _1 = _2[2 of 3]; +- _1 = copy _2[_3]; ++ _1 = copy _2[2 of 3]; StorageDead(_3); StorageDead(_2); _0 = const (); diff --git a/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.64bit.panic-unwind.diff index 87024da2628..af6e3626142 100644 --- a/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.64bit.panic-unwind.diff @@ -19,16 +19,16 @@ StorageLive(_3); _3 = const 2_usize; - _4 = Len(_2); -- _5 = Lt(_3, _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind continue]; +- _5 = Lt(copy _3, copy _4); +- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind continue]; + _4 = const 5000_usize; + _5 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind continue]; } bb1: { -- _1 = _2[_3]; -+ _1 = _2[2 of 3]; +- _1 = copy _2[_3]; ++ _1 = copy _2[2 of 3]; StorageDead(_3); StorageDead(_2); _0 = const (); diff --git a/tests/mir-opt/dataflow-const-prop/large_array_index.rs b/tests/mir-opt/dataflow-const-prop/large_array_index.rs index e74fd88d002..e9f2fa2badf 100644 --- a/tests/mir-opt/dataflow-const-prop/large_array_index.rs +++ b/tests/mir-opt/dataflow-const-prop/large_array_index.rs @@ -13,6 +13,6 @@ fn main() { // CHECK: {{_.*}} = const 5000_usize; // CHECK: {{_.*}} = const true; // CHECK: assert(const true - // CHECK: [[x]] = [[array_lit]][2 of 3]; + // CHECK: [[x]] = copy [[array_lit]][2 of 3]; let x: u8 = [0_u8; 5000][2]; } diff --git a/tests/mir-opt/dataflow-const-prop/mult_by_zero.test.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/mult_by_zero.test.DataflowConstProp.diff index 91bc10a562f..8b05386b38a 100644 --- a/tests/mir-opt/dataflow-const-prop/mult_by_zero.test.DataflowConstProp.diff +++ b/tests/mir-opt/dataflow-const-prop/mult_by_zero.test.DataflowConstProp.diff @@ -8,7 +8,7 @@ bb0: { StorageLive(_2); - _2 = _1; + _2 = copy _1; - _0 = Mul(move _2, const 0_i32); + _0 = const 0_i32; StorageDead(_2); diff --git a/tests/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.panic-abort.diff index fbbfd61bbed..a0e83265d31 100644 --- a/tests/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.panic-abort.diff @@ -39,7 +39,7 @@ bb2: { StorageDead(_5); StorageLive(_6); - _6 = _1; + _6 = copy _1; _0 = const (); StorageDead(_6); StorageDead(_1); diff --git a/tests/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.panic-unwind.diff index 4e1d26acfa3..6dead031a9f 100644 --- a/tests/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.panic-unwind.diff @@ -39,7 +39,7 @@ bb2: { StorageDead(_5); StorageLive(_6); - _6 = _1; + _6 = copy _1; _0 = const (); StorageDead(_6); StorageDead(_1); diff --git a/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs b/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs index 399de921a59..1c4eb41f35e 100644 --- a/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs +++ b/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs @@ -24,7 +24,7 @@ fn main() { // This should currently not be propagated. // CHECK-NOT: [[b]] = const - // CHECK: [[b]] = [[a]]; + // CHECK: [[b]] = copy [[a]]; // CHECK-NOT: [[b]] = const let b = a; } diff --git a/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.32bit.panic-abort.diff index a18ef6c9db7..dfa541b1200 100644 --- a/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.32bit.panic-abort.diff @@ -21,16 +21,16 @@ StorageLive(_4); _4 = const 2_usize; - _5 = Len(_3); -- _6 = Lt(_4, _5); -- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind unreachable]; +- _6 = Lt(copy _4, copy _5); +- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, copy _4) -> [success: bb1, unwind unreachable]; + _5 = const 8_usize; + _6 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } bb1: { -- _2 = _3[_4]; -+ _2 = _3[2 of 3]; +- _2 = copy _3[_4]; ++ _2 = copy _3[2 of 3]; _1 = Add(move _2, const 0_u32); StorageDead(_2); StorageDead(_4); diff --git a/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.32bit.panic-unwind.diff index 3356ef98b14..9ede3c5f7ac 100644 --- a/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.32bit.panic-unwind.diff @@ -21,16 +21,16 @@ StorageLive(_4); _4 = const 2_usize; - _5 = Len(_3); -- _6 = Lt(_4, _5); -- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind continue]; +- _6 = Lt(copy _4, copy _5); +- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, copy _4) -> [success: bb1, unwind continue]; + _5 = const 8_usize; + _6 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind continue]; } bb1: { -- _2 = _3[_4]; -+ _2 = _3[2 of 3]; +- _2 = copy _3[_4]; ++ _2 = copy _3[2 of 3]; _1 = Add(move _2, const 0_u32); StorageDead(_2); StorageDead(_4); diff --git a/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.64bit.panic-abort.diff index a18ef6c9db7..dfa541b1200 100644 --- a/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.64bit.panic-abort.diff @@ -21,16 +21,16 @@ StorageLive(_4); _4 = const 2_usize; - _5 = Len(_3); -- _6 = Lt(_4, _5); -- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind unreachable]; +- _6 = Lt(copy _4, copy _5); +- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, copy _4) -> [success: bb1, unwind unreachable]; + _5 = const 8_usize; + _6 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } bb1: { -- _2 = _3[_4]; -+ _2 = _3[2 of 3]; +- _2 = copy _3[_4]; ++ _2 = copy _3[2 of 3]; _1 = Add(move _2, const 0_u32); StorageDead(_2); StorageDead(_4); diff --git a/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.64bit.panic-unwind.diff index 3356ef98b14..9ede3c5f7ac 100644 --- a/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.64bit.panic-unwind.diff @@ -21,16 +21,16 @@ StorageLive(_4); _4 = const 2_usize; - _5 = Len(_3); -- _6 = Lt(_4, _5); -- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind continue]; +- _6 = Lt(copy _4, copy _5); +- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, copy _4) -> [success: bb1, unwind continue]; + _5 = const 8_usize; + _6 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind continue]; } bb1: { -- _2 = _3[_4]; -+ _2 = _3[2 of 3]; +- _2 = copy _3[_4]; ++ _2 = copy _3[2 of 3]; _1 = Add(move _2, const 0_u32); StorageDead(_2); StorageDead(_4); diff --git a/tests/mir-opt/dataflow-const-prop/repeat.rs b/tests/mir-opt/dataflow-const-prop/repeat.rs index e32c0d0877d..2067aa3d709 100644 --- a/tests/mir-opt/dataflow-const-prop/repeat.rs +++ b/tests/mir-opt/dataflow-const-prop/repeat.rs @@ -14,8 +14,8 @@ fn main() { // CHECK: {{_.*}} = const true; // CHECK: assert(const true - // CHECK-NOT: [[t:_.*]] = [[array_lit]][_ - // CHECK: [[t:_.*]] = [[array_lit]][2 of 3]; + // CHECK-NOT: [[t:_.*]] = {{copy|move}} [[array_lit]][_ + // CHECK: [[t:_.*]] = copy [[array_lit]][2 of 3]; // CHECK: [[x]] = Add(move [[t]], const 0_u32); let x: u32 = [42; 8][2] + 0; } diff --git a/tests/mir-opt/dataflow-const-prop/repr_transparent.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/repr_transparent.main.DataflowConstProp.diff index 98bd40ab2c3..d0915432aaa 100644 --- a/tests/mir-opt/dataflow-const-prop/repr_transparent.main.DataflowConstProp.diff +++ b/tests/mir-opt/dataflow-const-prop/repr_transparent.main.DataflowConstProp.diff @@ -22,10 +22,10 @@ StorageLive(_2); StorageLive(_3); StorageLive(_4); -- _4 = (_1.0: i32); +- _4 = copy (_1.0: i32); + _4 = const 0_i32; StorageLive(_5); -- _5 = (_1.0: i32); +- _5 = copy (_1.0: i32); - _3 = Add(move _4, move _5); + _5 = const 0_i32; + _3 = const 0_i32; diff --git a/tests/mir-opt/dataflow-const-prop/self_assign.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/self_assign.main.DataflowConstProp.diff index fbdbb3fa35c..e54a0d64b16 100644 --- a/tests/mir-opt/dataflow-const-prop/self_assign.main.DataflowConstProp.diff +++ b/tests/mir-opt/dataflow-const-prop/self_assign.main.DataflowConstProp.diff @@ -20,21 +20,21 @@ StorageLive(_1); _1 = const 0_i32; StorageLive(_2); - _2 = _1; + _2 = copy _1; _1 = Add(move _2, const 1_i32); StorageDead(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; _1 = move _3; StorageDead(_3); StorageLive(_4); _4 = &_1; StorageLive(_5); - _5 = _4; + _5 = copy _4; _4 = move _5; StorageDead(_5); StorageLive(_6); - _6 = (*_4); + _6 = copy (*_4); _1 = move _6; StorageDead(_6); _0 = const (); diff --git a/tests/mir-opt/dataflow-const-prop/self_assign_add.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/self_assign_add.main.DataflowConstProp.diff index e2468a9645d..77762ed9041 100644 --- a/tests/mir-opt/dataflow-const-prop/self_assign_add.main.DataflowConstProp.diff +++ b/tests/mir-opt/dataflow-const-prop/self_assign_add.main.DataflowConstProp.diff @@ -11,8 +11,8 @@ bb0: { StorageLive(_1); _1 = const 0_i32; -- _1 = Add(_1, const 1_i32); -- _1 = Add(_1, const 1_i32); +- _1 = Add(copy _1, const 1_i32); +- _1 = Add(copy _1, const 1_i32); + _1 = const 1_i32; + _1 = const 2_i32; _0 = const (); diff --git a/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.panic-abort.diff index a5e40990751..178ebad6105 100644 --- a/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.panic-abort.diff @@ -27,7 +27,7 @@ _3 = &raw mut (_1.0: u8); StorageLive(_4); StorageLive(_5); - _5 = _3; + _5 = copy _3; _4 = std::ptr::mut_ptr::::add(move _5, const 1_usize) -> [return: bb1, unwind unreachable]; } @@ -39,7 +39,7 @@ StorageDead(_3); StorageDead(_2); StorageLive(_6); - _6 = (_1.1: u8); + _6 = copy (_1.1: u8); _0 = const (); StorageDead(_6); StorageDead(_1); diff --git a/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.panic-unwind.diff index ce2178ddbee..ce2545589f1 100644 --- a/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.panic-unwind.diff @@ -27,7 +27,7 @@ _3 = &raw mut (_1.0: u8); StorageLive(_4); StorageLive(_5); - _5 = _3; + _5 = copy _3; _4 = std::ptr::mut_ptr::::add(move _5, const 1_usize) -> [return: bb1, unwind continue]; } @@ -39,7 +39,7 @@ StorageDead(_3); StorageDead(_2); StorageLive(_6); - _6 = (_1.1: u8); + _6 = copy (_1.1: u8); _0 = const (); StorageDead(_6); StorageDead(_1); diff --git a/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs b/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs index be7f311cdc1..b123f06807d 100644 --- a/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs +++ b/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs @@ -20,6 +20,6 @@ fn main() { *p.add(1) = 1; } - // CHECK: [[x1]] = ({{_.*}}.1: u8); + // CHECK: [[x1]] = copy ({{_.*}}.1: u8); let x1 = x.1; // should not be propagated } diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-abort.diff index efba4a4646c..40632db667a 100644 --- a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-abort.diff @@ -30,23 +30,23 @@ StorageLive(_3); StorageLive(_4); _14 = const main::promoted[0]; - _4 = _14; - _3 = _4; + _4 = copy _14; + _3 = copy _4; _2 = move _3 as &[u32] (PointerCoercion(Unsize)); StorageDead(_3); StorageLive(_6); _6 = const 1_usize; - _7 = Len((*_2)); -- _8 = Lt(_6, _7); -- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb1, unwind unreachable]; +- _8 = Lt(copy _6, copy _7); +- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind unreachable]; + _7 = const 3_usize; + _8 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind unreachable]; } bb1: { -- _1 = (*_2)[_6]; -+ _1 = (*_2)[1 of 2]; +- _1 = copy (*_2)[_6]; ++ _1 = copy (*_2)[1 of 2]; StorageDead(_6); StorageDead(_4); StorageDead(_2); @@ -56,16 +56,16 @@ StorageLive(_11); _11 = const 1_usize; - _12 = Len((*_10)); -- _13 = Lt(_11, _12); -- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, _11) -> [success: bb2, unwind unreachable]; +- _13 = Lt(copy _11, copy _12); +- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb2, unwind unreachable]; + _12 = const 3_usize; + _13 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb2, unwind unreachable]; } bb2: { -- _9 = (*_10)[_11]; -+ _9 = (*_10)[1 of 2]; +- _9 = copy (*_10)[_11]; ++ _9 = copy (*_10)[1 of 2]; StorageDead(_11); StorageDead(_10); _0 = const (); diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-unwind.diff index bf477d7e041..596b4ac9b1e 100644 --- a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-unwind.diff @@ -30,23 +30,23 @@ StorageLive(_3); StorageLive(_4); _14 = const main::promoted[0]; - _4 = _14; - _3 = _4; + _4 = copy _14; + _3 = copy _4; _2 = move _3 as &[u32] (PointerCoercion(Unsize)); StorageDead(_3); StorageLive(_6); _6 = const 1_usize; - _7 = Len((*_2)); -- _8 = Lt(_6, _7); -- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb1, unwind continue]; +- _8 = Lt(copy _6, copy _7); +- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind continue]; + _7 = const 3_usize; + _8 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind continue]; } bb1: { -- _1 = (*_2)[_6]; -+ _1 = (*_2)[1 of 2]; +- _1 = copy (*_2)[_6]; ++ _1 = copy (*_2)[1 of 2]; StorageDead(_6); StorageDead(_4); StorageDead(_2); @@ -56,16 +56,16 @@ StorageLive(_11); _11 = const 1_usize; - _12 = Len((*_10)); -- _13 = Lt(_11, _12); -- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, _11) -> [success: bb2, unwind continue]; +- _13 = Lt(copy _11, copy _12); +- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb2, unwind continue]; + _12 = const 3_usize; + _13 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb2, unwind continue]; } bb2: { -- _9 = (*_10)[_11]; -+ _9 = (*_10)[1 of 2]; +- _9 = copy (*_10)[_11]; ++ _9 = copy (*_10)[1 of 2]; StorageDead(_11); StorageDead(_10); _0 = const (); diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-abort.diff index efba4a4646c..40632db667a 100644 --- a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-abort.diff @@ -30,23 +30,23 @@ StorageLive(_3); StorageLive(_4); _14 = const main::promoted[0]; - _4 = _14; - _3 = _4; + _4 = copy _14; + _3 = copy _4; _2 = move _3 as &[u32] (PointerCoercion(Unsize)); StorageDead(_3); StorageLive(_6); _6 = const 1_usize; - _7 = Len((*_2)); -- _8 = Lt(_6, _7); -- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb1, unwind unreachable]; +- _8 = Lt(copy _6, copy _7); +- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind unreachable]; + _7 = const 3_usize; + _8 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind unreachable]; } bb1: { -- _1 = (*_2)[_6]; -+ _1 = (*_2)[1 of 2]; +- _1 = copy (*_2)[_6]; ++ _1 = copy (*_2)[1 of 2]; StorageDead(_6); StorageDead(_4); StorageDead(_2); @@ -56,16 +56,16 @@ StorageLive(_11); _11 = const 1_usize; - _12 = Len((*_10)); -- _13 = Lt(_11, _12); -- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, _11) -> [success: bb2, unwind unreachable]; +- _13 = Lt(copy _11, copy _12); +- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb2, unwind unreachable]; + _12 = const 3_usize; + _13 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb2, unwind unreachable]; } bb2: { -- _9 = (*_10)[_11]; -+ _9 = (*_10)[1 of 2]; +- _9 = copy (*_10)[_11]; ++ _9 = copy (*_10)[1 of 2]; StorageDead(_11); StorageDead(_10); _0 = const (); diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-unwind.diff index bf477d7e041..596b4ac9b1e 100644 --- a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-unwind.diff @@ -30,23 +30,23 @@ StorageLive(_3); StorageLive(_4); _14 = const main::promoted[0]; - _4 = _14; - _3 = _4; + _4 = copy _14; + _3 = copy _4; _2 = move _3 as &[u32] (PointerCoercion(Unsize)); StorageDead(_3); StorageLive(_6); _6 = const 1_usize; - _7 = Len((*_2)); -- _8 = Lt(_6, _7); -- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb1, unwind continue]; +- _8 = Lt(copy _6, copy _7); +- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind continue]; + _7 = const 3_usize; + _8 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind continue]; } bb1: { -- _1 = (*_2)[_6]; -+ _1 = (*_2)[1 of 2]; +- _1 = copy (*_2)[_6]; ++ _1 = copy (*_2)[1 of 2]; StorageDead(_6); StorageDead(_4); StorageDead(_2); @@ -56,16 +56,16 @@ StorageLive(_11); _11 = const 1_usize; - _12 = Len((*_10)); -- _13 = Lt(_11, _12); -- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, _11) -> [success: bb2, unwind continue]; +- _13 = Lt(copy _11, copy _12); +- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb2, unwind continue]; + _12 = const 3_usize; + _13 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb2, unwind continue]; } bb2: { -- _9 = (*_10)[_11]; -+ _9 = (*_10)[1 of 2]; +- _9 = copy (*_10)[_11]; ++ _9 = copy (*_10)[1 of 2]; StorageDead(_11); StorageDead(_10); _0 = const (); diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.rs b/tests/mir-opt/dataflow-const-prop/slice_len.rs index 64c043cca79..e0e68f9fde5 100644 --- a/tests/mir-opt/dataflow-const-prop/slice_len.rs +++ b/tests/mir-opt/dataflow-const-prop/slice_len.rs @@ -17,7 +17,7 @@ fn main() { // CHECK: {{_.*}} = const true; // CHECK: assert(const true, - // CHECK: [[local]] = (*{{_.*}})[1 of 2]; + // CHECK: [[local]] = copy (*{{_.*}})[1 of 2]; let local = (&[1u32, 2, 3] as &[u32])[1]; // CHECK-NOT: {{_.*}} = Len( @@ -28,7 +28,7 @@ fn main() { // CHECK: {{_.*}} = const true; // CHECK: assert(const true, - // CHECK-NOT: [[constant]] = (*{{_.*}})[_ - // CHECK: [[constant]] = (*{{_.*}})[1 of 2]; + // CHECK-NOT: [[constant]] = {{copy|move}} (*{{_.*}})[_ + // CHECK: [[constant]] = copy (*{{_.*}})[1 of 2]; let constant = SLICE[1]; } diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff index 5e89382ea8f..3ea49265cee 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff @@ -83,7 +83,7 @@ + _1 = const S(1_i32); StorageLive(_2); StorageLive(_3); -- _3 = (_1.0: i32); +- _3 = copy (_1.0: i32); - _2 = Add(move _3, const 2_i32); + _3 = const 1_i32; + _2 = const 3_i32; @@ -91,10 +91,10 @@ (_1.0: i32) = const 3_i32; StorageLive(_4); StorageLive(_5); -- _5 = _2; +- _5 = copy _2; + _5 = const 3_i32; StorageLive(_6); -- _6 = (_1.0: i32); +- _6 = copy (_1.0: i32); - _4 = Add(move _5, move _6); + _6 = const 3_i32; + _4 = const 6_i32; @@ -103,35 +103,35 @@ StorageLive(_10); _10 = const main::SMALL_VAL; StorageLive(_7); -- _7 = (_10.0: f32); +- _7 = copy (_10.0: f32); + _7 = const 4f32; StorageLive(_8); - _8 = (_10.1: std::option::Option); + _8 = copy (_10.1: std::option::Option); StorageLive(_9); - _9 = (_10.2: &[f32]); + _9 = copy (_10.2: &[f32]); StorageDead(_10); StorageLive(_14); _14 = const {ALLOC0: &&SmallStruct}; _31 = deref_copy (*_14); StorageLive(_11); _32 = deref_copy (*_14); -- _11 = ((*_32).0: f32); +- _11 = copy ((*_32).0: f32); + _11 = const 9f32; StorageLive(_12); _33 = deref_copy (*_14); - _12 = ((*_33).1: std::option::Option); + _12 = copy ((*_33).1: std::option::Option); StorageLive(_13); _34 = deref_copy (*_14); - _13 = ((*_34).2: &[f32]); + _13 = copy ((*_34).2: &[f32]); StorageDead(_14); StorageLive(_15); StorageLive(_16); -- _16 = _11; +- _16 = copy _11; + _16 = const 9f32; StorageLive(_17); - _17 = _12; + _17 = copy _12; StorageLive(_18); - _18 = _13; + _18 = copy _13; - _15 = SmallStruct(move _16, move _17, move _18); + _15 = SmallStruct(const 9f32, move _17, move _18); StorageDead(_18); @@ -140,35 +140,35 @@ StorageLive(_22); _22 = const main::BIG_VAL; StorageLive(_19); -- _19 = (_22.0: f32); +- _19 = copy (_22.0: f32); + _19 = const 25f32; StorageLive(_20); - _20 = (_22.1: std::option::Option); + _20 = copy (_22.1: std::option::Option); StorageLive(_21); - _21 = (_22.2: &[f32]); + _21 = copy (_22.2: &[f32]); StorageDead(_22); StorageLive(_26); _26 = const {ALLOC1: &&BigStruct}; _35 = deref_copy (*_26); StorageLive(_23); _36 = deref_copy (*_26); -- _23 = ((*_36).0: f32); +- _23 = copy ((*_36).0: f32); + _23 = const 82f32; StorageLive(_24); _37 = deref_copy (*_26); - _24 = ((*_37).1: std::option::Option); + _24 = copy ((*_37).1: std::option::Option); StorageLive(_25); _38 = deref_copy (*_26); - _25 = ((*_38).2: &[f32]); + _25 = copy ((*_38).2: &[f32]); StorageDead(_26); StorageLive(_27); StorageLive(_28); -- _28 = _23; +- _28 = copy _23; + _28 = const 82f32; StorageLive(_29); - _29 = _24; + _29 = copy _24; StorageLive(_30); - _30 = _25; + _30 = copy _25; - _27 = BigStruct(move _28, move _29, move _30); + _27 = BigStruct(const 82f32, move _29, move _30); StorageDead(_30); diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff index a707d7e5e76..78a0944975c 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff @@ -83,7 +83,7 @@ + _1 = const S(1_i32); StorageLive(_2); StorageLive(_3); -- _3 = (_1.0: i32); +- _3 = copy (_1.0: i32); - _2 = Add(move _3, const 2_i32); + _3 = const 1_i32; + _2 = const 3_i32; @@ -91,10 +91,10 @@ (_1.0: i32) = const 3_i32; StorageLive(_4); StorageLive(_5); -- _5 = _2; +- _5 = copy _2; + _5 = const 3_i32; StorageLive(_6); -- _6 = (_1.0: i32); +- _6 = copy (_1.0: i32); - _4 = Add(move _5, move _6); + _6 = const 3_i32; + _4 = const 6_i32; @@ -103,35 +103,35 @@ StorageLive(_10); _10 = const main::SMALL_VAL; StorageLive(_7); -- _7 = (_10.0: f32); +- _7 = copy (_10.0: f32); + _7 = const 4f32; StorageLive(_8); - _8 = (_10.1: std::option::Option); + _8 = copy (_10.1: std::option::Option); StorageLive(_9); - _9 = (_10.2: &[f32]); + _9 = copy (_10.2: &[f32]); StorageDead(_10); StorageLive(_14); _14 = const {ALLOC0: &&SmallStruct}; _31 = deref_copy (*_14); StorageLive(_11); _32 = deref_copy (*_14); -- _11 = ((*_32).0: f32); +- _11 = copy ((*_32).0: f32); + _11 = const 9f32; StorageLive(_12); _33 = deref_copy (*_14); - _12 = ((*_33).1: std::option::Option); + _12 = copy ((*_33).1: std::option::Option); StorageLive(_13); _34 = deref_copy (*_14); - _13 = ((*_34).2: &[f32]); + _13 = copy ((*_34).2: &[f32]); StorageDead(_14); StorageLive(_15); StorageLive(_16); -- _16 = _11; +- _16 = copy _11; + _16 = const 9f32; StorageLive(_17); - _17 = _12; + _17 = copy _12; StorageLive(_18); - _18 = _13; + _18 = copy _13; - _15 = SmallStruct(move _16, move _17, move _18); + _15 = SmallStruct(const 9f32, move _17, move _18); StorageDead(_18); @@ -140,35 +140,35 @@ StorageLive(_22); _22 = const main::BIG_VAL; StorageLive(_19); -- _19 = (_22.0: f32); +- _19 = copy (_22.0: f32); + _19 = const 25f32; StorageLive(_20); - _20 = (_22.1: std::option::Option); + _20 = copy (_22.1: std::option::Option); StorageLive(_21); - _21 = (_22.2: &[f32]); + _21 = copy (_22.2: &[f32]); StorageDead(_22); StorageLive(_26); _26 = const {ALLOC1: &&BigStruct}; _35 = deref_copy (*_26); StorageLive(_23); _36 = deref_copy (*_26); -- _23 = ((*_36).0: f32); +- _23 = copy ((*_36).0: f32); + _23 = const 82f32; StorageLive(_24); _37 = deref_copy (*_26); - _24 = ((*_37).1: std::option::Option); + _24 = copy ((*_37).1: std::option::Option); StorageLive(_25); _38 = deref_copy (*_26); - _25 = ((*_38).2: &[f32]); + _25 = copy ((*_38).2: &[f32]); StorageDead(_26); StorageLive(_27); StorageLive(_28); -- _28 = _23; +- _28 = copy _23; + _28 = const 82f32; StorageLive(_29); - _29 = _24; + _29 = copy _24; StorageLive(_30); - _30 = _25; + _30 = copy _25; - _27 = BigStruct(move _28, move _29, move _30); + _27 = BigStruct(const 82f32, move _29, move _30); StorageDead(_30); diff --git a/tests/mir-opt/dataflow-const-prop/struct.rs b/tests/mir-opt/dataflow-const-prop/struct.rs index 89ad1b87029..44591ffb6de 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.rs +++ b/tests/mir-opt/dataflow-const-prop/struct.rs @@ -46,15 +46,15 @@ fn main() { const SMALL_VAL: SmallStruct = SmallStruct(4., Some(S(1)), &[]); // CHECK: [[a1]] = const 4f32; - // CHECK: [[b1]] = ({{_.*}}.1: std::option::Option); - // CHECK: [[c1]] = ({{_.*}}.2: &[f32]); + // CHECK: [[b1]] = copy ({{_.*}}.1: std::option::Option); + // CHECK: [[c1]] = copy ({{_.*}}.2: &[f32]); let SmallStruct(a1, b1, c1) = SMALL_VAL; static SMALL_STAT: &SmallStruct = &SmallStruct(9., None, &[13.]); // CHECK: [[a2]] = const 9f32; - // CHECK: [[b2]] = ((*{{_.*}}).1: std::option::Option); - // CHECK: [[c2]] = ((*{{_.*}}).2: &[f32]); + // CHECK: [[b2]] = copy ((*{{_.*}}).1: std::option::Option); + // CHECK: [[c2]] = copy ((*{{_.*}}).2: &[f32]); let SmallStruct(a2, b2, c2) = *SMALL_STAT; // CHECK: [[ss]] = SmallStruct(const 9f32, move {{_.*}}, move {{_.*}}); @@ -63,14 +63,14 @@ fn main() { const BIG_VAL: BigStruct = BigStruct(25., None, &[]); // CHECK: [[a3]] = const 25f32; - // CHECK: [[b3]] = ({{_.*}}.1: std::option::Option); - // CHECK: [[c3]] = ({{_.*}}.2: &[f32]); + // CHECK: [[b3]] = copy ({{_.*}}.1: std::option::Option); + // CHECK: [[c3]] = copy ({{_.*}}.2: &[f32]); let BigStruct(a3, b3, c3) = BIG_VAL; static BIG_STAT: &BigStruct = &BigStruct(82., Some(S(35)), &[45., 72.]); // CHECK: [[a4]] = const 82f32; - // CHECK: [[b4]] = ((*{{_.*}}).1: std::option::Option); - // CHECK: [[c4]] = ((*{{_.*}}).2: &[f32]); + // CHECK: [[b4]] = copy ((*{{_.*}}).1: std::option::Option); + // CHECK: [[c4]] = copy ((*{{_.*}}).2: &[f32]); let BigStruct(a4, b4, c4) = *BIG_STAT; // We arbitrarily limit the size of synthetized values to 4 pointers. diff --git a/tests/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.panic-abort.diff index c0f378cc21f..e13b2aa9f7e 100644 --- a/tests/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.panic-abort.diff @@ -17,7 +17,7 @@ StorageLive(_2); StorageLive(_3); StorageLive(_4); -- _4 = _1; +- _4 = copy _1; - _3 = Add(move _4, const 1_i32); + _4 = const 1_i32; + _3 = const 2_i32; diff --git a/tests/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.panic-unwind.diff index 395620fec52..4be25fdcc38 100644 --- a/tests/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.panic-unwind.diff @@ -17,7 +17,7 @@ StorageLive(_2); StorageLive(_3); StorageLive(_4); -- _4 = _1; +- _4 = copy _1; - _3 = Add(move _4, const 1_i32); + _4 = const 1_i32; + _3 = const 2_i32; diff --git a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.32bit.diff index 258e2b454eb..2d67ac92209 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.32bit.diff @@ -13,7 +13,7 @@ StorageLive(_1); - _1 = const 1_usize as std::boxed::Box (Transmute); + _1 = const Box::(Unique:: {{ pointer: NonNull:: {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData:: }}, std::alloc::Global); - _2 = (((_1.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const Never); + _2 = copy (((_1.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const Never); unreachable; } } diff --git a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.64bit.diff index 258e2b454eb..2d67ac92209 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.64bit.diff @@ -13,7 +13,7 @@ StorageLive(_1); - _1 = const 1_usize as std::boxed::Box (Transmute); + _1 = const Box::(Unique:: {{ pointer: NonNull:: {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData:: }}, std::alloc::Global); - _2 = (((_1.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const Never); + _2 = copy (((_1.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const Never); unreachable; } } diff --git a/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.32bit.diff index e4031b65caa..f7846823e19 100644 --- a/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.32bit.diff @@ -37,10 +37,10 @@ StorageLive(_2); StorageLive(_3); StorageLive(_4); -- _4 = (_1.0: i32); +- _4 = copy (_1.0: i32); + _4 = const 1_i32; StorageLive(_5); -- _5 = (_1.1: i32); +- _5 = copy (_1.1: i32); - _3 = Add(move _4, move _5); + _5 = const 2_i32; + _3 = const 3_i32; @@ -54,17 +54,17 @@ StorageLive(_6); StorageLive(_7); StorageLive(_8); -- _8 = (_1.0: i32); +- _8 = copy (_1.0: i32); + _8 = const 2_i32; StorageLive(_9); -- _9 = (_1.1: i32); +- _9 = copy (_1.1: i32); - _7 = Add(move _8, move _9); + _9 = const 3_i32; + _7 = const 5_i32; StorageDead(_9); StorageDead(_8); StorageLive(_10); -- _10 = _2; +- _10 = copy _2; - _6 = Add(move _7, move _10); + _10 = const 6_i32; + _6 = const 11_i32; @@ -72,13 +72,13 @@ StorageDead(_7); StorageLive(_11); StorageLive(_12); -- _12 = _2; +- _12 = copy _2; + _12 = const 6_i32; StorageLive(_13); -- _13 = _1; +- _13 = copy _1; + _13 = const (2_i32, 3_i32); StorageLive(_14); -- _14 = _6; +- _14 = copy _6; - _11 = (move _12, move _13, move _14); + _14 = const 11_i32; + _11 = (const 6_i32, const (2_i32, 3_i32), const 11_i32); diff --git a/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.64bit.diff index e4031b65caa..f7846823e19 100644 --- a/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.64bit.diff @@ -37,10 +37,10 @@ StorageLive(_2); StorageLive(_3); StorageLive(_4); -- _4 = (_1.0: i32); +- _4 = copy (_1.0: i32); + _4 = const 1_i32; StorageLive(_5); -- _5 = (_1.1: i32); +- _5 = copy (_1.1: i32); - _3 = Add(move _4, move _5); + _5 = const 2_i32; + _3 = const 3_i32; @@ -54,17 +54,17 @@ StorageLive(_6); StorageLive(_7); StorageLive(_8); -- _8 = (_1.0: i32); +- _8 = copy (_1.0: i32); + _8 = const 2_i32; StorageLive(_9); -- _9 = (_1.1: i32); +- _9 = copy (_1.1: i32); - _7 = Add(move _8, move _9); + _9 = const 3_i32; + _7 = const 5_i32; StorageDead(_9); StorageDead(_8); StorageLive(_10); -- _10 = _2; +- _10 = copy _2; - _6 = Add(move _7, move _10); + _10 = const 6_i32; + _6 = const 11_i32; @@ -72,13 +72,13 @@ StorageDead(_7); StorageLive(_11); StorageLive(_12); -- _12 = _2; +- _12 = copy _2; + _12 = const 6_i32; StorageLive(_13); -- _13 = _1; +- _13 = copy _1; + _13 = const (2_i32, 3_i32); StorageLive(_14); -- _14 = _6; +- _14 = copy _6; - _11 = (move _12, move _13, move _14); + _14 = const 11_i32; + _11 = (const 6_i32, const (2_i32, 3_i32), const 11_i32); diff --git a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination-final.panic-abort.diff b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination-final.panic-abort.diff index 07fb8301b9a..80b727dd1a4 100644 --- a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination-final.panic-abort.diff +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination-final.panic-abort.diff @@ -5,7 +5,7 @@ let mut _0: (); bb0: { - _0 = use_both(const 0_i32, (_1.1: i32)) -> [return: bb1, unwind unreachable]; + _0 = use_both(const 0_i32, copy (_1.1: i32)) -> [return: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination-final.panic-unwind.diff b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination-final.panic-unwind.diff index cac3badfa67..c7aff795bd8 100644 --- a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination-final.panic-unwind.diff +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination-final.panic-unwind.diff @@ -5,7 +5,7 @@ let mut _0: (); bb0: { - _0 = use_both(const 0_i32, (_1.1: i32)) -> [return: bb1, unwind continue]; + _0 = use_both(const 0_i32, copy (_1.1: i32)) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination-final.panic-abort.diff b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination-final.panic-abort.diff index f9bc9405d6a..a09ef3e4f34 100644 --- a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination-final.panic-abort.diff +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination-final.panic-abort.diff @@ -10,8 +10,8 @@ bb0: { StorageLive(_2); -- _2 = use_both(_1, _1) -> [return: bb1, unwind unreachable]; -+ _2 = use_both(_1, move _1) -> [return: bb1, unwind unreachable]; +- _2 = use_both(copy _1, copy _1) -> [return: bb1, unwind unreachable]; ++ _2 = use_both(copy _1, move _1) -> [return: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination-final.panic-unwind.diff b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination-final.panic-unwind.diff index efe165422d9..09413c99fef 100644 --- a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination-final.panic-unwind.diff +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination-final.panic-unwind.diff @@ -10,8 +10,8 @@ bb0: { StorageLive(_2); -- _2 = use_both(_1, _1) -> [return: bb1, unwind continue]; -+ _2 = use_both(_1, move _1) -> [return: bb1, unwind continue]; +- _2 = use_both(copy _1, copy _1) -> [return: bb1, unwind continue]; ++ _2 = use_both(copy _1, move _1) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/dead-store-elimination/call_arg_copy.rs b/tests/mir-opt/dead-store-elimination/call_arg_copy.rs index 2556848ec46..27b5ccdb936 100644 --- a/tests/mir-opt/dead-store-elimination/call_arg_copy.rs +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.rs @@ -14,7 +14,7 @@ fn use_both(_: i32, _: i32) {} // EMIT_MIR call_arg_copy.move_simple.DeadStoreElimination-final.diff fn move_simple(x: i32) { // CHECK-LABEL: fn move_simple( - // CHECK: = use_both(_1, move _1) + // CHECK: = use_both(copy _1, move _1) use_both(x, x); } @@ -28,7 +28,7 @@ struct Packed { #[custom_mir(dialect = "analysis")] fn move_packed(packed: Packed) { // CHECK-LABEL: fn move_packed( - // CHECK: = use_both(const 0_i32, (_1.1: i32)) + // CHECK: = use_both(const 0_i32, copy (_1.1: i32)) mir! { { // We have a packed struct, verify that the copy is not turned into a move. diff --git a/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination-initial.diff b/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination-initial.diff index 2766b6ce6a9..ff18df1efcf 100644 --- a/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination-initial.diff +++ b/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination-initial.diff @@ -11,14 +11,14 @@ } bb1: { - switchInt(_4) -> [1: bb2, otherwise: bb3]; + switchInt(copy _4) -> [1: bb2, otherwise: bb3]; } bb2: { -- _5 = _3; -- _3 = _2; -- _2 = _1; -- _1 = _5; +- _5 = copy _3; +- _3 = copy _2; +- _2 = copy _1; +- _1 = copy _5; + nop; + nop; + nop; diff --git a/tests/mir-opt/dead-store-elimination/provenance_soundness.pointer_to_int.DeadStoreElimination-initial.diff b/tests/mir-opt/dead-store-elimination/provenance_soundness.pointer_to_int.DeadStoreElimination-initial.diff index 56d5c24ae1d..5d054e2ea16 100644 --- a/tests/mir-opt/dead-store-elimination/provenance_soundness.pointer_to_int.DeadStoreElimination-initial.diff +++ b/tests/mir-opt/dead-store-elimination/provenance_soundness.pointer_to_int.DeadStoreElimination-initial.diff @@ -18,12 +18,12 @@ bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; _2 = move _3 as usize (PointerExposeProvenance); StorageDead(_3); StorageLive(_4); StorageLive(_5); - _5 = _1; + _5 = copy _1; _4 = move _5 as isize (PointerExposeProvenance); StorageDead(_5); _0 = const (); diff --git a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-abort.diff b/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-abort.diff index efb28ba344b..60742ef0e9a 100644 --- a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-abort.diff +++ b/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-abort.diff @@ -37,40 +37,40 @@ } bb3: { - switchInt((*_2)[0 of 4]) -> [47: bb4, otherwise: bb2]; + switchInt(copy (*_2)[0 of 4]) -> [47: bb4, otherwise: bb2]; } bb4: { - switchInt((*_2)[1 of 4]) -> [47: bb5, otherwise: bb2]; + switchInt(copy (*_2)[1 of 4]) -> [47: bb5, otherwise: bb2]; } bb5: { - switchInt((*_2)[2 of 4]) -> [47: bb6, otherwise: bb2]; + switchInt(copy (*_2)[2 of 4]) -> [47: bb6, otherwise: bb2]; } bb6: { -- switchInt((*_2)[3 of 4]) -> [47: bb13, otherwise: bb2]; -+ switchInt((*_2)[3 of 4]) -> [47: bb11, otherwise: bb2]; +- switchInt(copy (*_2)[3 of 4]) -> [47: bb13, otherwise: bb2]; ++ switchInt(copy (*_2)[3 of 4]) -> [47: bb11, otherwise: bb2]; } bb7: { - _0 = const false; - goto -> bb14; -+ switchInt((*_2)[0 of 3]) -> [47: bb8, otherwise: bb11]; ++ switchInt(copy (*_2)[0 of 3]) -> [47: bb8, otherwise: bb11]; } bb8: { -- switchInt((*_2)[0 of 3]) -> [47: bb9, otherwise: bb7]; -+ switchInt((*_2)[1 of 3]) -> [47: bb9, otherwise: bb11]; +- switchInt(copy (*_2)[0 of 3]) -> [47: bb9, otherwise: bb7]; ++ switchInt(copy (*_2)[1 of 3]) -> [47: bb9, otherwise: bb11]; } bb9: { -- switchInt((*_2)[1 of 3]) -> [47: bb10, otherwise: bb7]; -+ switchInt((*_2)[2 of 3]) -> [47: bb10, 33: bb10, otherwise: bb11]; +- switchInt(copy (*_2)[1 of 3]) -> [47: bb10, otherwise: bb7]; ++ switchInt(copy (*_2)[2 of 3]) -> [47: bb10, 33: bb10, otherwise: bb11]; } bb10: { -- switchInt((*_2)[2 of 3]) -> [47: bb12, 33: bb11, otherwise: bb7]; +- switchInt(copy (*_2)[2 of 3]) -> [47: bb12, 33: bb11, otherwise: bb7]; - } - - bb11: { diff --git a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-unwind.diff b/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-unwind.diff index c6e2d3a5512..7337a32f525 100644 --- a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-unwind.diff +++ b/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-unwind.diff @@ -37,40 +37,40 @@ } bb3: { - switchInt((*_2)[0 of 4]) -> [47: bb4, otherwise: bb2]; + switchInt(copy (*_2)[0 of 4]) -> [47: bb4, otherwise: bb2]; } bb4: { - switchInt((*_2)[1 of 4]) -> [47: bb5, otherwise: bb2]; + switchInt(copy (*_2)[1 of 4]) -> [47: bb5, otherwise: bb2]; } bb5: { - switchInt((*_2)[2 of 4]) -> [47: bb6, otherwise: bb2]; + switchInt(copy (*_2)[2 of 4]) -> [47: bb6, otherwise: bb2]; } bb6: { -- switchInt((*_2)[3 of 4]) -> [47: bb13, otherwise: bb2]; -+ switchInt((*_2)[3 of 4]) -> [47: bb11, otherwise: bb2]; +- switchInt(copy (*_2)[3 of 4]) -> [47: bb13, otherwise: bb2]; ++ switchInt(copy (*_2)[3 of 4]) -> [47: bb11, otherwise: bb2]; } bb7: { - _0 = const false; - goto -> bb14; -+ switchInt((*_2)[0 of 3]) -> [47: bb8, otherwise: bb11]; ++ switchInt(copy (*_2)[0 of 3]) -> [47: bb8, otherwise: bb11]; } bb8: { -- switchInt((*_2)[0 of 3]) -> [47: bb9, otherwise: bb7]; -+ switchInt((*_2)[1 of 3]) -> [47: bb9, otherwise: bb11]; +- switchInt(copy (*_2)[0 of 3]) -> [47: bb9, otherwise: bb7]; ++ switchInt(copy (*_2)[1 of 3]) -> [47: bb9, otherwise: bb11]; } bb9: { -- switchInt((*_2)[1 of 3]) -> [47: bb10, otherwise: bb7]; -+ switchInt((*_2)[2 of 3]) -> [47: bb10, 33: bb10, otherwise: bb11]; +- switchInt(copy (*_2)[1 of 3]) -> [47: bb10, otherwise: bb7]; ++ switchInt(copy (*_2)[2 of 3]) -> [47: bb10, 33: bb10, otherwise: bb11]; } bb10: { -- switchInt((*_2)[2 of 3]) -> [47: bb12, 33: bb11, otherwise: bb7]; +- switchInt(copy (*_2)[2 of 3]) -> [47: bb12, 33: bb11, otherwise: bb7]; - } - - bb11: { diff --git a/tests/mir-opt/derefer_complex_case.main.Derefer.panic-abort.diff b/tests/mir-opt/derefer_complex_case.main.Derefer.panic-abort.diff index 4ead50e96d8..bac62c88668 100644 --- a/tests/mir-opt/derefer_complex_case.main.Derefer.panic-abort.diff +++ b/tests/mir-opt/derefer_complex_case.main.Derefer.panic-abort.diff @@ -64,11 +64,11 @@ bb5: { StorageLive(_12); -- _12 = (*((_7 as Some).0: &i32)); +- _12 = copy (*((_7 as Some).0: &i32)); + _15 = deref_copy ((_7 as Some).0: &i32); -+ _12 = (*_15); ++ _12 = copy (*_15); StorageLive(_13); - _13 = _12; + _13 = copy _12; _6 = std::mem::drop::(move _13) -> [return: bb7, unwind: bb8]; } diff --git a/tests/mir-opt/derefer_complex_case.main.Derefer.panic-unwind.diff b/tests/mir-opt/derefer_complex_case.main.Derefer.panic-unwind.diff index c7cf5f02e0e..55cd2e427ee 100644 --- a/tests/mir-opt/derefer_complex_case.main.Derefer.panic-unwind.diff +++ b/tests/mir-opt/derefer_complex_case.main.Derefer.panic-unwind.diff @@ -64,11 +64,11 @@ bb5: { StorageLive(_12); -- _12 = (*((_7 as Some).0: &i32)); +- _12 = copy (*((_7 as Some).0: &i32)); + _15 = deref_copy ((_7 as Some).0: &i32); -+ _12 = (*_15); ++ _12 = copy (*_15); StorageLive(_13); - _13 = _12; + _13 = copy _12; _6 = std::mem::drop::(move _13) -> [return: bb7, unwind continue]; } diff --git a/tests/mir-opt/derefer_terminator_test.main.Derefer.panic-abort.diff b/tests/mir-opt/derefer_terminator_test.main.Derefer.panic-abort.diff index f4c034517f7..012d2eb8b72 100644 --- a/tests/mir-opt/derefer_terminator_test.main.Derefer.panic-abort.diff +++ b/tests/mir-opt/derefer_terminator_test.main.Derefer.panic-abort.diff @@ -52,7 +52,7 @@ _5 = &_6; _4 = &_5; - PlaceMention((*(*(*(*_4))))); -- switchInt((*(*(*(*_4))))) -> [0: bb3, otherwise: bb4]; +- switchInt(copy (*(*(*(*_4))))) -> [0: bb3, otherwise: bb4]; + _10 = deref_copy (*_4); + _11 = deref_copy (*_10); + _12 = deref_copy (*_11); @@ -60,7 +60,7 @@ + _13 = deref_copy (*_4); + _14 = deref_copy (*_13); + _15 = deref_copy (*_14); -+ switchInt((*_15)) -> [0: bb3, otherwise: bb4]; ++ switchInt(copy (*_15)) -> [0: bb3, otherwise: bb4]; } bb3: { diff --git a/tests/mir-opt/derefer_terminator_test.main.Derefer.panic-unwind.diff b/tests/mir-opt/derefer_terminator_test.main.Derefer.panic-unwind.diff index e3c0c6b7dd2..43cee292335 100644 --- a/tests/mir-opt/derefer_terminator_test.main.Derefer.panic-unwind.diff +++ b/tests/mir-opt/derefer_terminator_test.main.Derefer.panic-unwind.diff @@ -52,7 +52,7 @@ _5 = &_6; _4 = &_5; - PlaceMention((*(*(*(*_4))))); -- switchInt((*(*(*(*_4))))) -> [0: bb3, otherwise: bb4]; +- switchInt(copy (*(*(*(*_4))))) -> [0: bb3, otherwise: bb4]; + _10 = deref_copy (*_4); + _11 = deref_copy (*_10); + _12 = deref_copy (*_11); @@ -60,7 +60,7 @@ + _13 = deref_copy (*_4); + _14 = deref_copy (*_13); + _15 = deref_copy (*_14); -+ switchInt((*_15)) -> [0: bb3, otherwise: bb4]; ++ switchInt(copy (*_15)) -> [0: bb3, otherwise: bb4]; } bb3: { diff --git a/tests/mir-opt/dest-prop/branch.foo.DestinationPropagation.panic-abort.diff b/tests/mir-opt/dest-prop/branch.foo.DestinationPropagation.panic-abort.diff index 10ec3aa555e..775d51ea49f 100644 --- a/tests/mir-opt/dest-prop/branch.foo.DestinationPropagation.panic-abort.diff +++ b/tests/mir-opt/dest-prop/branch.foo.DestinationPropagation.panic-abort.diff @@ -35,7 +35,7 @@ } bb3: { -- _2 = _1; +- _2 = copy _1; + nop; goto -> bb6; } @@ -47,14 +47,14 @@ bb5: { StorageDead(_4); -- _2 = _1; +- _2 = copy _1; + nop; goto -> bb6; } bb6: { StorageDead(_3); -- _0 = _2; +- _0 = copy _2; - StorageDead(_2); - StorageDead(_1); + nop; diff --git a/tests/mir-opt/dest-prop/branch.foo.DestinationPropagation.panic-unwind.diff b/tests/mir-opt/dest-prop/branch.foo.DestinationPropagation.panic-unwind.diff index 759c1cabf45..875ef8829d0 100644 --- a/tests/mir-opt/dest-prop/branch.foo.DestinationPropagation.panic-unwind.diff +++ b/tests/mir-opt/dest-prop/branch.foo.DestinationPropagation.panic-unwind.diff @@ -35,7 +35,7 @@ } bb3: { -- _2 = _1; +- _2 = copy _1; + nop; goto -> bb6; } @@ -47,14 +47,14 @@ bb5: { StorageDead(_4); -- _2 = _1; +- _2 = copy _1; + nop; goto -> bb6; } bb6: { StorageDead(_3); -- _0 = _2; +- _0 = copy _2; - StorageDead(_2); - StorageDead(_1); + nop; diff --git a/tests/mir-opt/dest-prop/copy_propagation_arg.arg_src.DestinationPropagation.panic-abort.diff b/tests/mir-opt/dest-prop/copy_propagation_arg.arg_src.DestinationPropagation.panic-abort.diff index 1aed07f9e6a..a4908c05e2e 100644 --- a/tests/mir-opt/dest-prop/copy_propagation_arg.arg_src.DestinationPropagation.panic-abort.diff +++ b/tests/mir-opt/dest-prop/copy_propagation_arg.arg_src.DestinationPropagation.panic-abort.diff @@ -12,11 +12,11 @@ bb0: { - StorageLive(_2); -- _2 = _1; +- _2 = copy _1; + nop; -+ _0 = _1; ++ _0 = copy _1; _1 = const 123_i32; -- _0 = _2; +- _0 = copy _2; - StorageDead(_2); + nop; + nop; diff --git a/tests/mir-opt/dest-prop/copy_propagation_arg.arg_src.DestinationPropagation.panic-unwind.diff b/tests/mir-opt/dest-prop/copy_propagation_arg.arg_src.DestinationPropagation.panic-unwind.diff index 1aed07f9e6a..a4908c05e2e 100644 --- a/tests/mir-opt/dest-prop/copy_propagation_arg.arg_src.DestinationPropagation.panic-unwind.diff +++ b/tests/mir-opt/dest-prop/copy_propagation_arg.arg_src.DestinationPropagation.panic-unwind.diff @@ -12,11 +12,11 @@ bb0: { - StorageLive(_2); -- _2 = _1; +- _2 = copy _1; + nop; -+ _0 = _1; ++ _0 = copy _1; _1 = const 123_i32; -- _0 = _2; +- _0 = copy _2; - StorageDead(_2); + nop; + nop; diff --git a/tests/mir-opt/dest-prop/copy_propagation_arg.bar.DestinationPropagation.panic-abort.diff b/tests/mir-opt/dest-prop/copy_propagation_arg.bar.DestinationPropagation.panic-abort.diff index 641dea594e1..24f2b464e2c 100644 --- a/tests/mir-opt/dest-prop/copy_propagation_arg.bar.DestinationPropagation.panic-abort.diff +++ b/tests/mir-opt/dest-prop/copy_propagation_arg.bar.DestinationPropagation.panic-abort.diff @@ -10,7 +10,7 @@ bb0: { StorageLive(_2); - StorageLive(_3); -- _3 = _1; +- _3 = copy _1; - _2 = dummy(move _3) -> [return: bb1, unwind unreachable]; + nop; + nop; diff --git a/tests/mir-opt/dest-prop/copy_propagation_arg.bar.DestinationPropagation.panic-unwind.diff b/tests/mir-opt/dest-prop/copy_propagation_arg.bar.DestinationPropagation.panic-unwind.diff index 8b2835c8ced..d42ac52b631 100644 --- a/tests/mir-opt/dest-prop/copy_propagation_arg.bar.DestinationPropagation.panic-unwind.diff +++ b/tests/mir-opt/dest-prop/copy_propagation_arg.bar.DestinationPropagation.panic-unwind.diff @@ -10,7 +10,7 @@ bb0: { StorageLive(_2); - StorageLive(_3); -- _3 = _1; +- _3 = copy _1; - _2 = dummy(move _3) -> [return: bb1, unwind continue]; + nop; + nop; diff --git a/tests/mir-opt/dest-prop/copy_propagation_arg.baz.DestinationPropagation.panic-abort.diff b/tests/mir-opt/dest-prop/copy_propagation_arg.baz.DestinationPropagation.panic-abort.diff index 4cddaec01d2..f1f1714b472 100644 --- a/tests/mir-opt/dest-prop/copy_propagation_arg.baz.DestinationPropagation.panic-abort.diff +++ b/tests/mir-opt/dest-prop/copy_propagation_arg.baz.DestinationPropagation.panic-abort.diff @@ -8,14 +8,14 @@ bb0: { - StorageLive(_2); -- _2 = _1; +- _2 = copy _1; - _1 = move _2; - StorageDead(_2); + nop; + nop; + nop; + nop; - _0 = _1; + _0 = copy _1; return; } } diff --git a/tests/mir-opt/dest-prop/copy_propagation_arg.baz.DestinationPropagation.panic-unwind.diff b/tests/mir-opt/dest-prop/copy_propagation_arg.baz.DestinationPropagation.panic-unwind.diff index 4cddaec01d2..f1f1714b472 100644 --- a/tests/mir-opt/dest-prop/copy_propagation_arg.baz.DestinationPropagation.panic-unwind.diff +++ b/tests/mir-opt/dest-prop/copy_propagation_arg.baz.DestinationPropagation.panic-unwind.diff @@ -8,14 +8,14 @@ bb0: { - StorageLive(_2); -- _2 = _1; +- _2 = copy _1; - _1 = move _2; - StorageDead(_2); + nop; + nop; + nop; + nop; - _0 = _1; + _0 = copy _1; return; } } diff --git a/tests/mir-opt/dest-prop/copy_propagation_arg.foo.DestinationPropagation.panic-abort.diff b/tests/mir-opt/dest-prop/copy_propagation_arg.foo.DestinationPropagation.panic-abort.diff index b461869be31..0328fc6b745 100644 --- a/tests/mir-opt/dest-prop/copy_propagation_arg.foo.DestinationPropagation.panic-abort.diff +++ b/tests/mir-opt/dest-prop/copy_propagation_arg.foo.DestinationPropagation.panic-abort.diff @@ -10,7 +10,7 @@ bb0: { StorageLive(_2); - StorageLive(_3); -- _3 = _1; +- _3 = copy _1; - _2 = dummy(move _3) -> [return: bb1, unwind unreachable]; + nop; + nop; diff --git a/tests/mir-opt/dest-prop/copy_propagation_arg.foo.DestinationPropagation.panic-unwind.diff b/tests/mir-opt/dest-prop/copy_propagation_arg.foo.DestinationPropagation.panic-unwind.diff index d5c2e07c6c2..30e2248db82 100644 --- a/tests/mir-opt/dest-prop/copy_propagation_arg.foo.DestinationPropagation.panic-unwind.diff +++ b/tests/mir-opt/dest-prop/copy_propagation_arg.foo.DestinationPropagation.panic-unwind.diff @@ -10,7 +10,7 @@ bb0: { StorageLive(_2); - StorageLive(_3); -- _3 = _1; +- _3 = copy _1; - _2 = dummy(move _3) -> [return: bb1, unwind continue]; + nop; + nop; diff --git a/tests/mir-opt/dest-prop/copy_propagation_arg.rs b/tests/mir-opt/dest-prop/copy_propagation_arg.rs index 084bd0544c1..ef531f4afa2 100644 --- a/tests/mir-opt/dest-prop/copy_propagation_arg.rs +++ b/tests/mir-opt/dest-prop/copy_propagation_arg.rs @@ -41,9 +41,9 @@ fn arg_src(mut x: i32) -> i32 { // CHECK-LABEL: fn arg_src( // CHECK: debug x => [[x:_.*]]; // CHECK: debug y => [[y:_.*]]; - // CHECK: [[y]] = [[x]] + // CHECK: [[y]] = copy [[x]] // CHECK: [[x]] = const 123_i32; - // CHECK-NOT: {{_.*}} = [[y]]; + // CHECK-NOT: {{_.*}} = copy [[y]]; let y = x; x = 123; // Don't propagate this assignment to `y` y diff --git a/tests/mir-opt/dest-prop/cycle.main.DestinationPropagation.panic-abort.diff b/tests/mir-opt/dest-prop/cycle.main.DestinationPropagation.panic-abort.diff index 98b4ee866d2..5d8aaedae37 100644 --- a/tests/mir-opt/dest-prop/cycle.main.DestinationPropagation.panic-abort.diff +++ b/tests/mir-opt/dest-prop/cycle.main.DestinationPropagation.panic-abort.diff @@ -31,11 +31,11 @@ bb1: { - StorageLive(_2); -- _2 = _1; +- _2 = copy _1; - StorageLive(_3); -- _3 = _2; +- _3 = copy _2; - StorageLive(_4); -- _4 = _3; +- _4 = copy _3; - _1 = move _4; - StorageDead(_4); + nop; @@ -48,7 +48,7 @@ + nop; StorageLive(_5); - StorageLive(_6); -- _6 = _1; +- _6 = copy _1; + nop; + nop; _5 = std::mem::drop::(move _6) -> [return: bb2, unwind unreachable]; diff --git a/tests/mir-opt/dest-prop/cycle.main.DestinationPropagation.panic-unwind.diff b/tests/mir-opt/dest-prop/cycle.main.DestinationPropagation.panic-unwind.diff index 6f6e01d37b1..05c9bcc1d73 100644 --- a/tests/mir-opt/dest-prop/cycle.main.DestinationPropagation.panic-unwind.diff +++ b/tests/mir-opt/dest-prop/cycle.main.DestinationPropagation.panic-unwind.diff @@ -31,11 +31,11 @@ bb1: { - StorageLive(_2); -- _2 = _1; +- _2 = copy _1; - StorageLive(_3); -- _3 = _2; +- _3 = copy _2; - StorageLive(_4); -- _4 = _3; +- _4 = copy _3; - _1 = move _4; - StorageDead(_4); + nop; @@ -48,7 +48,7 @@ + nop; StorageLive(_5); - StorageLive(_6); -- _6 = _1; +- _6 = copy _1; + nop; + nop; _5 = std::mem::drop::(move _6) -> [return: bb2, unwind continue]; diff --git a/tests/mir-opt/dest-prop/dead_stores_79191.f.DestinationPropagation.after.panic-abort.mir b/tests/mir-opt/dest-prop/dead_stores_79191.f.DestinationPropagation.after.panic-abort.mir index eb160fc194a..eb4209731c6 100644 --- a/tests/mir-opt/dest-prop/dead_stores_79191.f.DestinationPropagation.after.panic-abort.mir +++ b/tests/mir-opt/dest-prop/dead_stores_79191.f.DestinationPropagation.after.panic-abort.mir @@ -12,7 +12,7 @@ fn f(_1: usize) -> usize { bb0: { nop; - _3 = _1; + _3 = copy _1; _1 = const 5_usize; nop; nop; diff --git a/tests/mir-opt/dest-prop/dead_stores_79191.f.DestinationPropagation.after.panic-unwind.mir b/tests/mir-opt/dest-prop/dead_stores_79191.f.DestinationPropagation.after.panic-unwind.mir index 9147de2ec47..fe9a7376a58 100644 --- a/tests/mir-opt/dest-prop/dead_stores_79191.f.DestinationPropagation.after.panic-unwind.mir +++ b/tests/mir-opt/dest-prop/dead_stores_79191.f.DestinationPropagation.after.panic-unwind.mir @@ -12,7 +12,7 @@ fn f(_1: usize) -> usize { bb0: { nop; - _3 = _1; + _3 = copy _1; _1 = const 5_usize; nop; nop; diff --git a/tests/mir-opt/dest-prop/dead_stores_79191.rs b/tests/mir-opt/dest-prop/dead_stores_79191.rs index 61060e4f850..d035de5ce07 100644 --- a/tests/mir-opt/dest-prop/dead_stores_79191.rs +++ b/tests/mir-opt/dest-prop/dead_stores_79191.rs @@ -10,7 +10,7 @@ fn f(mut a: usize) -> usize { // CHECK-LABEL: fn f( // CHECK: debug a => [[a:_.*]]; // CHECK: debug b => [[b:_.*]]; - // CHECK: [[b]] = [[a]]; + // CHECK: [[b]] = copy [[a]]; // CHECK: [[a]] = const 5_usize; // CHECK: [[a]] = move [[b]]; // CHECK: id::(move [[a]]) diff --git a/tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.panic-abort.mir b/tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.panic-abort.mir index eb160fc194a..eb4209731c6 100644 --- a/tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.panic-abort.mir +++ b/tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.panic-abort.mir @@ -12,7 +12,7 @@ fn f(_1: usize) -> usize { bb0: { nop; - _3 = _1; + _3 = copy _1; _1 = const 5_usize; nop; nop; diff --git a/tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.panic-unwind.mir b/tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.panic-unwind.mir index 9147de2ec47..fe9a7376a58 100644 --- a/tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.panic-unwind.mir +++ b/tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.panic-unwind.mir @@ -12,7 +12,7 @@ fn f(_1: usize) -> usize { bb0: { nop; - _3 = _1; + _3 = copy _1; _1 = const 5_usize; nop; nop; diff --git a/tests/mir-opt/dest-prop/dead_stores_better.rs b/tests/mir-opt/dest-prop/dead_stores_better.rs index d2b9fe05712..d4c297fd97a 100644 --- a/tests/mir-opt/dest-prop/dead_stores_better.rs +++ b/tests/mir-opt/dest-prop/dead_stores_better.rs @@ -14,7 +14,7 @@ pub fn f(mut a: usize) -> usize { // CHECK-LABEL: fn f( // CHECK: debug a => [[a:_.*]]; // CHECK: debug b => [[b:_.*]]; - // CHECK: [[b]] = [[a]]; + // CHECK: [[b]] = copy [[a]]; // CHECK: [[a]] = const 5_usize; // CHECK: [[a]] = move [[b]]; // CHECK: id::(move [[a]]) diff --git a/tests/mir-opt/dest-prop/simple.nrvo.DestinationPropagation.panic-abort.diff b/tests/mir-opt/dest-prop/simple.nrvo.DestinationPropagation.panic-abort.diff index 4d34f43fd5c..e9fbcf20a72 100644 --- a/tests/mir-opt/dest-prop/simple.nrvo.DestinationPropagation.panic-abort.diff +++ b/tests/mir-opt/dest-prop/simple.nrvo.DestinationPropagation.panic-abort.diff @@ -18,7 +18,7 @@ _2 = [const 0_u8; 1024]; StorageLive(_3); - StorageLive(_4); -- _4 = _1; +- _4 = copy _1; + nop; + nop; StorageLive(_5); @@ -35,7 +35,7 @@ + nop; StorageDead(_6); StorageDead(_3); - _0 = _2; + _0 = copy _2; StorageDead(_2); return; } diff --git a/tests/mir-opt/dest-prop/simple.nrvo.DestinationPropagation.panic-unwind.diff b/tests/mir-opt/dest-prop/simple.nrvo.DestinationPropagation.panic-unwind.diff index 9c3cbef38d6..95d5fe1b930 100644 --- a/tests/mir-opt/dest-prop/simple.nrvo.DestinationPropagation.panic-unwind.diff +++ b/tests/mir-opt/dest-prop/simple.nrvo.DestinationPropagation.panic-unwind.diff @@ -18,7 +18,7 @@ _2 = [const 0_u8; 1024]; StorageLive(_3); - StorageLive(_4); -- _4 = _1; +- _4 = copy _1; + nop; + nop; StorageLive(_5); @@ -35,7 +35,7 @@ + nop; StorageDead(_6); StorageDead(_3); - _0 = _2; + _0 = copy _2; StorageDead(_2); return; } diff --git a/tests/mir-opt/dest-prop/simple.rs b/tests/mir-opt/dest-prop/simple.rs index 833d49b8c46..927a9c5b24c 100644 --- a/tests/mir-opt/dest-prop/simple.rs +++ b/tests/mir-opt/dest-prop/simple.rs @@ -7,9 +7,9 @@ fn nrvo(init: fn(&mut [u8; 1024])) -> [u8; 1024] { // CHECK: debug init => [[init:_.*]]; // CHECK: debug buf => [[buf:_.*]]; // CHECK: [[buf]] = [const 0_u8; 1024]; - // CHECK-NOT: {{_.*}} = [[init]]; + // CHECK-NOT: {{_.*}} = copy [[init]]; // CHECK: move [[init]](move {{_.*}}) - // CHECK: {{_.*}} = [[buf]] + // CHECK: {{_.*}} = copy [[buf]] let mut buf = [0; 1024]; init(&mut buf); buf diff --git a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff index b596e25ddfd..557320f0179 100644 --- a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff +++ b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff @@ -22,7 +22,7 @@ _1 = Un { us: const 1_u32 }; StorageDead(_2); StorageLive(_3); - _3 = (_1.0: u32); + _3 = copy (_1.0: u32); StorageDead(_3); StorageDead(_1); return; diff --git a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff index b596e25ddfd..557320f0179 100644 --- a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff +++ b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff @@ -22,7 +22,7 @@ _1 = Un { us: const 1_u32 }; StorageDead(_2); StorageLive(_3); - _3 = (_1.0: u32); + _3 = copy (_1.0: u32); StorageDead(_3); StorageDead(_1); return; diff --git a/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff index 4af3ed3e1d1..51c41996678 100644 --- a/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff @@ -20,9 +20,9 @@ bb0: { StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; StorageLive(_5); - _5 = _2; + _5 = copy _2; _3 = (move _4, move _5); StorageDead(_5); StorageDead(_4); @@ -42,9 +42,9 @@ bb3: { StorageLive(_8); - _8 = (((_3.0: std::option::Option) as Some).0: u32); + _8 = copy (((_3.0: std::option::Option) as Some).0: u32); StorageLive(_9); - _9 = (((_3.1: std::option::Option) as Some).0: u32); + _9 = copy (((_3.1: std::option::Option) as Some).0: u32); _0 = const 0_u32; StorageDead(_9); StorageDead(_8); diff --git a/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff index 41ae2fd3af3..f17ebee9416 100644 --- a/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff @@ -21,9 +21,9 @@ bb0: { StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; StorageLive(_5); - _5 = _2; + _5 = copy _2; _3 = (move _4, move _5); StorageDead(_5); StorageDead(_4); @@ -53,9 +53,9 @@ bb5: { StorageLive(_9); - _9 = (((_3.0: std::option::Option) as Some).0: u32); + _9 = copy (((_3.0: std::option::Option) as Some).0: u32); StorageLive(_10); - _10 = (((_3.1: std::option::Option) as Some).0: u32); + _10 = copy (((_3.1: std::option::Option) as Some).0: u32); _0 = const 0_u32; StorageDead(_10); StorageDead(_9); diff --git a/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff index 302fd0bfded..7b94a4c2bf7 100644 --- a/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff @@ -35,7 +35,7 @@ + StorageLive(_12); + _12 = discriminant((_3.1: Option2)); + StorageLive(_13); -+ _13 = Ne(_9, move _12); ++ _13 = Ne(copy _9, move _12); + StorageDead(_12); + switchInt(move _13) -> [0: bb7, otherwise: bb1]; } @@ -78,9 +78,9 @@ - bb7: { + bb4: { StorageLive(_10); - _10 = (((_3.0: Option2) as Some).0: u32); + _10 = copy (((_3.0: Option2) as Some).0: u32); StorageLive(_11); - _11 = (((_3.1: Option2) as Some).0: bool); + _11 = copy (((_3.1: Option2) as Some).0: bool); _0 = const 0_u32; StorageDead(_11); StorageDead(_10); @@ -101,7 +101,7 @@ + + bb7: { + StorageDead(_13); -+ switchInt(_9) -> [0: bb4, 1: bb3, 2: bb2, otherwise: bb6]; ++ switchInt(copy _9) -> [0: bb4, 1: bb3, 2: bb2, otherwise: bb6]; } } diff --git a/tests/mir-opt/early_otherwise_branch.opt4.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt4.EarlyOtherwiseBranch.diff index eef4fb3278c..f52795baef8 100644 --- a/tests/mir-opt/early_otherwise_branch.opt4.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch.opt4.EarlyOtherwiseBranch.diff @@ -35,7 +35,7 @@ + StorageLive(_12); + _12 = discriminant((_3.1: Option2)); + StorageLive(_13); -+ _13 = Ne(_9, move _12); ++ _13 = Ne(copy _9, move _12); + StorageDead(_12); + switchInt(move _13) -> [0: bb7, otherwise: bb1]; } @@ -78,9 +78,9 @@ - bb7: { + bb4: { StorageLive(_10); - _10 = (((_3.0: Option2) as Some).0: u32); + _10 = copy (((_3.0: Option2) as Some).0: u32); StorageLive(_11); - _11 = (((_3.1: Option2) as Some).0: u32); + _11 = copy (((_3.1: Option2) as Some).0: u32); _0 = const 0_u32; StorageDead(_11); StorageDead(_10); @@ -101,7 +101,7 @@ + + bb7: { + StorageDead(_13); -+ switchInt(_9) -> [0: bb4, 1: bb3, 2: bb2, otherwise: bb6]; ++ switchInt(copy _9) -> [0: bb4, 1: bb3, 2: bb2, otherwise: bb6]; } } diff --git a/tests/mir-opt/early_otherwise_branch.rs b/tests/mir-opt/early_otherwise_branch.rs index b047c50df97..47bd4be295b 100644 --- a/tests/mir-opt/early_otherwise_branch.rs +++ b/tests/mir-opt/early_otherwise_branch.rs @@ -49,7 +49,7 @@ fn opt3(x: Option2, y: Option2) -> u32 { // CHECK: bb0: { // CHECK: [[LOCAL1:_.*]] = discriminant({{.*}}); // CHECK: [[LOCAL2:_.*]] = discriminant({{.*}}); - // CHECK: [[CMP_LOCAL]] = Ne([[LOCAL1]], move [[LOCAL2]]); + // CHECK: [[CMP_LOCAL]] = Ne(copy [[LOCAL1]], move [[LOCAL2]]); // CHECK: switchInt(move [[CMP_LOCAL]]) -> [ // CHECK-NEXT: } match (x, y) { @@ -67,7 +67,7 @@ fn opt4(x: Option2, y: Option2) -> u32 { // CHECK: bb0: { // CHECK: [[LOCAL1:_.*]] = discriminant({{.*}}); // CHECK: [[LOCAL2:_.*]] = discriminant({{.*}}); - // CHECK: [[CMP_LOCAL]] = Ne([[LOCAL1]], move [[LOCAL2]]); + // CHECK: [[CMP_LOCAL]] = Ne(copy [[LOCAL1]], move [[LOCAL2]]); // CHECK: switchInt(move [[CMP_LOCAL]]) -> [ // CHECK-NEXT: } match (x, y) { diff --git a/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff index cb03e2697cc..98df9934af0 100644 --- a/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff @@ -27,11 +27,11 @@ bb0: { StorageLive(_4); StorageLive(_5); - _5 = _1; + _5 = copy _1; StorageLive(_6); - _6 = _2; + _6 = copy _2; StorageLive(_7); - _7 = _3; + _7 = copy _3; _4 = (move _5, move _6, move _7); StorageDead(_7); StorageDead(_6); @@ -72,11 +72,11 @@ bb7: { StorageLive(_13); - _13 = (((_4.0: std::option::Option) as Some).0: u32); + _13 = copy (((_4.0: std::option::Option) as Some).0: u32); StorageLive(_14); - _14 = (((_4.1: std::option::Option) as Some).0: u32); + _14 = copy (((_4.1: std::option::Option) as Some).0: u32); StorageLive(_15); - _15 = (((_4.2: std::option::Option) as Some).0: u32); + _15 = copy (((_4.2: std::option::Option) as Some).0: u32); _0 = const 0_u32; StorageDead(_15); StorageDead(_14); diff --git a/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt2.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt2.EarlyOtherwiseBranch.diff index 5634df253a5..831d8cbb4d6 100644 --- a/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt2.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt2.EarlyOtherwiseBranch.diff @@ -45,7 +45,7 @@ + StorageLive(_18); + _18 = discriminant((_4.1: Option2)); + StorageLive(_19); -+ _19 = Ne(_14, move _18); ++ _19 = Ne(copy _14, move _18); + StorageDead(_18); + switchInt(move _19) -> [0: bb10, otherwise: bb1]; } @@ -109,11 +109,11 @@ - bb10: { + bb7: { StorageLive(_15); - _15 = (((_4.0: Option2) as Some).0: u32); + _15 = copy (((_4.0: Option2) as Some).0: u32); StorageLive(_16); - _16 = (((_4.1: Option2) as Some).0: u32); + _16 = copy (((_4.1: Option2) as Some).0: u32); StorageLive(_17); - _17 = (((_4.2: Option2) as Some).0: u32); + _17 = copy (((_4.2: Option2) as Some).0: u32); _0 = const 0_u32; StorageDead(_17); StorageDead(_16); @@ -135,7 +135,7 @@ + + bb10: { + StorageDead(_19); -+ switchInt(_14) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb9]; ++ switchInt(copy _14) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb9]; } } diff --git a/tests/mir-opt/early_otherwise_branch_3_element_tuple.rs b/tests/mir-opt/early_otherwise_branch_3_element_tuple.rs index d2a3e1f59ff..d6b27fbce48 100644 --- a/tests/mir-opt/early_otherwise_branch_3_element_tuple.rs +++ b/tests/mir-opt/early_otherwise_branch_3_element_tuple.rs @@ -32,7 +32,7 @@ fn opt2(x: Option2, y: Option2, z: Option2) -> u32 { // CHECK: bb0: { // CHECK: [[LOCAL1:_.*]] = discriminant({{.*}}); // CHECK: [[LOCAL2:_.*]] = discriminant({{.*}}); - // CHECK: [[CMP_LOCAL]] = Ne([[LOCAL1]], move [[LOCAL2]]); + // CHECK: [[CMP_LOCAL]] = Ne(copy [[LOCAL1]], move [[LOCAL2]]); // CHECK: switchInt(move [[CMP_LOCAL]]) -> [ // CHECK-NEXT: } match (x, y, z) { diff --git a/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff index 8179d9dd115..fec318c1ab4 100644 --- a/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff @@ -70,9 +70,9 @@ StorageLive(_3); StorageLive(_4); StorageLive(_5); - _5 = _1; + _5 = copy _1; StorageLive(_6); - _6 = _2; + _6 = copy _2; _4 = (move _5, move _6); StorageDead(_6); StorageDead(_5); @@ -118,15 +118,15 @@ bb6: { StorageLive(_27); _39 = deref_copy (_4.0: &ViewportPercentageLength); - _27 = (((*_39) as Vmax).0: f32); + _27 = copy (((*_39) as Vmax).0: f32); StorageLive(_28); _40 = deref_copy (_4.1: &ViewportPercentageLength); - _28 = (((*_40) as Vmax).0: f32); + _28 = copy (((*_40) as Vmax).0: f32); StorageLive(_29); StorageLive(_30); - _30 = _27; + _30 = copy _27; StorageLive(_31); - _31 = _28; + _31 = copy _28; _29 = Add(move _30, move _31); StorageDead(_31); StorageDead(_30); @@ -140,15 +140,15 @@ bb7: { StorageLive(_22); _41 = deref_copy (_4.0: &ViewportPercentageLength); - _22 = (((*_41) as Vmin).0: f32); + _22 = copy (((*_41) as Vmin).0: f32); StorageLive(_23); _42 = deref_copy (_4.1: &ViewportPercentageLength); - _23 = (((*_42) as Vmin).0: f32); + _23 = copy (((*_42) as Vmin).0: f32); StorageLive(_24); StorageLive(_25); - _25 = _22; + _25 = copy _22; StorageLive(_26); - _26 = _23; + _26 = copy _23; _24 = Add(move _25, move _26); StorageDead(_26); StorageDead(_25); @@ -162,15 +162,15 @@ bb8: { StorageLive(_17); _43 = deref_copy (_4.0: &ViewportPercentageLength); - _17 = (((*_43) as Vh).0: f32); + _17 = copy (((*_43) as Vh).0: f32); StorageLive(_18); _44 = deref_copy (_4.1: &ViewportPercentageLength); - _18 = (((*_44) as Vh).0: f32); + _18 = copy (((*_44) as Vh).0: f32); StorageLive(_19); StorageLive(_20); - _20 = _17; + _20 = copy _17; StorageLive(_21); - _21 = _18; + _21 = copy _18; _19 = Add(move _20, move _21); StorageDead(_21); StorageDead(_20); @@ -184,15 +184,15 @@ bb9: { StorageLive(_12); _45 = deref_copy (_4.0: &ViewportPercentageLength); - _12 = (((*_45) as Vw).0: f32); + _12 = copy (((*_45) as Vw).0: f32); StorageLive(_13); _46 = deref_copy (_4.1: &ViewportPercentageLength); - _13 = (((*_46) as Vw).0: f32); + _13 = copy (((*_46) as Vw).0: f32); StorageLive(_14); StorageLive(_15); - _15 = _12; + _15 = copy _12; StorageLive(_16); - _16 = _13; + _16 = copy _13; _14 = Add(move _15, move _16); StorageDead(_16); StorageDead(_15); diff --git a/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff index 651b1de4ddd..8ed2274a72b 100644 --- a/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff @@ -29,9 +29,9 @@ bb0: { StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; StorageLive(_5); - _5 = _2; + _5 = copy _2; _3 = (move _4, move _5); StorageDead(_5); StorageDead(_4); @@ -60,7 +60,7 @@ bb5: { StorageLive(_12); - _12 = (((_3.1: std::option::Option) as Some).0: u32); + _12 = copy (((_3.1: std::option::Option) as Some).0: u32); _0 = const 2_u32; StorageDead(_12); goto -> bb8; @@ -68,7 +68,7 @@ bb6: { StorageLive(_11); - _11 = (((_3.0: std::option::Option) as Some).0: u32); + _11 = copy (((_3.0: std::option::Option) as Some).0: u32); _0 = const 1_u32; StorageDead(_11); goto -> bb8; @@ -76,9 +76,9 @@ bb7: { StorageLive(_9); - _9 = (((_3.0: std::option::Option) as Some).0: u32); + _9 = copy (((_3.0: std::option::Option) as Some).0: u32); StorageLive(_10); - _10 = (((_3.1: std::option::Option) as Some).0: u32); + _10 = copy (((_3.1: std::option::Option) as Some).0: u32); _0 = const 0_u32; StorageDead(_10); StorageDead(_9); diff --git a/tests/mir-opt/early_otherwise_branch_soundness.no_deref_ptr.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_soundness.no_deref_ptr.EarlyOtherwiseBranch.diff index 8eab59823f4..eeb8b766b5d 100644 --- a/tests/mir-opt/early_otherwise_branch_soundness.no_deref_ptr.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch_soundness.no_deref_ptr.EarlyOtherwiseBranch.diff @@ -34,8 +34,8 @@ bb4: { StorageLive(_5); - _5 = (((*_2) as Some).0: i32); - _0 = _5; + _5 = copy (((*_2) as Some).0: i32); + _0 = copy _5; StorageDead(_5); goto -> bb5; } diff --git a/tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff index 085c55caaa0..727efe4b0d9 100644 --- a/tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff +++ b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff @@ -38,28 +38,28 @@ + StorageLive(_4); + _4 = const [2_usize, 8197_usize]; + _5 = discriminant(_2); -+ _6 = _5 as usize (IntToInt); -+ _7 = _4[_6]; ++ _6 = copy _5 as usize (IntToInt); ++ _7 = copy _4[_6]; + _8 = &raw mut _1; -+ _9 = _8 as *mut u8 (PtrToPtr); ++ _9 = copy _8 as *mut u8 (PtrToPtr); + _10 = &raw const _2; -+ _11 = _10 as *const u8 (PtrToPtr); ++ _11 = copy _10 as *const u8 (PtrToPtr); + Deinit(_8); -+ copy_nonoverlapping(dst = _9, src = _11, count = _7); ++ copy_nonoverlapping(dst = copy _9, src = copy _11, count = copy _7); + StorageDead(_4); StorageDead(_2); - _0 = move _1; + StorageLive(_12); + _12 = const [2_usize, 8197_usize]; + _13 = discriminant(_1); -+ _14 = _13 as usize (IntToInt); -+ _15 = _12[_14]; ++ _14 = copy _13 as usize (IntToInt); ++ _15 = copy _12[_14]; + _16 = &raw mut _0; -+ _17 = _16 as *mut u8 (PtrToPtr); ++ _17 = copy _16 as *mut u8 (PtrToPtr); + _18 = &raw const _1; -+ _19 = _18 as *const u8 (PtrToPtr); ++ _19 = copy _18 as *const u8 (PtrToPtr); + Deinit(_16); -+ copy_nonoverlapping(dst = _17, src = _19, count = _15); ++ copy_nonoverlapping(dst = copy _17, src = copy _19, count = copy _15); + StorageDead(_12); StorageDead(_1); return; diff --git a/tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff index 798b7c10fe8..8d0cd97f786 100644 --- a/tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff +++ b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff @@ -38,28 +38,28 @@ + StorageLive(_4); + _4 = const [2_usize, 8197_usize]; + _5 = discriminant(_2); -+ _6 = _5 as usize (IntToInt); -+ _7 = _4[_6]; ++ _6 = copy _5 as usize (IntToInt); ++ _7 = copy _4[_6]; + _8 = &raw mut _1; -+ _9 = _8 as *mut u8 (PtrToPtr); ++ _9 = copy _8 as *mut u8 (PtrToPtr); + _10 = &raw const _2; -+ _11 = _10 as *const u8 (PtrToPtr); ++ _11 = copy _10 as *const u8 (PtrToPtr); + Deinit(_8); -+ copy_nonoverlapping(dst = _9, src = _11, count = _7); ++ copy_nonoverlapping(dst = copy _9, src = copy _11, count = copy _7); + StorageDead(_4); StorageDead(_2); - _0 = move _1; + StorageLive(_12); + _12 = const [2_usize, 8197_usize]; + _13 = discriminant(_1); -+ _14 = _13 as usize (IntToInt); -+ _15 = _12[_14]; ++ _14 = copy _13 as usize (IntToInt); ++ _15 = copy _12[_14]; + _16 = &raw mut _0; -+ _17 = _16 as *mut u8 (PtrToPtr); ++ _17 = copy _16 as *mut u8 (PtrToPtr); + _18 = &raw const _1; -+ _19 = _18 as *const u8 (PtrToPtr); ++ _19 = copy _18 as *const u8 (PtrToPtr); + Deinit(_16); -+ copy_nonoverlapping(dst = _17, src = _19, count = _15); ++ copy_nonoverlapping(dst = copy _17, src = copy _19, count = copy _15); + StorageDead(_12); StorageDead(_1); return; diff --git a/tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff index a04829af4b5..6d1e2a72fdb 100644 --- a/tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff +++ b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff @@ -38,28 +38,28 @@ + StorageLive(_4); + _4 = const [8197_usize, 1_usize]; + _5 = discriminant(_2); -+ _6 = _5 as usize (IntToInt); -+ _7 = _4[_6]; ++ _6 = copy _5 as usize (IntToInt); ++ _7 = copy _4[_6]; + _8 = &raw mut _1; -+ _9 = _8 as *mut u8 (PtrToPtr); ++ _9 = copy _8 as *mut u8 (PtrToPtr); + _10 = &raw const _2; -+ _11 = _10 as *const u8 (PtrToPtr); ++ _11 = copy _10 as *const u8 (PtrToPtr); + Deinit(_8); -+ copy_nonoverlapping(dst = _9, src = _11, count = _7); ++ copy_nonoverlapping(dst = copy _9, src = copy _11, count = copy _7); + StorageDead(_4); StorageDead(_2); - _0 = move _1; + StorageLive(_12); + _12 = const [8197_usize, 1_usize]; + _13 = discriminant(_1); -+ _14 = _13 as usize (IntToInt); -+ _15 = _12[_14]; ++ _14 = copy _13 as usize (IntToInt); ++ _15 = copy _12[_14]; + _16 = &raw mut _0; -+ _17 = _16 as *mut u8 (PtrToPtr); ++ _17 = copy _16 as *mut u8 (PtrToPtr); + _18 = &raw const _1; -+ _19 = _18 as *const u8 (PtrToPtr); ++ _19 = copy _18 as *const u8 (PtrToPtr); + Deinit(_16); -+ copy_nonoverlapping(dst = _17, src = _19, count = _15); ++ copy_nonoverlapping(dst = copy _17, src = copy _19, count = copy _15); + StorageDead(_12); StorageDead(_1); return; diff --git a/tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff index f5521a1e22a..4b1406d0d62 100644 --- a/tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff +++ b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff @@ -38,28 +38,28 @@ + StorageLive(_4); + _4 = const [8197_usize, 1_usize]; + _5 = discriminant(_2); -+ _6 = _5 as usize (IntToInt); -+ _7 = _4[_6]; ++ _6 = copy _5 as usize (IntToInt); ++ _7 = copy _4[_6]; + _8 = &raw mut _1; -+ _9 = _8 as *mut u8 (PtrToPtr); ++ _9 = copy _8 as *mut u8 (PtrToPtr); + _10 = &raw const _2; -+ _11 = _10 as *const u8 (PtrToPtr); ++ _11 = copy _10 as *const u8 (PtrToPtr); + Deinit(_8); -+ copy_nonoverlapping(dst = _9, src = _11, count = _7); ++ copy_nonoverlapping(dst = copy _9, src = copy _11, count = copy _7); + StorageDead(_4); StorageDead(_2); - _0 = move _1; + StorageLive(_12); + _12 = const [8197_usize, 1_usize]; + _13 = discriminant(_1); -+ _14 = _13 as usize (IntToInt); -+ _15 = _12[_14]; ++ _14 = copy _13 as usize (IntToInt); ++ _15 = copy _12[_14]; + _16 = &raw mut _0; -+ _17 = _16 as *mut u8 (PtrToPtr); ++ _17 = copy _16 as *mut u8 (PtrToPtr); + _18 = &raw const _1; -+ _19 = _18 as *const u8 (PtrToPtr); ++ _19 = copy _18 as *const u8 (PtrToPtr); + Deinit(_16); -+ copy_nonoverlapping(dst = _17, src = _19, count = _15); ++ copy_nonoverlapping(dst = copy _17, src = copy _19, count = copy _15); + StorageDead(_12); StorageDead(_1); return; diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff index 8a701641ff9..ed72ca72629 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff @@ -42,13 +42,13 @@ StorageLive(_4); StorageLive(_20); StorageLive(_21); - _21 = ((*_1).0: u32); + _21 = copy ((*_1).0: u32); _20 = BitAnd(move _21, const 1_u32); StorageDead(_21); _4 = Ne(move _20, const 0_u32); StorageDead(_20); StorageLive(_5); - switchInt(_4) -> [0: bb2, otherwise: bb1]; + switchInt(copy _4) -> [0: bb2, otherwise: bb1]; } bb1: { @@ -65,7 +65,7 @@ bb3: { StorageLive(_6); - _6 = ((*_1).4: std::option::Option); + _6 = copy ((*_1).4: std::option::Option); _7 = discriminant(_6); switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb9]; } @@ -73,26 +73,26 @@ bb4: { - StorageLive(_8); + nop; - _8 = ((_6 as Some).0: usize); + _8 = copy ((_6 as Some).0: usize); StorageLive(_9); - _9 = _1; + _9 = copy _1; StorageLive(_10); - _10 = _2; + _10 = copy _2; StorageLive(_11); - _11 = _5; + _11 = copy _5; StorageLive(_12); StorageLive(_13); StorageLive(_14); - _14 = _8; + _14 = copy _8; - _13 = move _14 as u32 (IntToInt); -+ _13 = _8 as u32 (IntToInt); ++ _13 = copy _8 as u32 (IntToInt); StorageDead(_14); _12 = Add(move _13, const 1_u32); StorageDead(_13); StorageLive(_15); - _15 = _3; + _15 = copy _3; - _0 = float_to_exponential_common_exact::(move _9, move _10, move _11, move _12, move _15) -> [return: bb5, unwind unreachable]; -+ _0 = float_to_exponential_common_exact::(_1, _2, move _11, move _12, _3) -> [return: bb5, unwind unreachable]; ++ _0 = float_to_exponential_common_exact::(copy _1, copy _2, move _11, move _12, copy _3) -> [return: bb5, unwind unreachable]; } bb5: { @@ -108,15 +108,15 @@ bb6: { StorageLive(_16); - _16 = _1; + _16 = copy _1; StorageLive(_17); - _17 = _2; + _17 = copy _2; StorageLive(_18); - _18 = _5; + _18 = copy _5; StorageLive(_19); - _19 = _3; + _19 = copy _3; - _0 = float_to_exponential_common_shortest::(move _16, move _17, move _18, move _19) -> [return: bb7, unwind unreachable]; -+ _0 = float_to_exponential_common_shortest::(_1, _2, move _18, _3) -> [return: bb7, unwind unreachable]; ++ _0 = float_to_exponential_common_shortest::(copy _1, copy _2, move _18, copy _3) -> [return: bb7, unwind unreachable]; } bb7: { diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff index 5e65700ee4a..42d99883749 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff @@ -42,13 +42,13 @@ StorageLive(_4); StorageLive(_20); StorageLive(_21); - _21 = ((*_1).0: u32); + _21 = copy ((*_1).0: u32); _20 = BitAnd(move _21, const 1_u32); StorageDead(_21); _4 = Ne(move _20, const 0_u32); StorageDead(_20); StorageLive(_5); - switchInt(_4) -> [0: bb2, otherwise: bb1]; + switchInt(copy _4) -> [0: bb2, otherwise: bb1]; } bb1: { @@ -65,7 +65,7 @@ bb3: { StorageLive(_6); - _6 = ((*_1).4: std::option::Option); + _6 = copy ((*_1).4: std::option::Option); _7 = discriminant(_6); switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb9]; } @@ -73,26 +73,26 @@ bb4: { - StorageLive(_8); + nop; - _8 = ((_6 as Some).0: usize); + _8 = copy ((_6 as Some).0: usize); StorageLive(_9); - _9 = _1; + _9 = copy _1; StorageLive(_10); - _10 = _2; + _10 = copy _2; StorageLive(_11); - _11 = _5; + _11 = copy _5; StorageLive(_12); StorageLive(_13); StorageLive(_14); - _14 = _8; + _14 = copy _8; - _13 = move _14 as u32 (IntToInt); -+ _13 = _8 as u32 (IntToInt); ++ _13 = copy _8 as u32 (IntToInt); StorageDead(_14); _12 = Add(move _13, const 1_u32); StorageDead(_13); StorageLive(_15); - _15 = _3; + _15 = copy _3; - _0 = float_to_exponential_common_exact::(move _9, move _10, move _11, move _12, move _15) -> [return: bb5, unwind continue]; -+ _0 = float_to_exponential_common_exact::(_1, _2, move _11, move _12, _3) -> [return: bb5, unwind continue]; ++ _0 = float_to_exponential_common_exact::(copy _1, copy _2, move _11, move _12, copy _3) -> [return: bb5, unwind continue]; } bb5: { @@ -108,15 +108,15 @@ bb6: { StorageLive(_16); - _16 = _1; + _16 = copy _1; StorageLive(_17); - _17 = _2; + _17 = copy _2; StorageLive(_18); - _18 = _5; + _18 = copy _5; StorageLive(_19); - _19 = _3; + _19 = copy _3; - _0 = float_to_exponential_common_shortest::(move _16, move _17, move _18, move _19) -> [return: bb7, unwind continue]; -+ _0 = float_to_exponential_common_shortest::(_1, _2, move _18, _3) -> [return: bb7, unwind continue]; ++ _0 = float_to_exponential_common_shortest::(copy _1, copy _2, move _18, copy _3) -> [return: bb7, unwind continue]; } bb7: { diff --git a/tests/mir-opt/gvn.arithmetic.GVN.panic-abort.diff b/tests/mir-opt/gvn.arithmetic.GVN.panic-abort.diff index cb87d902015..f980645b1d0 100644 --- a/tests/mir-opt/gvn.arithmetic.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.arithmetic.GVN.panic-abort.diff @@ -82,12 +82,12 @@ StorageLive(_2); StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; - _3 = Add(move _4, const 0_u64); -+ _3 = _1; ++ _3 = copy _1; StorageDead(_4); - _2 = opaque::(move _3) -> [return: bb1, unwind unreachable]; -+ _2 = opaque::(_1) -> [return: bb1, unwind unreachable]; ++ _2 = opaque::(copy _1) -> [return: bb1, unwind unreachable]; } bb1: { @@ -96,12 +96,12 @@ StorageLive(_5); StorageLive(_6); StorageLive(_7); - _7 = _1; + _7 = copy _1; - _6 = Sub(move _7, const 0_u64); -+ _6 = _1; ++ _6 = copy _1; StorageDead(_7); - _5 = opaque::(move _6) -> [return: bb2, unwind unreachable]; -+ _5 = opaque::(_1) -> [return: bb2, unwind unreachable]; ++ _5 = opaque::(copy _1) -> [return: bb2, unwind unreachable]; } bb2: { @@ -111,9 +111,9 @@ - StorageLive(_9); + nop; StorageLive(_10); - _10 = _1; + _10 = copy _1; StorageLive(_11); - _11 = _1; + _11 = copy _1; - _9 = Sub(move _10, move _11); + _9 = const 0_u64; StorageDead(_11); @@ -129,7 +129,7 @@ StorageLive(_12); StorageLive(_13); StorageLive(_14); - _14 = _1; + _14 = copy _1; - _13 = Mul(move _14, const 0_u64); + _13 = const 0_u64; StorageDead(_14); @@ -143,12 +143,12 @@ StorageLive(_15); StorageLive(_16); StorageLive(_17); - _17 = _1; + _17 = copy _1; - _16 = Mul(move _17, const 1_u64); -+ _16 = _1; ++ _16 = copy _1; StorageDead(_17); - _15 = opaque::(move _16) -> [return: bb5, unwind unreachable]; -+ _15 = opaque::(_1) -> [return: bb5, unwind unreachable]; ++ _15 = opaque::(copy _1) -> [return: bb5, unwind unreachable]; } bb5: { @@ -157,16 +157,16 @@ StorageLive(_18); StorageLive(_19); StorageLive(_20); - _20 = _1; + _20 = copy _1; - _21 = Eq(const 0_u64, const 0_u64); -- assert(!move _21, "attempt to divide `{}` by zero", _20) -> [success: bb6, unwind unreachable]; +- assert(!move _21, "attempt to divide `{}` by zero", copy _20) -> [success: bb6, unwind unreachable]; + _21 = const true; -+ assert(!const true, "attempt to divide `{}` by zero", _1) -> [success: bb6, unwind unreachable]; ++ assert(!const true, "attempt to divide `{}` by zero", copy _1) -> [success: bb6, unwind unreachable]; } bb6: { - _19 = Div(move _20, const 0_u64); -+ _19 = Div(_1, const 0_u64); ++ _19 = Div(copy _1, const 0_u64); StorageDead(_20); _18 = opaque::(move _19) -> [return: bb7, unwind unreachable]; } @@ -177,19 +177,19 @@ StorageLive(_22); StorageLive(_23); StorageLive(_24); - _24 = _1; + _24 = copy _1; - _25 = Eq(const 1_u64, const 0_u64); -- assert(!move _25, "attempt to divide `{}` by zero", _24) -> [success: bb8, unwind unreachable]; +- assert(!move _25, "attempt to divide `{}` by zero", copy _24) -> [success: bb8, unwind unreachable]; + _25 = const false; -+ assert(!const false, "attempt to divide `{}` by zero", _1) -> [success: bb8, unwind unreachable]; ++ assert(!const false, "attempt to divide `{}` by zero", copy _1) -> [success: bb8, unwind unreachable]; } bb8: { - _23 = Div(move _24, const 1_u64); -+ _23 = _1; ++ _23 = copy _1; StorageDead(_24); - _22 = opaque::(move _23) -> [return: bb9, unwind unreachable]; -+ _22 = opaque::(_1) -> [return: bb9, unwind unreachable]; ++ _22 = opaque::(copy _1) -> [return: bb9, unwind unreachable]; } bb9: { @@ -198,11 +198,11 @@ StorageLive(_26); StorageLive(_27); StorageLive(_28); - _28 = _1; -- _29 = Eq(_28, const 0_u64); + _28 = copy _1; +- _29 = Eq(copy _28, const 0_u64); - assert(!move _29, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb10, unwind unreachable]; -+ _29 = Eq(_1, const 0_u64); -+ assert(!_29, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb10, unwind unreachable]; ++ _29 = Eq(copy _1, const 0_u64); ++ assert(!copy _29, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb10, unwind unreachable]; } bb10: { @@ -219,16 +219,16 @@ StorageLive(_30); StorageLive(_31); StorageLive(_32); - _32 = _1; -- _33 = Eq(_32, const 0_u64); + _32 = copy _1; +- _33 = Eq(copy _32, const 0_u64); - assert(!move _33, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb12, unwind unreachable]; -+ _33 = _29; -+ assert(!_29, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb12, unwind unreachable]; ++ _33 = copy _29; ++ assert(!copy _29, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb12, unwind unreachable]; } bb12: { - _31 = Div(const 1_u64, move _32); -+ _31 = Div(const 1_u64, _1); ++ _31 = Div(const 1_u64, copy _1); StorageDead(_32); _30 = opaque::(move _31) -> [return: bb13, unwind unreachable]; } @@ -239,16 +239,16 @@ StorageLive(_34); StorageLive(_35); StorageLive(_36); - _36 = _1; + _36 = copy _1; - _37 = Eq(const 0_u64, const 0_u64); -- assert(!move _37, "attempt to calculate the remainder of `{}` with a divisor of zero", _36) -> [success: bb14, unwind unreachable]; +- assert(!move _37, "attempt to calculate the remainder of `{}` with a divisor of zero", copy _36) -> [success: bb14, unwind unreachable]; + _37 = const true; -+ assert(!const true, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb14, unwind unreachable]; ++ assert(!const true, "attempt to calculate the remainder of `{}` with a divisor of zero", copy _1) -> [success: bb14, unwind unreachable]; } bb14: { - _35 = Rem(move _36, const 0_u64); -+ _35 = Rem(_1, const 0_u64); ++ _35 = Rem(copy _1, const 0_u64); StorageDead(_36); _34 = opaque::(move _35) -> [return: bb15, unwind unreachable]; } @@ -259,11 +259,11 @@ StorageLive(_38); StorageLive(_39); StorageLive(_40); - _40 = _1; + _40 = copy _1; - _41 = Eq(const 1_u64, const 0_u64); -- assert(!move _41, "attempt to calculate the remainder of `{}` with a divisor of zero", _40) -> [success: bb16, unwind unreachable]; +- assert(!move _41, "attempt to calculate the remainder of `{}` with a divisor of zero", copy _40) -> [success: bb16, unwind unreachable]; + _41 = const false; -+ assert(!const false, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb16, unwind unreachable]; ++ assert(!const false, "attempt to calculate the remainder of `{}` with a divisor of zero", copy _1) -> [success: bb16, unwind unreachable]; } bb16: { @@ -280,11 +280,11 @@ StorageLive(_42); StorageLive(_43); StorageLive(_44); - _44 = _1; -- _45 = Eq(_44, const 0_u64); + _44 = copy _1; +- _45 = Eq(copy _44, const 0_u64); - assert(!move _45, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb18, unwind unreachable]; -+ _45 = _29; -+ assert(!_29, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb18, unwind unreachable]; ++ _45 = copy _29; ++ assert(!copy _29, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb18, unwind unreachable]; } bb18: { @@ -301,16 +301,16 @@ StorageLive(_46); StorageLive(_47); StorageLive(_48); - _48 = _1; -- _49 = Eq(_48, const 0_u64); + _48 = copy _1; +- _49 = Eq(copy _48, const 0_u64); - assert(!move _49, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb20, unwind unreachable]; -+ _49 = _29; -+ assert(!_29, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb20, unwind unreachable]; ++ _49 = copy _29; ++ assert(!copy _29, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb20, unwind unreachable]; } bb20: { - _47 = Rem(const 1_u64, move _48); -+ _47 = Rem(const 1_u64, _1); ++ _47 = Rem(const 1_u64, copy _1); StorageDead(_48); _46 = opaque::(move _47) -> [return: bb21, unwind unreachable]; } @@ -321,7 +321,7 @@ StorageLive(_50); StorageLive(_51); StorageLive(_52); - _52 = _1; + _52 = copy _1; - _51 = BitAnd(move _52, const 0_u64); + _51 = const 0_u64; StorageDead(_52); @@ -335,12 +335,12 @@ StorageLive(_53); StorageLive(_54); StorageLive(_55); - _55 = _1; + _55 = copy _1; - _54 = BitAnd(move _55, const core::num::::MAX); -+ _54 = _1; ++ _54 = copy _1; StorageDead(_55); - _53 = opaque::(move _54) -> [return: bb23, unwind unreachable]; -+ _53 = opaque::(_1) -> [return: bb23, unwind unreachable]; ++ _53 = opaque::(copy _1) -> [return: bb23, unwind unreachable]; } bb23: { @@ -349,12 +349,12 @@ StorageLive(_56); StorageLive(_57); StorageLive(_58); - _58 = _1; + _58 = copy _1; - _57 = BitOr(move _58, const 0_u64); -+ _57 = _1; ++ _57 = copy _1; StorageDead(_58); - _56 = opaque::(move _57) -> [return: bb24, unwind unreachable]; -+ _56 = opaque::(_1) -> [return: bb24, unwind unreachable]; ++ _56 = opaque::(copy _1) -> [return: bb24, unwind unreachable]; } bb24: { @@ -363,7 +363,7 @@ StorageLive(_59); StorageLive(_60); StorageLive(_61); - _61 = _1; + _61 = copy _1; - _60 = BitOr(move _61, const core::num::::MAX); + _60 = const u64::MAX; StorageDead(_61); @@ -377,12 +377,12 @@ StorageLive(_62); StorageLive(_63); StorageLive(_64); - _64 = _1; + _64 = copy _1; - _63 = BitXor(move _64, const 0_u64); -+ _63 = _1; ++ _63 = copy _1; StorageDead(_64); - _62 = opaque::(move _63) -> [return: bb26, unwind unreachable]; -+ _62 = opaque::(_1) -> [return: bb26, unwind unreachable]; ++ _62 = opaque::(copy _1) -> [return: bb26, unwind unreachable]; } bb26: { @@ -391,9 +391,9 @@ StorageLive(_65); StorageLive(_66); StorageLive(_67); - _67 = _1; + _67 = copy _1; StorageLive(_68); - _68 = _1; + _68 = copy _1; - _66 = BitXor(move _67, move _68); + _66 = const 0_u64; StorageDead(_68); @@ -408,12 +408,12 @@ StorageLive(_69); StorageLive(_70); StorageLive(_71); - _71 = _1; + _71 = copy _1; - _70 = Shr(move _71, const 0_i32); -+ _70 = _1; ++ _70 = copy _1; StorageDead(_71); - _69 = opaque::(move _70) -> [return: bb28, unwind unreachable]; -+ _69 = opaque::(_1) -> [return: bb28, unwind unreachable]; ++ _69 = opaque::(copy _1) -> [return: bb28, unwind unreachable]; } bb28: { @@ -422,12 +422,12 @@ StorageLive(_72); StorageLive(_73); StorageLive(_74); - _74 = _1; + _74 = copy _1; - _73 = Shl(move _74, const 0_i32); -+ _73 = _1; ++ _73 = copy _1; StorageDead(_74); - _72 = opaque::(move _73) -> [return: bb29, unwind unreachable]; -+ _72 = opaque::(_1) -> [return: bb29, unwind unreachable]; ++ _72 = opaque::(copy _1) -> [return: bb29, unwind unreachable]; } bb29: { diff --git a/tests/mir-opt/gvn.arithmetic.GVN.panic-unwind.diff b/tests/mir-opt/gvn.arithmetic.GVN.panic-unwind.diff index fa7536efc8e..b8e4967fe8b 100644 --- a/tests/mir-opt/gvn.arithmetic.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.arithmetic.GVN.panic-unwind.diff @@ -82,12 +82,12 @@ StorageLive(_2); StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; - _3 = Add(move _4, const 0_u64); -+ _3 = _1; ++ _3 = copy _1; StorageDead(_4); - _2 = opaque::(move _3) -> [return: bb1, unwind continue]; -+ _2 = opaque::(_1) -> [return: bb1, unwind continue]; ++ _2 = opaque::(copy _1) -> [return: bb1, unwind continue]; } bb1: { @@ -96,12 +96,12 @@ StorageLive(_5); StorageLive(_6); StorageLive(_7); - _7 = _1; + _7 = copy _1; - _6 = Sub(move _7, const 0_u64); -+ _6 = _1; ++ _6 = copy _1; StorageDead(_7); - _5 = opaque::(move _6) -> [return: bb2, unwind continue]; -+ _5 = opaque::(_1) -> [return: bb2, unwind continue]; ++ _5 = opaque::(copy _1) -> [return: bb2, unwind continue]; } bb2: { @@ -111,9 +111,9 @@ - StorageLive(_9); + nop; StorageLive(_10); - _10 = _1; + _10 = copy _1; StorageLive(_11); - _11 = _1; + _11 = copy _1; - _9 = Sub(move _10, move _11); + _9 = const 0_u64; StorageDead(_11); @@ -129,7 +129,7 @@ StorageLive(_12); StorageLive(_13); StorageLive(_14); - _14 = _1; + _14 = copy _1; - _13 = Mul(move _14, const 0_u64); + _13 = const 0_u64; StorageDead(_14); @@ -143,12 +143,12 @@ StorageLive(_15); StorageLive(_16); StorageLive(_17); - _17 = _1; + _17 = copy _1; - _16 = Mul(move _17, const 1_u64); -+ _16 = _1; ++ _16 = copy _1; StorageDead(_17); - _15 = opaque::(move _16) -> [return: bb5, unwind continue]; -+ _15 = opaque::(_1) -> [return: bb5, unwind continue]; ++ _15 = opaque::(copy _1) -> [return: bb5, unwind continue]; } bb5: { @@ -157,16 +157,16 @@ StorageLive(_18); StorageLive(_19); StorageLive(_20); - _20 = _1; + _20 = copy _1; - _21 = Eq(const 0_u64, const 0_u64); -- assert(!move _21, "attempt to divide `{}` by zero", _20) -> [success: bb6, unwind continue]; +- assert(!move _21, "attempt to divide `{}` by zero", copy _20) -> [success: bb6, unwind continue]; + _21 = const true; -+ assert(!const true, "attempt to divide `{}` by zero", _1) -> [success: bb6, unwind continue]; ++ assert(!const true, "attempt to divide `{}` by zero", copy _1) -> [success: bb6, unwind continue]; } bb6: { - _19 = Div(move _20, const 0_u64); -+ _19 = Div(_1, const 0_u64); ++ _19 = Div(copy _1, const 0_u64); StorageDead(_20); _18 = opaque::(move _19) -> [return: bb7, unwind continue]; } @@ -177,19 +177,19 @@ StorageLive(_22); StorageLive(_23); StorageLive(_24); - _24 = _1; + _24 = copy _1; - _25 = Eq(const 1_u64, const 0_u64); -- assert(!move _25, "attempt to divide `{}` by zero", _24) -> [success: bb8, unwind continue]; +- assert(!move _25, "attempt to divide `{}` by zero", copy _24) -> [success: bb8, unwind continue]; + _25 = const false; -+ assert(!const false, "attempt to divide `{}` by zero", _1) -> [success: bb8, unwind continue]; ++ assert(!const false, "attempt to divide `{}` by zero", copy _1) -> [success: bb8, unwind continue]; } bb8: { - _23 = Div(move _24, const 1_u64); -+ _23 = _1; ++ _23 = copy _1; StorageDead(_24); - _22 = opaque::(move _23) -> [return: bb9, unwind continue]; -+ _22 = opaque::(_1) -> [return: bb9, unwind continue]; ++ _22 = opaque::(copy _1) -> [return: bb9, unwind continue]; } bb9: { @@ -198,11 +198,11 @@ StorageLive(_26); StorageLive(_27); StorageLive(_28); - _28 = _1; -- _29 = Eq(_28, const 0_u64); + _28 = copy _1; +- _29 = Eq(copy _28, const 0_u64); - assert(!move _29, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb10, unwind continue]; -+ _29 = Eq(_1, const 0_u64); -+ assert(!_29, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb10, unwind continue]; ++ _29 = Eq(copy _1, const 0_u64); ++ assert(!copy _29, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb10, unwind continue]; } bb10: { @@ -219,16 +219,16 @@ StorageLive(_30); StorageLive(_31); StorageLive(_32); - _32 = _1; -- _33 = Eq(_32, const 0_u64); + _32 = copy _1; +- _33 = Eq(copy _32, const 0_u64); - assert(!move _33, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb12, unwind continue]; -+ _33 = _29; -+ assert(!_29, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb12, unwind continue]; ++ _33 = copy _29; ++ assert(!copy _29, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb12, unwind continue]; } bb12: { - _31 = Div(const 1_u64, move _32); -+ _31 = Div(const 1_u64, _1); ++ _31 = Div(const 1_u64, copy _1); StorageDead(_32); _30 = opaque::(move _31) -> [return: bb13, unwind continue]; } @@ -239,16 +239,16 @@ StorageLive(_34); StorageLive(_35); StorageLive(_36); - _36 = _1; + _36 = copy _1; - _37 = Eq(const 0_u64, const 0_u64); -- assert(!move _37, "attempt to calculate the remainder of `{}` with a divisor of zero", _36) -> [success: bb14, unwind continue]; +- assert(!move _37, "attempt to calculate the remainder of `{}` with a divisor of zero", copy _36) -> [success: bb14, unwind continue]; + _37 = const true; -+ assert(!const true, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb14, unwind continue]; ++ assert(!const true, "attempt to calculate the remainder of `{}` with a divisor of zero", copy _1) -> [success: bb14, unwind continue]; } bb14: { - _35 = Rem(move _36, const 0_u64); -+ _35 = Rem(_1, const 0_u64); ++ _35 = Rem(copy _1, const 0_u64); StorageDead(_36); _34 = opaque::(move _35) -> [return: bb15, unwind continue]; } @@ -259,11 +259,11 @@ StorageLive(_38); StorageLive(_39); StorageLive(_40); - _40 = _1; + _40 = copy _1; - _41 = Eq(const 1_u64, const 0_u64); -- assert(!move _41, "attempt to calculate the remainder of `{}` with a divisor of zero", _40) -> [success: bb16, unwind continue]; +- assert(!move _41, "attempt to calculate the remainder of `{}` with a divisor of zero", copy _40) -> [success: bb16, unwind continue]; + _41 = const false; -+ assert(!const false, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb16, unwind continue]; ++ assert(!const false, "attempt to calculate the remainder of `{}` with a divisor of zero", copy _1) -> [success: bb16, unwind continue]; } bb16: { @@ -280,11 +280,11 @@ StorageLive(_42); StorageLive(_43); StorageLive(_44); - _44 = _1; -- _45 = Eq(_44, const 0_u64); + _44 = copy _1; +- _45 = Eq(copy _44, const 0_u64); - assert(!move _45, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb18, unwind continue]; -+ _45 = _29; -+ assert(!_29, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb18, unwind continue]; ++ _45 = copy _29; ++ assert(!copy _29, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb18, unwind continue]; } bb18: { @@ -301,16 +301,16 @@ StorageLive(_46); StorageLive(_47); StorageLive(_48); - _48 = _1; -- _49 = Eq(_48, const 0_u64); + _48 = copy _1; +- _49 = Eq(copy _48, const 0_u64); - assert(!move _49, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb20, unwind continue]; -+ _49 = _29; -+ assert(!_29, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb20, unwind continue]; ++ _49 = copy _29; ++ assert(!copy _29, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb20, unwind continue]; } bb20: { - _47 = Rem(const 1_u64, move _48); -+ _47 = Rem(const 1_u64, _1); ++ _47 = Rem(const 1_u64, copy _1); StorageDead(_48); _46 = opaque::(move _47) -> [return: bb21, unwind continue]; } @@ -321,7 +321,7 @@ StorageLive(_50); StorageLive(_51); StorageLive(_52); - _52 = _1; + _52 = copy _1; - _51 = BitAnd(move _52, const 0_u64); + _51 = const 0_u64; StorageDead(_52); @@ -335,12 +335,12 @@ StorageLive(_53); StorageLive(_54); StorageLive(_55); - _55 = _1; + _55 = copy _1; - _54 = BitAnd(move _55, const core::num::::MAX); -+ _54 = _1; ++ _54 = copy _1; StorageDead(_55); - _53 = opaque::(move _54) -> [return: bb23, unwind continue]; -+ _53 = opaque::(_1) -> [return: bb23, unwind continue]; ++ _53 = opaque::(copy _1) -> [return: bb23, unwind continue]; } bb23: { @@ -349,12 +349,12 @@ StorageLive(_56); StorageLive(_57); StorageLive(_58); - _58 = _1; + _58 = copy _1; - _57 = BitOr(move _58, const 0_u64); -+ _57 = _1; ++ _57 = copy _1; StorageDead(_58); - _56 = opaque::(move _57) -> [return: bb24, unwind continue]; -+ _56 = opaque::(_1) -> [return: bb24, unwind continue]; ++ _56 = opaque::(copy _1) -> [return: bb24, unwind continue]; } bb24: { @@ -363,7 +363,7 @@ StorageLive(_59); StorageLive(_60); StorageLive(_61); - _61 = _1; + _61 = copy _1; - _60 = BitOr(move _61, const core::num::::MAX); + _60 = const u64::MAX; StorageDead(_61); @@ -377,12 +377,12 @@ StorageLive(_62); StorageLive(_63); StorageLive(_64); - _64 = _1; + _64 = copy _1; - _63 = BitXor(move _64, const 0_u64); -+ _63 = _1; ++ _63 = copy _1; StorageDead(_64); - _62 = opaque::(move _63) -> [return: bb26, unwind continue]; -+ _62 = opaque::(_1) -> [return: bb26, unwind continue]; ++ _62 = opaque::(copy _1) -> [return: bb26, unwind continue]; } bb26: { @@ -391,9 +391,9 @@ StorageLive(_65); StorageLive(_66); StorageLive(_67); - _67 = _1; + _67 = copy _1; StorageLive(_68); - _68 = _1; + _68 = copy _1; - _66 = BitXor(move _67, move _68); + _66 = const 0_u64; StorageDead(_68); @@ -408,12 +408,12 @@ StorageLive(_69); StorageLive(_70); StorageLive(_71); - _71 = _1; + _71 = copy _1; - _70 = Shr(move _71, const 0_i32); -+ _70 = _1; ++ _70 = copy _1; StorageDead(_71); - _69 = opaque::(move _70) -> [return: bb28, unwind continue]; -+ _69 = opaque::(_1) -> [return: bb28, unwind continue]; ++ _69 = opaque::(copy _1) -> [return: bb28, unwind continue]; } bb28: { @@ -422,12 +422,12 @@ StorageLive(_72); StorageLive(_73); StorageLive(_74); - _74 = _1; + _74 = copy _1; - _73 = Shl(move _74, const 0_i32); -+ _73 = _1; ++ _73 = copy _1; StorageDead(_74); - _72 = opaque::(move _73) -> [return: bb29, unwind continue]; -+ _72 = opaque::(_1) -> [return: bb29, unwind continue]; ++ _72 = opaque::(copy _1) -> [return: bb29, unwind continue]; } bb29: { diff --git a/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-abort.diff b/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-abort.diff index 0e3f2459fae..acf8bfc71be 100644 --- a/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-abort.diff @@ -30,19 +30,19 @@ StorageLive(_2); StorageLive(_3); StorageLive(_4); - _4 = _1; -- _5 = AddWithOverflow(_4, const 0_u64); + _4 = copy _1; +- _5 = AddWithOverflow(copy _4, const 0_u64); - assert(!move (_5.1: bool), "attempt to compute `{} + {}`, which would overflow", move _4, const 0_u64) -> [success: bb1, unwind unreachable]; -+ _5 = AddWithOverflow(_1, const 0_u64); -+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", _1, const 0_u64) -> [success: bb1, unwind unreachable]; ++ _5 = AddWithOverflow(copy _1, const 0_u64); ++ assert(!const false, "attempt to compute `{} + {}`, which would overflow", copy _1, const 0_u64) -> [success: bb1, unwind unreachable]; } bb1: { - _3 = move (_5.0: u64); -+ _3 = _1; ++ _3 = copy _1; StorageDead(_4); - _2 = opaque::(move _3) -> [return: bb2, unwind unreachable]; -+ _2 = opaque::(_1) -> [return: bb2, unwind unreachable]; ++ _2 = opaque::(copy _1) -> [return: bb2, unwind unreachable]; } bb2: { @@ -51,19 +51,19 @@ StorageLive(_6); StorageLive(_7); StorageLive(_8); - _8 = _1; -- _9 = SubWithOverflow(_8, const 0_u64); + _8 = copy _1; +- _9 = SubWithOverflow(copy _8, const 0_u64); - assert(!move (_9.1: bool), "attempt to compute `{} - {}`, which would overflow", move _8, const 0_u64) -> [success: bb3, unwind unreachable]; -+ _9 = _5; -+ assert(!const false, "attempt to compute `{} - {}`, which would overflow", _1, const 0_u64) -> [success: bb3, unwind unreachable]; ++ _9 = copy _5; ++ assert(!const false, "attempt to compute `{} - {}`, which would overflow", copy _1, const 0_u64) -> [success: bb3, unwind unreachable]; } bb3: { - _7 = move (_9.0: u64); -+ _7 = _1; ++ _7 = copy _1; StorageDead(_8); - _6 = opaque::(move _7) -> [return: bb4, unwind unreachable]; -+ _6 = opaque::(_1) -> [return: bb4, unwind unreachable]; ++ _6 = opaque::(copy _1) -> [return: bb4, unwind unreachable]; } bb4: { @@ -73,13 +73,13 @@ - StorageLive(_11); + nop; StorageLive(_12); - _12 = _1; + _12 = copy _1; StorageLive(_13); - _13 = _1; -- _14 = SubWithOverflow(_12, _13); + _13 = copy _1; +- _14 = SubWithOverflow(copy _12, copy _13); - assert(!move (_14.1: bool), "attempt to compute `{} - {}`, which would overflow", move _12, move _13) -> [success: bb5, unwind unreachable]; + _14 = const (0_u64, false); -+ assert(!const false, "attempt to compute `{} - {}`, which would overflow", _1, _1) -> [success: bb5, unwind unreachable]; ++ assert(!const false, "attempt to compute `{} - {}`, which would overflow", copy _1, copy _1) -> [success: bb5, unwind unreachable]; } bb5: { @@ -98,11 +98,11 @@ StorageLive(_15); StorageLive(_16); StorageLive(_17); - _17 = _1; -- _18 = MulWithOverflow(_17, const 0_u64); + _17 = copy _1; +- _18 = MulWithOverflow(copy _17, const 0_u64); - assert(!move (_18.1: bool), "attempt to compute `{} * {}`, which would overflow", move _17, const 0_u64) -> [success: bb7, unwind unreachable]; + _18 = const (0_u64, false); -+ assert(!const false, "attempt to compute `{} * {}`, which would overflow", _1, const 0_u64) -> [success: bb7, unwind unreachable]; ++ assert(!const false, "attempt to compute `{} * {}`, which would overflow", copy _1, const 0_u64) -> [success: bb7, unwind unreachable]; } bb7: { @@ -119,19 +119,19 @@ StorageLive(_19); StorageLive(_20); StorageLive(_21); - _21 = _1; -- _22 = MulWithOverflow(_21, const 1_u64); + _21 = copy _1; +- _22 = MulWithOverflow(copy _21, const 1_u64); - assert(!move (_22.1: bool), "attempt to compute `{} * {}`, which would overflow", move _21, const 1_u64) -> [success: bb9, unwind unreachable]; -+ _22 = _5; -+ assert(!const false, "attempt to compute `{} * {}`, which would overflow", _1, const 1_u64) -> [success: bb9, unwind unreachable]; ++ _22 = copy _5; ++ assert(!const false, "attempt to compute `{} * {}`, which would overflow", copy _1, const 1_u64) -> [success: bb9, unwind unreachable]; } bb9: { - _20 = move (_22.0: u64); -+ _20 = _1; ++ _20 = copy _1; StorageDead(_21); - _19 = opaque::(move _20) -> [return: bb10, unwind unreachable]; -+ _19 = opaque::(_1) -> [return: bb10, unwind unreachable]; ++ _19 = opaque::(copy _1) -> [return: bb10, unwind unreachable]; } bb10: { diff --git a/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-unwind.diff b/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-unwind.diff index 2873d7ef0ab..f3f6b381a81 100644 --- a/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-unwind.diff @@ -30,19 +30,19 @@ StorageLive(_2); StorageLive(_3); StorageLive(_4); - _4 = _1; -- _5 = AddWithOverflow(_4, const 0_u64); + _4 = copy _1; +- _5 = AddWithOverflow(copy _4, const 0_u64); - assert(!move (_5.1: bool), "attempt to compute `{} + {}`, which would overflow", move _4, const 0_u64) -> [success: bb1, unwind continue]; -+ _5 = AddWithOverflow(_1, const 0_u64); -+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", _1, const 0_u64) -> [success: bb1, unwind continue]; ++ _5 = AddWithOverflow(copy _1, const 0_u64); ++ assert(!const false, "attempt to compute `{} + {}`, which would overflow", copy _1, const 0_u64) -> [success: bb1, unwind continue]; } bb1: { - _3 = move (_5.0: u64); -+ _3 = _1; ++ _3 = copy _1; StorageDead(_4); - _2 = opaque::(move _3) -> [return: bb2, unwind continue]; -+ _2 = opaque::(_1) -> [return: bb2, unwind continue]; ++ _2 = opaque::(copy _1) -> [return: bb2, unwind continue]; } bb2: { @@ -51,19 +51,19 @@ StorageLive(_6); StorageLive(_7); StorageLive(_8); - _8 = _1; -- _9 = SubWithOverflow(_8, const 0_u64); + _8 = copy _1; +- _9 = SubWithOverflow(copy _8, const 0_u64); - assert(!move (_9.1: bool), "attempt to compute `{} - {}`, which would overflow", move _8, const 0_u64) -> [success: bb3, unwind continue]; -+ _9 = _5; -+ assert(!const false, "attempt to compute `{} - {}`, which would overflow", _1, const 0_u64) -> [success: bb3, unwind continue]; ++ _9 = copy _5; ++ assert(!const false, "attempt to compute `{} - {}`, which would overflow", copy _1, const 0_u64) -> [success: bb3, unwind continue]; } bb3: { - _7 = move (_9.0: u64); -+ _7 = _1; ++ _7 = copy _1; StorageDead(_8); - _6 = opaque::(move _7) -> [return: bb4, unwind continue]; -+ _6 = opaque::(_1) -> [return: bb4, unwind continue]; ++ _6 = opaque::(copy _1) -> [return: bb4, unwind continue]; } bb4: { @@ -73,13 +73,13 @@ - StorageLive(_11); + nop; StorageLive(_12); - _12 = _1; + _12 = copy _1; StorageLive(_13); - _13 = _1; -- _14 = SubWithOverflow(_12, _13); + _13 = copy _1; +- _14 = SubWithOverflow(copy _12, copy _13); - assert(!move (_14.1: bool), "attempt to compute `{} - {}`, which would overflow", move _12, move _13) -> [success: bb5, unwind continue]; + _14 = const (0_u64, false); -+ assert(!const false, "attempt to compute `{} - {}`, which would overflow", _1, _1) -> [success: bb5, unwind continue]; ++ assert(!const false, "attempt to compute `{} - {}`, which would overflow", copy _1, copy _1) -> [success: bb5, unwind continue]; } bb5: { @@ -98,11 +98,11 @@ StorageLive(_15); StorageLive(_16); StorageLive(_17); - _17 = _1; -- _18 = MulWithOverflow(_17, const 0_u64); + _17 = copy _1; +- _18 = MulWithOverflow(copy _17, const 0_u64); - assert(!move (_18.1: bool), "attempt to compute `{} * {}`, which would overflow", move _17, const 0_u64) -> [success: bb7, unwind continue]; + _18 = const (0_u64, false); -+ assert(!const false, "attempt to compute `{} * {}`, which would overflow", _1, const 0_u64) -> [success: bb7, unwind continue]; ++ assert(!const false, "attempt to compute `{} * {}`, which would overflow", copy _1, const 0_u64) -> [success: bb7, unwind continue]; } bb7: { @@ -119,19 +119,19 @@ StorageLive(_19); StorageLive(_20); StorageLive(_21); - _21 = _1; -- _22 = MulWithOverflow(_21, const 1_u64); + _21 = copy _1; +- _22 = MulWithOverflow(copy _21, const 1_u64); - assert(!move (_22.1: bool), "attempt to compute `{} * {}`, which would overflow", move _21, const 1_u64) -> [success: bb9, unwind continue]; -+ _22 = _5; -+ assert(!const false, "attempt to compute `{} * {}`, which would overflow", _1, const 1_u64) -> [success: bb9, unwind continue]; ++ _22 = copy _5; ++ assert(!const false, "attempt to compute `{} * {}`, which would overflow", copy _1, const 1_u64) -> [success: bb9, unwind continue]; } bb9: { - _20 = move (_22.0: u64); -+ _20 = _1; ++ _20 = copy _1; StorageDead(_21); - _19 = opaque::(move _20) -> [return: bb10, unwind continue]; -+ _19 = opaque::(_1) -> [return: bb10, unwind continue]; ++ _19 = opaque::(copy _1) -> [return: bb10, unwind continue]; } bb10: { diff --git a/tests/mir-opt/gvn.arithmetic_float.GVN.panic-abort.diff b/tests/mir-opt/gvn.arithmetic_float.GVN.panic-abort.diff index b332100eaf0..31a85468126 100644 --- a/tests/mir-opt/gvn.arithmetic_float.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.arithmetic_float.GVN.panic-abort.diff @@ -38,9 +38,9 @@ StorageLive(_2); StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; - _3 = Add(move _4, const 0f64); -+ _3 = Add(_1, const 0f64); ++ _3 = Add(copy _1, const 0f64); StorageDead(_4); _2 = opaque::(move _3) -> [return: bb1, unwind unreachable]; } @@ -51,9 +51,9 @@ StorageLive(_5); StorageLive(_6); StorageLive(_7); - _7 = _1; + _7 = copy _1; - _6 = Sub(move _7, const 0f64); -+ _6 = Sub(_1, const 0f64); ++ _6 = Sub(copy _1, const 0f64); StorageDead(_7); _5 = opaque::(move _6) -> [return: bb2, unwind unreachable]; } @@ -64,9 +64,9 @@ StorageLive(_8); StorageLive(_9); StorageLive(_10); - _10 = _1; + _10 = copy _1; - _9 = Mul(move _10, const 0f64); -+ _9 = Mul(_1, const 0f64); ++ _9 = Mul(copy _1, const 0f64); StorageDead(_10); _8 = opaque::(move _9) -> [return: bb3, unwind unreachable]; } @@ -77,9 +77,9 @@ StorageLive(_11); StorageLive(_12); StorageLive(_13); - _13 = _1; + _13 = copy _1; - _12 = Div(move _13, const 0f64); -+ _12 = Div(_1, const 0f64); ++ _12 = Div(copy _1, const 0f64); StorageDead(_13); _11 = opaque::(move _12) -> [return: bb4, unwind unreachable]; } @@ -90,9 +90,9 @@ StorageLive(_14); StorageLive(_15); StorageLive(_16); - _16 = _1; + _16 = copy _1; - _15 = Div(const 0f64, move _16); -+ _15 = Div(const 0f64, _1); ++ _15 = Div(const 0f64, copy _1); StorageDead(_16); _14 = opaque::(move _15) -> [return: bb5, unwind unreachable]; } @@ -103,9 +103,9 @@ StorageLive(_17); StorageLive(_18); StorageLive(_19); - _19 = _1; + _19 = copy _1; - _18 = Rem(move _19, const 0f64); -+ _18 = Rem(_1, const 0f64); ++ _18 = Rem(copy _1, const 0f64); StorageDead(_19); _17 = opaque::(move _18) -> [return: bb6, unwind unreachable]; } @@ -116,9 +116,9 @@ StorageLive(_20); StorageLive(_21); StorageLive(_22); - _22 = _1; + _22 = copy _1; - _21 = Rem(const 0f64, move _22); -+ _21 = Rem(const 0f64, _1); ++ _21 = Rem(const 0f64, copy _1); StorageDead(_22); _20 = opaque::(move _21) -> [return: bb7, unwind unreachable]; } @@ -129,11 +129,11 @@ StorageLive(_23); StorageLive(_24); StorageLive(_25); - _25 = _1; + _25 = copy _1; StorageLive(_26); - _26 = _1; + _26 = copy _1; - _24 = Eq(move _25, move _26); -+ _24 = Eq(_1, _1); ++ _24 = Eq(copy _1, copy _1); StorageDead(_26); StorageDead(_25); _23 = opaque::(move _24) -> [return: bb8, unwind unreachable]; @@ -145,11 +145,11 @@ StorageLive(_27); StorageLive(_28); StorageLive(_29); - _29 = _1; + _29 = copy _1; StorageLive(_30); - _30 = _1; + _30 = copy _1; - _28 = Ne(move _29, move _30); -+ _28 = Ne(_1, _1); ++ _28 = Ne(copy _1, copy _1); StorageDead(_30); StorageDead(_29); _27 = opaque::(move _28) -> [return: bb9, unwind unreachable]; diff --git a/tests/mir-opt/gvn.arithmetic_float.GVN.panic-unwind.diff b/tests/mir-opt/gvn.arithmetic_float.GVN.panic-unwind.diff index 28664cb0ac8..4e42b1af4fc 100644 --- a/tests/mir-opt/gvn.arithmetic_float.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.arithmetic_float.GVN.panic-unwind.diff @@ -38,9 +38,9 @@ StorageLive(_2); StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; - _3 = Add(move _4, const 0f64); -+ _3 = Add(_1, const 0f64); ++ _3 = Add(copy _1, const 0f64); StorageDead(_4); _2 = opaque::(move _3) -> [return: bb1, unwind continue]; } @@ -51,9 +51,9 @@ StorageLive(_5); StorageLive(_6); StorageLive(_7); - _7 = _1; + _7 = copy _1; - _6 = Sub(move _7, const 0f64); -+ _6 = Sub(_1, const 0f64); ++ _6 = Sub(copy _1, const 0f64); StorageDead(_7); _5 = opaque::(move _6) -> [return: bb2, unwind continue]; } @@ -64,9 +64,9 @@ StorageLive(_8); StorageLive(_9); StorageLive(_10); - _10 = _1; + _10 = copy _1; - _9 = Mul(move _10, const 0f64); -+ _9 = Mul(_1, const 0f64); ++ _9 = Mul(copy _1, const 0f64); StorageDead(_10); _8 = opaque::(move _9) -> [return: bb3, unwind continue]; } @@ -77,9 +77,9 @@ StorageLive(_11); StorageLive(_12); StorageLive(_13); - _13 = _1; + _13 = copy _1; - _12 = Div(move _13, const 0f64); -+ _12 = Div(_1, const 0f64); ++ _12 = Div(copy _1, const 0f64); StorageDead(_13); _11 = opaque::(move _12) -> [return: bb4, unwind continue]; } @@ -90,9 +90,9 @@ StorageLive(_14); StorageLive(_15); StorageLive(_16); - _16 = _1; + _16 = copy _1; - _15 = Div(const 0f64, move _16); -+ _15 = Div(const 0f64, _1); ++ _15 = Div(const 0f64, copy _1); StorageDead(_16); _14 = opaque::(move _15) -> [return: bb5, unwind continue]; } @@ -103,9 +103,9 @@ StorageLive(_17); StorageLive(_18); StorageLive(_19); - _19 = _1; + _19 = copy _1; - _18 = Rem(move _19, const 0f64); -+ _18 = Rem(_1, const 0f64); ++ _18 = Rem(copy _1, const 0f64); StorageDead(_19); _17 = opaque::(move _18) -> [return: bb6, unwind continue]; } @@ -116,9 +116,9 @@ StorageLive(_20); StorageLive(_21); StorageLive(_22); - _22 = _1; + _22 = copy _1; - _21 = Rem(const 0f64, move _22); -+ _21 = Rem(const 0f64, _1); ++ _21 = Rem(const 0f64, copy _1); StorageDead(_22); _20 = opaque::(move _21) -> [return: bb7, unwind continue]; } @@ -129,11 +129,11 @@ StorageLive(_23); StorageLive(_24); StorageLive(_25); - _25 = _1; + _25 = copy _1; StorageLive(_26); - _26 = _1; + _26 = copy _1; - _24 = Eq(move _25, move _26); -+ _24 = Eq(_1, _1); ++ _24 = Eq(copy _1, copy _1); StorageDead(_26); StorageDead(_25); _23 = opaque::(move _24) -> [return: bb8, unwind continue]; @@ -145,11 +145,11 @@ StorageLive(_27); StorageLive(_28); StorageLive(_29); - _29 = _1; + _29 = copy _1; StorageLive(_30); - _30 = _1; + _30 = copy _1; - _28 = Ne(move _29, move _30); -+ _28 = Ne(_1, _1); ++ _28 = Ne(copy _1, copy _1); StorageDead(_30); StorageDead(_29); _27 = opaque::(move _28) -> [return: bb9, unwind continue]; diff --git a/tests/mir-opt/gvn.borrowed.GVN.panic-abort.diff b/tests/mir-opt/gvn.borrowed.GVN.panic-abort.diff index 9520bd382ee..b0702696e18 100644 --- a/tests/mir-opt/gvn.borrowed.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.borrowed.GVN.panic-abort.diff @@ -7,19 +7,19 @@ let mut _3: &T; bb0: { - _2 = _1; + _2 = copy _1; _3 = &_1; - _0 = opaque::<&T>(_3) -> [return: bb1, unwind unreachable]; + _0 = opaque::<&T>(copy _3) -> [return: bb1, unwind unreachable]; } bb1: { -- _0 = opaque::(_2) -> [return: bb2, unwind unreachable]; -+ _0 = opaque::(_1) -> [return: bb2, unwind unreachable]; +- _0 = opaque::(copy _2) -> [return: bb2, unwind unreachable]; ++ _0 = opaque::(copy _1) -> [return: bb2, unwind unreachable]; } bb2: { -- _0 = opaque::((*_3)) -> [return: bb3, unwind unreachable]; -+ _0 = opaque::(_1) -> [return: bb3, unwind unreachable]; +- _0 = opaque::(copy (*_3)) -> [return: bb3, unwind unreachable]; ++ _0 = opaque::(copy _1) -> [return: bb3, unwind unreachable]; } bb3: { diff --git a/tests/mir-opt/gvn.borrowed.GVN.panic-unwind.diff b/tests/mir-opt/gvn.borrowed.GVN.panic-unwind.diff index 4f5d76d5644..fe05d4deeed 100644 --- a/tests/mir-opt/gvn.borrowed.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.borrowed.GVN.panic-unwind.diff @@ -7,19 +7,19 @@ let mut _3: &T; bb0: { - _2 = _1; + _2 = copy _1; _3 = &_1; - _0 = opaque::<&T>(_3) -> [return: bb1, unwind continue]; + _0 = opaque::<&T>(copy _3) -> [return: bb1, unwind continue]; } bb1: { -- _0 = opaque::(_2) -> [return: bb2, unwind continue]; -+ _0 = opaque::(_1) -> [return: bb2, unwind continue]; +- _0 = opaque::(copy _2) -> [return: bb2, unwind continue]; ++ _0 = opaque::(copy _1) -> [return: bb2, unwind continue]; } bb2: { -- _0 = opaque::((*_3)) -> [return: bb3, unwind continue]; -+ _0 = opaque::(_1) -> [return: bb3, unwind continue]; +- _0 = opaque::(copy (*_3)) -> [return: bb3, unwind continue]; ++ _0 = opaque::(copy _1) -> [return: bb3, unwind continue]; } bb3: { diff --git a/tests/mir-opt/gvn.cast.GVN.panic-abort.diff b/tests/mir-opt/gvn.cast.GVN.panic-abort.diff index d43198c9911..1d523d22ca6 100644 --- a/tests/mir-opt/gvn.cast.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.cast.GVN.panic-abort.diff @@ -116,7 +116,7 @@ StorageLive(_4); StorageLive(_5); StorageLive(_6); -- _6 = _1; +- _6 = copy _1; - _5 = move _6 as u8 (IntToInt); + _6 = const 1_i64; + _5 = const 1_u8; @@ -131,7 +131,7 @@ StorageLive(_7); StorageLive(_8); StorageLive(_9); -- _9 = _1; +- _9 = copy _1; - _8 = move _9 as u16 (IntToInt); + _9 = const 1_i64; + _8 = const 1_u16; @@ -146,7 +146,7 @@ StorageLive(_10); StorageLive(_11); StorageLive(_12); -- _12 = _1; +- _12 = copy _1; - _11 = move _12 as u32 (IntToInt); + _12 = const 1_i64; + _11 = const 1_u32; @@ -161,7 +161,7 @@ StorageLive(_13); StorageLive(_14); StorageLive(_15); -- _15 = _1; +- _15 = copy _1; - _14 = move _15 as u64 (IntToInt); + _15 = const 1_i64; + _14 = const 1_u64; @@ -176,7 +176,7 @@ StorageLive(_16); StorageLive(_17); StorageLive(_18); -- _18 = _1; +- _18 = copy _1; - _17 = move _18 as i8 (IntToInt); + _18 = const 1_i64; + _17 = const 1_i8; @@ -191,7 +191,7 @@ StorageLive(_19); StorageLive(_20); StorageLive(_21); -- _21 = _1; +- _21 = copy _1; - _20 = move _21 as i16 (IntToInt); + _21 = const 1_i64; + _20 = const 1_i16; @@ -206,7 +206,7 @@ StorageLive(_22); StorageLive(_23); StorageLive(_24); -- _24 = _1; +- _24 = copy _1; - _23 = move _24 as i32 (IntToInt); + _24 = const 1_i64; + _23 = const 1_i32; @@ -220,7 +220,7 @@ StorageDead(_22); StorageLive(_25); StorageLive(_26); -- _26 = _1; +- _26 = copy _1; - _25 = opaque::(move _26) -> [return: bb8, unwind unreachable]; + _26 = const 1_i64; + _25 = opaque::(const 1_i64) -> [return: bb8, unwind unreachable]; @@ -232,7 +232,7 @@ StorageLive(_27); StorageLive(_28); StorageLive(_29); -- _29 = _1; +- _29 = copy _1; - _28 = move _29 as f32 (IntToFloat); + _29 = const 1_i64; + _28 = const 1f32; @@ -247,7 +247,7 @@ StorageLive(_30); StorageLive(_31); StorageLive(_32); -- _32 = _1; +- _32 = copy _1; - _31 = move _32 as f64 (IntToFloat); + _32 = const 1_i64; + _31 = const 1f64; @@ -262,7 +262,7 @@ StorageLive(_33); StorageLive(_34); StorageLive(_35); -- _35 = _2; +- _35 = copy _2; - _34 = move _35 as u8 (IntToInt); + _35 = const 1_u64; + _34 = const 1_u8; @@ -277,7 +277,7 @@ StorageLive(_36); StorageLive(_37); StorageLive(_38); -- _38 = _2; +- _38 = copy _2; - _37 = move _38 as u16 (IntToInt); + _38 = const 1_u64; + _37 = const 1_u16; @@ -292,7 +292,7 @@ StorageLive(_39); StorageLive(_40); StorageLive(_41); -- _41 = _2; +- _41 = copy _2; - _40 = move _41 as u32 (IntToInt); + _41 = const 1_u64; + _40 = const 1_u32; @@ -306,7 +306,7 @@ StorageDead(_39); StorageLive(_42); StorageLive(_43); -- _43 = _2; +- _43 = copy _2; - _42 = opaque::(move _43) -> [return: bb14, unwind unreachable]; + _43 = const 1_u64; + _42 = opaque::(const 1_u64) -> [return: bb14, unwind unreachable]; @@ -318,7 +318,7 @@ StorageLive(_44); StorageLive(_45); StorageLive(_46); -- _46 = _2; +- _46 = copy _2; - _45 = move _46 as i8 (IntToInt); + _46 = const 1_u64; + _45 = const 1_i8; @@ -333,7 +333,7 @@ StorageLive(_47); StorageLive(_48); StorageLive(_49); -- _49 = _2; +- _49 = copy _2; - _48 = move _49 as i16 (IntToInt); + _49 = const 1_u64; + _48 = const 1_i16; @@ -348,7 +348,7 @@ StorageLive(_50); StorageLive(_51); StorageLive(_52); -- _52 = _2; +- _52 = copy _2; - _51 = move _52 as i32 (IntToInt); + _52 = const 1_u64; + _51 = const 1_i32; @@ -363,7 +363,7 @@ StorageLive(_53); StorageLive(_54); StorageLive(_55); -- _55 = _2; +- _55 = copy _2; - _54 = move _55 as i64 (IntToInt); + _55 = const 1_u64; + _54 = const 1_i64; @@ -378,7 +378,7 @@ StorageLive(_56); StorageLive(_57); StorageLive(_58); -- _58 = _2; +- _58 = copy _2; - _57 = move _58 as f32 (IntToFloat); + _58 = const 1_u64; + _57 = const 1f32; @@ -393,7 +393,7 @@ StorageLive(_59); StorageLive(_60); StorageLive(_61); -- _61 = _2; +- _61 = copy _2; - _60 = move _61 as f64 (IntToFloat); + _61 = const 1_u64; + _60 = const 1f64; @@ -408,7 +408,7 @@ StorageLive(_62); StorageLive(_63); StorageLive(_64); -- _64 = _3; +- _64 = copy _3; - _63 = move _64 as u8 (FloatToInt); + _64 = const 1f64; + _63 = const 1_u8; @@ -423,7 +423,7 @@ StorageLive(_65); StorageLive(_66); StorageLive(_67); -- _67 = _3; +- _67 = copy _3; - _66 = move _67 as u16 (FloatToInt); + _67 = const 1f64; + _66 = const 1_u16; @@ -438,7 +438,7 @@ StorageLive(_68); StorageLive(_69); StorageLive(_70); -- _70 = _3; +- _70 = copy _3; - _69 = move _70 as u32 (FloatToInt); + _70 = const 1f64; + _69 = const 1_u32; @@ -453,7 +453,7 @@ StorageLive(_71); StorageLive(_72); StorageLive(_73); -- _73 = _3; +- _73 = copy _3; - _72 = move _73 as u64 (FloatToInt); + _73 = const 1f64; + _72 = const 1_u64; @@ -468,7 +468,7 @@ StorageLive(_74); StorageLive(_75); StorageLive(_76); -- _76 = _3; +- _76 = copy _3; - _75 = move _76 as i8 (FloatToInt); + _76 = const 1f64; + _75 = const 1_i8; @@ -483,7 +483,7 @@ StorageLive(_77); StorageLive(_78); StorageLive(_79); -- _79 = _3; +- _79 = copy _3; - _78 = move _79 as i16 (FloatToInt); + _79 = const 1f64; + _78 = const 1_i16; @@ -498,7 +498,7 @@ StorageLive(_80); StorageLive(_81); StorageLive(_82); -- _82 = _3; +- _82 = copy _3; - _81 = move _82 as i32 (FloatToInt); + _82 = const 1f64; + _81 = const 1_i32; @@ -513,7 +513,7 @@ StorageLive(_83); StorageLive(_84); StorageLive(_85); -- _85 = _3; +- _85 = copy _3; - _84 = move _85 as i64 (FloatToInt); + _85 = const 1f64; + _84 = const 1_i64; @@ -528,7 +528,7 @@ StorageLive(_86); StorageLive(_87); StorageLive(_88); -- _88 = _3; +- _88 = copy _3; - _87 = move _88 as f32 (FloatToFloat); + _88 = const 1f64; + _87 = const 1f32; @@ -542,7 +542,7 @@ StorageDead(_86); StorageLive(_89); StorageLive(_90); -- _90 = _3; +- _90 = copy _3; - _89 = opaque::(move _90) -> [return: bb30, unwind unreachable]; + _90 = const 1f64; + _89 = opaque::(const 1f64) -> [return: bb30, unwind unreachable]; diff --git a/tests/mir-opt/gvn.cast.GVN.panic-unwind.diff b/tests/mir-opt/gvn.cast.GVN.panic-unwind.diff index 08b97e13aa0..3541c10da64 100644 --- a/tests/mir-opt/gvn.cast.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.cast.GVN.panic-unwind.diff @@ -116,7 +116,7 @@ StorageLive(_4); StorageLive(_5); StorageLive(_6); -- _6 = _1; +- _6 = copy _1; - _5 = move _6 as u8 (IntToInt); + _6 = const 1_i64; + _5 = const 1_u8; @@ -131,7 +131,7 @@ StorageLive(_7); StorageLive(_8); StorageLive(_9); -- _9 = _1; +- _9 = copy _1; - _8 = move _9 as u16 (IntToInt); + _9 = const 1_i64; + _8 = const 1_u16; @@ -146,7 +146,7 @@ StorageLive(_10); StorageLive(_11); StorageLive(_12); -- _12 = _1; +- _12 = copy _1; - _11 = move _12 as u32 (IntToInt); + _12 = const 1_i64; + _11 = const 1_u32; @@ -161,7 +161,7 @@ StorageLive(_13); StorageLive(_14); StorageLive(_15); -- _15 = _1; +- _15 = copy _1; - _14 = move _15 as u64 (IntToInt); + _15 = const 1_i64; + _14 = const 1_u64; @@ -176,7 +176,7 @@ StorageLive(_16); StorageLive(_17); StorageLive(_18); -- _18 = _1; +- _18 = copy _1; - _17 = move _18 as i8 (IntToInt); + _18 = const 1_i64; + _17 = const 1_i8; @@ -191,7 +191,7 @@ StorageLive(_19); StorageLive(_20); StorageLive(_21); -- _21 = _1; +- _21 = copy _1; - _20 = move _21 as i16 (IntToInt); + _21 = const 1_i64; + _20 = const 1_i16; @@ -206,7 +206,7 @@ StorageLive(_22); StorageLive(_23); StorageLive(_24); -- _24 = _1; +- _24 = copy _1; - _23 = move _24 as i32 (IntToInt); + _24 = const 1_i64; + _23 = const 1_i32; @@ -220,7 +220,7 @@ StorageDead(_22); StorageLive(_25); StorageLive(_26); -- _26 = _1; +- _26 = copy _1; - _25 = opaque::(move _26) -> [return: bb8, unwind continue]; + _26 = const 1_i64; + _25 = opaque::(const 1_i64) -> [return: bb8, unwind continue]; @@ -232,7 +232,7 @@ StorageLive(_27); StorageLive(_28); StorageLive(_29); -- _29 = _1; +- _29 = copy _1; - _28 = move _29 as f32 (IntToFloat); + _29 = const 1_i64; + _28 = const 1f32; @@ -247,7 +247,7 @@ StorageLive(_30); StorageLive(_31); StorageLive(_32); -- _32 = _1; +- _32 = copy _1; - _31 = move _32 as f64 (IntToFloat); + _32 = const 1_i64; + _31 = const 1f64; @@ -262,7 +262,7 @@ StorageLive(_33); StorageLive(_34); StorageLive(_35); -- _35 = _2; +- _35 = copy _2; - _34 = move _35 as u8 (IntToInt); + _35 = const 1_u64; + _34 = const 1_u8; @@ -277,7 +277,7 @@ StorageLive(_36); StorageLive(_37); StorageLive(_38); -- _38 = _2; +- _38 = copy _2; - _37 = move _38 as u16 (IntToInt); + _38 = const 1_u64; + _37 = const 1_u16; @@ -292,7 +292,7 @@ StorageLive(_39); StorageLive(_40); StorageLive(_41); -- _41 = _2; +- _41 = copy _2; - _40 = move _41 as u32 (IntToInt); + _41 = const 1_u64; + _40 = const 1_u32; @@ -306,7 +306,7 @@ StorageDead(_39); StorageLive(_42); StorageLive(_43); -- _43 = _2; +- _43 = copy _2; - _42 = opaque::(move _43) -> [return: bb14, unwind continue]; + _43 = const 1_u64; + _42 = opaque::(const 1_u64) -> [return: bb14, unwind continue]; @@ -318,7 +318,7 @@ StorageLive(_44); StorageLive(_45); StorageLive(_46); -- _46 = _2; +- _46 = copy _2; - _45 = move _46 as i8 (IntToInt); + _46 = const 1_u64; + _45 = const 1_i8; @@ -333,7 +333,7 @@ StorageLive(_47); StorageLive(_48); StorageLive(_49); -- _49 = _2; +- _49 = copy _2; - _48 = move _49 as i16 (IntToInt); + _49 = const 1_u64; + _48 = const 1_i16; @@ -348,7 +348,7 @@ StorageLive(_50); StorageLive(_51); StorageLive(_52); -- _52 = _2; +- _52 = copy _2; - _51 = move _52 as i32 (IntToInt); + _52 = const 1_u64; + _51 = const 1_i32; @@ -363,7 +363,7 @@ StorageLive(_53); StorageLive(_54); StorageLive(_55); -- _55 = _2; +- _55 = copy _2; - _54 = move _55 as i64 (IntToInt); + _55 = const 1_u64; + _54 = const 1_i64; @@ -378,7 +378,7 @@ StorageLive(_56); StorageLive(_57); StorageLive(_58); -- _58 = _2; +- _58 = copy _2; - _57 = move _58 as f32 (IntToFloat); + _58 = const 1_u64; + _57 = const 1f32; @@ -393,7 +393,7 @@ StorageLive(_59); StorageLive(_60); StorageLive(_61); -- _61 = _2; +- _61 = copy _2; - _60 = move _61 as f64 (IntToFloat); + _61 = const 1_u64; + _60 = const 1f64; @@ -408,7 +408,7 @@ StorageLive(_62); StorageLive(_63); StorageLive(_64); -- _64 = _3; +- _64 = copy _3; - _63 = move _64 as u8 (FloatToInt); + _64 = const 1f64; + _63 = const 1_u8; @@ -423,7 +423,7 @@ StorageLive(_65); StorageLive(_66); StorageLive(_67); -- _67 = _3; +- _67 = copy _3; - _66 = move _67 as u16 (FloatToInt); + _67 = const 1f64; + _66 = const 1_u16; @@ -438,7 +438,7 @@ StorageLive(_68); StorageLive(_69); StorageLive(_70); -- _70 = _3; +- _70 = copy _3; - _69 = move _70 as u32 (FloatToInt); + _70 = const 1f64; + _69 = const 1_u32; @@ -453,7 +453,7 @@ StorageLive(_71); StorageLive(_72); StorageLive(_73); -- _73 = _3; +- _73 = copy _3; - _72 = move _73 as u64 (FloatToInt); + _73 = const 1f64; + _72 = const 1_u64; @@ -468,7 +468,7 @@ StorageLive(_74); StorageLive(_75); StorageLive(_76); -- _76 = _3; +- _76 = copy _3; - _75 = move _76 as i8 (FloatToInt); + _76 = const 1f64; + _75 = const 1_i8; @@ -483,7 +483,7 @@ StorageLive(_77); StorageLive(_78); StorageLive(_79); -- _79 = _3; +- _79 = copy _3; - _78 = move _79 as i16 (FloatToInt); + _79 = const 1f64; + _78 = const 1_i16; @@ -498,7 +498,7 @@ StorageLive(_80); StorageLive(_81); StorageLive(_82); -- _82 = _3; +- _82 = copy _3; - _81 = move _82 as i32 (FloatToInt); + _82 = const 1f64; + _81 = const 1_i32; @@ -513,7 +513,7 @@ StorageLive(_83); StorageLive(_84); StorageLive(_85); -- _85 = _3; +- _85 = copy _3; - _84 = move _85 as i64 (FloatToInt); + _85 = const 1f64; + _84 = const 1_i64; @@ -528,7 +528,7 @@ StorageLive(_86); StorageLive(_87); StorageLive(_88); -- _88 = _3; +- _88 = copy _3; - _87 = move _88 as f32 (FloatToFloat); + _88 = const 1f64; + _87 = const 1f32; @@ -542,7 +542,7 @@ StorageDead(_86); StorageLive(_89); StorageLive(_90); -- _90 = _3; +- _90 = copy _3; - _89 = opaque::(move _90) -> [return: bb30, unwind continue]; + _90 = const 1f64; + _89 = opaque::(const 1f64) -> [return: bb30, unwind continue]; diff --git a/tests/mir-opt/gvn.cast_pointer_eq.GVN.panic-abort.diff b/tests/mir-opt/gvn.cast_pointer_eq.GVN.panic-abort.diff index 757ab959813..f66aed0f441 100644 --- a/tests/mir-opt/gvn.cast_pointer_eq.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.cast_pointer_eq.GVN.panic-abort.diff @@ -52,70 +52,70 @@ - StorageLive(_5); + nop; StorageLive(_6); - _6 = _1; + _6 = copy _1; - _5 = move _6 as *const u32 (PtrToPtr); -+ _5 = _1 as *const u32 (PtrToPtr); ++ _5 = copy _1 as *const u32 (PtrToPtr); StorageDead(_6); StorageLive(_7); - StorageLive(_8); + nop; StorageLive(_9); - _9 = _2; + _9 = copy _2; - _8 = move _9 as *const u32 (PtrToPtr); -+ _8 = _2 as *const u32 (PtrToPtr); ++ _8 = copy _2 as *const u32 (PtrToPtr); StorageDead(_9); - _7 = move _8 as *const u32 (PtrToPtr); - StorageDead(_8); -+ _7 = _8; ++ _7 = copy _8; + nop; StorageLive(_10); - StorageLive(_11); + nop; StorageLive(_12); - _12 = _3; + _12 = copy _3; - _11 = move _12 as *const u32 (PtrToPtr); -+ _11 = _3 as *const u32 (PtrToPtr); ++ _11 = copy _3 as *const u32 (PtrToPtr); StorageDead(_12); - _10 = move _11 as *const u32 (PtrToPtr); - StorageDead(_11); - StorageLive(_13); -+ _10 = _11; ++ _10 = copy _11; + nop; + nop; StorageLive(_14); - _14 = _4; + _14 = copy _4; - _13 = move _14 as *const u32 (PtrToPtr); -+ _13 = _4 as *const u32 (PtrToPtr); ++ _13 = copy _4 as *const u32 (PtrToPtr); StorageDead(_14); StorageLive(_15); StorageLive(_16); - _16 = _5; + _16 = copy _5; StorageLive(_17); -- _17 = _7; +- _17 = copy _7; - _15 = Eq(move _16, move _17); -+ _17 = _8; -+ _15 = Eq(_5, _8); ++ _17 = copy _8; ++ _15 = Eq(copy _5, copy _8); StorageDead(_17); StorageDead(_16); StorageLive(_18); StorageLive(_19); -- _19 = _7; -+ _19 = _8; +- _19 = copy _7; ++ _19 = copy _8; StorageLive(_20); -- _20 = _10; +- _20 = copy _10; - _18 = Eq(move _19, move _20); -+ _20 = _11; -+ _18 = Eq(_2, _3); ++ _20 = copy _11; ++ _18 = Eq(copy _2, copy _3); StorageDead(_20); StorageDead(_19); StorageLive(_21); StorageLive(_22); -- _22 = _10; -+ _22 = _11; +- _22 = copy _10; ++ _22 = copy _11; StorageLive(_23); - _23 = _13; + _23 = copy _13; - _21 = Eq(move _22, move _23); -+ _21 = Eq(_11, _13); ++ _21 = Eq(copy _11, copy _13); StorageDead(_23); StorageDead(_22); _0 = const (); diff --git a/tests/mir-opt/gvn.cast_pointer_eq.GVN.panic-unwind.diff b/tests/mir-opt/gvn.cast_pointer_eq.GVN.panic-unwind.diff index 757ab959813..f66aed0f441 100644 --- a/tests/mir-opt/gvn.cast_pointer_eq.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.cast_pointer_eq.GVN.panic-unwind.diff @@ -52,70 +52,70 @@ - StorageLive(_5); + nop; StorageLive(_6); - _6 = _1; + _6 = copy _1; - _5 = move _6 as *const u32 (PtrToPtr); -+ _5 = _1 as *const u32 (PtrToPtr); ++ _5 = copy _1 as *const u32 (PtrToPtr); StorageDead(_6); StorageLive(_7); - StorageLive(_8); + nop; StorageLive(_9); - _9 = _2; + _9 = copy _2; - _8 = move _9 as *const u32 (PtrToPtr); -+ _8 = _2 as *const u32 (PtrToPtr); ++ _8 = copy _2 as *const u32 (PtrToPtr); StorageDead(_9); - _7 = move _8 as *const u32 (PtrToPtr); - StorageDead(_8); -+ _7 = _8; ++ _7 = copy _8; + nop; StorageLive(_10); - StorageLive(_11); + nop; StorageLive(_12); - _12 = _3; + _12 = copy _3; - _11 = move _12 as *const u32 (PtrToPtr); -+ _11 = _3 as *const u32 (PtrToPtr); ++ _11 = copy _3 as *const u32 (PtrToPtr); StorageDead(_12); - _10 = move _11 as *const u32 (PtrToPtr); - StorageDead(_11); - StorageLive(_13); -+ _10 = _11; ++ _10 = copy _11; + nop; + nop; StorageLive(_14); - _14 = _4; + _14 = copy _4; - _13 = move _14 as *const u32 (PtrToPtr); -+ _13 = _4 as *const u32 (PtrToPtr); ++ _13 = copy _4 as *const u32 (PtrToPtr); StorageDead(_14); StorageLive(_15); StorageLive(_16); - _16 = _5; + _16 = copy _5; StorageLive(_17); -- _17 = _7; +- _17 = copy _7; - _15 = Eq(move _16, move _17); -+ _17 = _8; -+ _15 = Eq(_5, _8); ++ _17 = copy _8; ++ _15 = Eq(copy _5, copy _8); StorageDead(_17); StorageDead(_16); StorageLive(_18); StorageLive(_19); -- _19 = _7; -+ _19 = _8; +- _19 = copy _7; ++ _19 = copy _8; StorageLive(_20); -- _20 = _10; +- _20 = copy _10; - _18 = Eq(move _19, move _20); -+ _20 = _11; -+ _18 = Eq(_2, _3); ++ _20 = copy _11; ++ _18 = Eq(copy _2, copy _3); StorageDead(_20); StorageDead(_19); StorageLive(_21); StorageLive(_22); -- _22 = _10; -+ _22 = _11; +- _22 = copy _10; ++ _22 = copy _11; StorageLive(_23); - _23 = _13; + _23 = copy _13; - _21 = Eq(move _22, move _23); -+ _21 = Eq(_11, _13); ++ _21 = Eq(copy _11, copy _13); StorageDead(_23); StorageDead(_22); _0 = const (); diff --git a/tests/mir-opt/gvn.cast_pointer_then_transmute.GVN.panic-abort.diff b/tests/mir-opt/gvn.cast_pointer_then_transmute.GVN.panic-abort.diff index 8133f6e0b00..d9f945d2c41 100644 --- a/tests/mir-opt/gvn.cast_pointer_then_transmute.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.cast_pointer_then_transmute.GVN.panic-abort.diff @@ -22,19 +22,19 @@ StorageLive(_3); StorageLive(_4); StorageLive(_5); - _5 = _1; + _5 = copy _1; - _4 = move _5 as *const () (PtrToPtr); -+ _4 = _1 as *const () (PtrToPtr); ++ _4 = copy _1 as *const () (PtrToPtr); StorageDead(_5); - _3 = move _4 as usize (Transmute); -+ _3 = _1 as usize (Transmute); ++ _3 = copy _1 as usize (Transmute); StorageDead(_4); StorageLive(_6); StorageLive(_7); StorageLive(_8); - _8 = _2; + _8 = copy _2; - _7 = move _8 as *const () (PtrToPtr); -+ _7 = _2 as *const () (PtrToPtr); ++ _7 = copy _2 as *const () (PtrToPtr); StorageDead(_8); _6 = move _7 as usize (Transmute); StorageDead(_7); diff --git a/tests/mir-opt/gvn.cast_pointer_then_transmute.GVN.panic-unwind.diff b/tests/mir-opt/gvn.cast_pointer_then_transmute.GVN.panic-unwind.diff index 8133f6e0b00..d9f945d2c41 100644 --- a/tests/mir-opt/gvn.cast_pointer_then_transmute.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.cast_pointer_then_transmute.GVN.panic-unwind.diff @@ -22,19 +22,19 @@ StorageLive(_3); StorageLive(_4); StorageLive(_5); - _5 = _1; + _5 = copy _1; - _4 = move _5 as *const () (PtrToPtr); -+ _4 = _1 as *const () (PtrToPtr); ++ _4 = copy _1 as *const () (PtrToPtr); StorageDead(_5); - _3 = move _4 as usize (Transmute); -+ _3 = _1 as usize (Transmute); ++ _3 = copy _1 as usize (Transmute); StorageDead(_4); StorageLive(_6); StorageLive(_7); StorageLive(_8); - _8 = _2; + _8 = copy _2; - _7 = move _8 as *const () (PtrToPtr); -+ _7 = _2 as *const () (PtrToPtr); ++ _7 = copy _2 as *const () (PtrToPtr); StorageDead(_8); _6 = move _7 as usize (Transmute); StorageDead(_7); diff --git a/tests/mir-opt/gvn.casts_before_aggregate_raw_ptr.GVN.panic-abort.diff b/tests/mir-opt/gvn.casts_before_aggregate_raw_ptr.GVN.panic-abort.diff index 6e5bdb16595..fd09310fabd 100644 --- a/tests/mir-opt/gvn.casts_before_aggregate_raw_ptr.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.casts_before_aggregate_raw_ptr.GVN.panic-abort.diff @@ -25,28 +25,28 @@ - StorageLive(_2); + nop; StorageLive(_3); - _3 = _1; + _3 = copy _1; - _2 = move _3 as *const [u8; 4] (PtrToPtr); -+ _2 = _1 as *const [u8; 4] (PtrToPtr); ++ _2 = copy _1 as *const [u8; 4] (PtrToPtr); StorageDead(_3); - StorageLive(_4); + nop; StorageLive(_5); - _5 = _2; + _5 = copy _2; - _4 = move _5 as *const u8 (PtrToPtr); -+ _4 = _1 as *const u8 (PtrToPtr); ++ _4 = copy _1 as *const u8 (PtrToPtr); StorageDead(_5); - StorageLive(_6); + nop; StorageLive(_7); - _7 = _4; + _7 = copy _4; - _6 = move _7 as *const () (PtrToPtr); -+ _6 = _1 as *const () (PtrToPtr); ++ _6 = copy _1 as *const () (PtrToPtr); StorageDead(_7); StorageLive(_8); - _8 = _6; + _8 = copy _6; - _0 = *const [u8] from (move _8, const 4_usize); -+ _0 = *const [u8] from (_1, const 4_usize); ++ _0 = *const [u8] from (copy _1, const 4_usize); StorageDead(_8); - StorageDead(_6); - StorageDead(_4); diff --git a/tests/mir-opt/gvn.casts_before_aggregate_raw_ptr.GVN.panic-unwind.diff b/tests/mir-opt/gvn.casts_before_aggregate_raw_ptr.GVN.panic-unwind.diff index 6e5bdb16595..fd09310fabd 100644 --- a/tests/mir-opt/gvn.casts_before_aggregate_raw_ptr.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.casts_before_aggregate_raw_ptr.GVN.panic-unwind.diff @@ -25,28 +25,28 @@ - StorageLive(_2); + nop; StorageLive(_3); - _3 = _1; + _3 = copy _1; - _2 = move _3 as *const [u8; 4] (PtrToPtr); -+ _2 = _1 as *const [u8; 4] (PtrToPtr); ++ _2 = copy _1 as *const [u8; 4] (PtrToPtr); StorageDead(_3); - StorageLive(_4); + nop; StorageLive(_5); - _5 = _2; + _5 = copy _2; - _4 = move _5 as *const u8 (PtrToPtr); -+ _4 = _1 as *const u8 (PtrToPtr); ++ _4 = copy _1 as *const u8 (PtrToPtr); StorageDead(_5); - StorageLive(_6); + nop; StorageLive(_7); - _7 = _4; + _7 = copy _4; - _6 = move _7 as *const () (PtrToPtr); -+ _6 = _1 as *const () (PtrToPtr); ++ _6 = copy _1 as *const () (PtrToPtr); StorageDead(_7); StorageLive(_8); - _8 = _6; + _8 = copy _6; - _0 = *const [u8] from (move _8, const 4_usize); -+ _0 = *const [u8] from (_1, const 4_usize); ++ _0 = *const [u8] from (copy _1, const 4_usize); StorageDead(_8); - StorageDead(_6); - StorageDead(_4); diff --git a/tests/mir-opt/gvn.comparison.GVN.panic-abort.diff b/tests/mir-opt/gvn.comparison.GVN.panic-abort.diff index fefdf14bddc..7b25dedbb88 100644 --- a/tests/mir-opt/gvn.comparison.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.comparison.GVN.panic-abort.diff @@ -26,9 +26,9 @@ StorageLive(_3); StorageLive(_4); StorageLive(_5); - _5 = _1; + _5 = copy _1; StorageLive(_6); - _6 = _1; + _6 = copy _1; - _4 = Eq(move _5, move _6); + _4 = const true; StorageDead(_6); @@ -43,9 +43,9 @@ StorageLive(_7); StorageLive(_8); StorageLive(_9); - _9 = _1; + _9 = copy _1; StorageLive(_10); - _10 = _1; + _10 = copy _1; - _8 = Ne(move _9, move _10); + _8 = const false; StorageDead(_10); @@ -60,11 +60,11 @@ StorageLive(_11); StorageLive(_12); StorageLive(_13); - _13 = _1; + _13 = copy _1; StorageLive(_14); - _14 = _2; + _14 = copy _2; - _12 = Eq(move _13, move _14); -+ _12 = Eq(_1, _2); ++ _12 = Eq(copy _1, copy _2); StorageDead(_14); StorageDead(_13); _11 = opaque::(move _12) -> [return: bb3, unwind unreachable]; @@ -76,11 +76,11 @@ StorageLive(_15); StorageLive(_16); StorageLive(_17); - _17 = _1; + _17 = copy _1; StorageLive(_18); - _18 = _2; + _18 = copy _2; - _16 = Ne(move _17, move _18); -+ _16 = Ne(_1, _2); ++ _16 = Ne(copy _1, copy _2); StorageDead(_18); StorageDead(_17); _15 = opaque::(move _16) -> [return: bb4, unwind unreachable]; diff --git a/tests/mir-opt/gvn.comparison.GVN.panic-unwind.diff b/tests/mir-opt/gvn.comparison.GVN.panic-unwind.diff index 9f19b2b59fa..416ae1ee559 100644 --- a/tests/mir-opt/gvn.comparison.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.comparison.GVN.panic-unwind.diff @@ -26,9 +26,9 @@ StorageLive(_3); StorageLive(_4); StorageLive(_5); - _5 = _1; + _5 = copy _1; StorageLive(_6); - _6 = _1; + _6 = copy _1; - _4 = Eq(move _5, move _6); + _4 = const true; StorageDead(_6); @@ -43,9 +43,9 @@ StorageLive(_7); StorageLive(_8); StorageLive(_9); - _9 = _1; + _9 = copy _1; StorageLive(_10); - _10 = _1; + _10 = copy _1; - _8 = Ne(move _9, move _10); + _8 = const false; StorageDead(_10); @@ -60,11 +60,11 @@ StorageLive(_11); StorageLive(_12); StorageLive(_13); - _13 = _1; + _13 = copy _1; StorageLive(_14); - _14 = _2; + _14 = copy _2; - _12 = Eq(move _13, move _14); -+ _12 = Eq(_1, _2); ++ _12 = Eq(copy _1, copy _2); StorageDead(_14); StorageDead(_13); _11 = opaque::(move _12) -> [return: bb3, unwind continue]; @@ -76,11 +76,11 @@ StorageLive(_15); StorageLive(_16); StorageLive(_17); - _17 = _1; + _17 = copy _1; StorageLive(_18); - _18 = _2; + _18 = copy _2; - _16 = Ne(move _17, move _18); -+ _16 = Ne(_1, _2); ++ _16 = Ne(copy _1, copy _2); StorageDead(_18); StorageDead(_17); _15 = opaque::(move _16) -> [return: bb4, unwind continue]; diff --git a/tests/mir-opt/gvn.constant_index_overflow.GVN.panic-abort.diff b/tests/mir-opt/gvn.constant_index_overflow.GVN.panic-abort.diff index c417c51f9b7..3f052ee19fd 100644 --- a/tests/mir-opt/gvn.constant_index_overflow.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.constant_index_overflow.GVN.panic-abort.diff @@ -32,7 +32,7 @@ StorageLive(_3); StorageLive(_4); StorageLive(_5); -- _5 = _2; +- _5 = copy _2; + _5 = const usize::MAX; StorageLive(_6); StorageLive(_7); @@ -51,18 +51,18 @@ StorageDead(_6); StorageDead(_5); StorageLive(_8); -- _8 = _2; +- _8 = copy _2; + _8 = const usize::MAX; _9 = Len((*_1)); -- _10 = Lt(_8, _9); -- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> [success: bb3, unwind unreachable]; -+ _10 = Lt(const usize::MAX, _9); +- _10 = Lt(copy _8, copy _9); +- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, copy _8) -> [success: bb3, unwind unreachable]; ++ _10 = Lt(const usize::MAX, copy _9); + assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, const usize::MAX) -> [success: bb3, unwind unreachable]; } bb3: { -- _3 = (*_1)[_8]; -+ _3 = (*_1)[_2]; +- _3 = copy (*_1)[_8]; ++ _3 = copy (*_1)[_2]; StorageDead(_8); goto -> bb6; } @@ -73,15 +73,15 @@ StorageLive(_11); _11 = const 0_usize; _12 = Len((*_1)); -- _13 = Lt(_11, _12); -- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, _11) -> [success: bb5, unwind unreachable]; -+ _13 = Lt(const 0_usize, _12); +- _13 = Lt(copy _11, copy _12); +- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb5, unwind unreachable]; ++ _13 = Lt(const 0_usize, copy _12); + assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, const 0_usize) -> [success: bb5, unwind unreachable]; } bb5: { -- _3 = (*_1)[_11]; -+ _3 = (*_1)[0 of 1]; +- _3 = copy (*_1)[_11]; ++ _3 = copy (*_1)[0 of 1]; StorageDead(_11); goto -> bb6; } @@ -89,7 +89,7 @@ bb6: { StorageDead(_4); StorageLive(_14); - _14 = _3; + _14 = copy _3; _0 = opaque::(move _14) -> [return: bb7, unwind unreachable]; } diff --git a/tests/mir-opt/gvn.constant_index_overflow.GVN.panic-unwind.diff b/tests/mir-opt/gvn.constant_index_overflow.GVN.panic-unwind.diff index 7a23fbe7cc0..84b738c7804 100644 --- a/tests/mir-opt/gvn.constant_index_overflow.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.constant_index_overflow.GVN.panic-unwind.diff @@ -32,7 +32,7 @@ StorageLive(_3); StorageLive(_4); StorageLive(_5); -- _5 = _2; +- _5 = copy _2; + _5 = const usize::MAX; StorageLive(_6); StorageLive(_7); @@ -51,18 +51,18 @@ StorageDead(_6); StorageDead(_5); StorageLive(_8); -- _8 = _2; +- _8 = copy _2; + _8 = const usize::MAX; _9 = Len((*_1)); -- _10 = Lt(_8, _9); -- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> [success: bb3, unwind continue]; -+ _10 = Lt(const usize::MAX, _9); +- _10 = Lt(copy _8, copy _9); +- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, copy _8) -> [success: bb3, unwind continue]; ++ _10 = Lt(const usize::MAX, copy _9); + assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, const usize::MAX) -> [success: bb3, unwind continue]; } bb3: { -- _3 = (*_1)[_8]; -+ _3 = (*_1)[_2]; +- _3 = copy (*_1)[_8]; ++ _3 = copy (*_1)[_2]; StorageDead(_8); goto -> bb6; } @@ -73,15 +73,15 @@ StorageLive(_11); _11 = const 0_usize; _12 = Len((*_1)); -- _13 = Lt(_11, _12); -- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, _11) -> [success: bb5, unwind continue]; -+ _13 = Lt(const 0_usize, _12); +- _13 = Lt(copy _11, copy _12); +- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb5, unwind continue]; ++ _13 = Lt(const 0_usize, copy _12); + assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, const 0_usize) -> [success: bb5, unwind continue]; } bb5: { -- _3 = (*_1)[_11]; -+ _3 = (*_1)[0 of 1]; +- _3 = copy (*_1)[_11]; ++ _3 = copy (*_1)[0 of 1]; StorageDead(_11); goto -> bb6; } @@ -89,7 +89,7 @@ bb6: { StorageDead(_4); StorageLive(_14); - _14 = _3; + _14 = copy _3; _0 = opaque::(move _14) -> [return: bb7, unwind continue]; } diff --git a/tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff b/tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff index 906835530d8..a763614dc64 100644 --- a/tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff @@ -48,7 +48,7 @@ bb0: { StorageLive(_4); StorageLive(_5); - _5 = (*_1); + _5 = copy (*_1); _4 = opaque::(move _5) -> [return: bb1, unwind unreachable]; } @@ -57,7 +57,7 @@ StorageDead(_4); StorageLive(_6); StorageLive(_7); - _7 = (*_1); + _7 = copy (*_1); _6 = opaque::(move _7) -> [return: bb2, unwind unreachable]; } @@ -68,7 +68,7 @@ _8 = &raw const (*_1); StorageLive(_9); StorageLive(_10); - _10 = (*_8); + _10 = copy (*_8); _9 = opaque::(move _10) -> [return: bb3, unwind unreachable]; } @@ -77,7 +77,7 @@ StorageDead(_9); StorageLive(_11); StorageLive(_12); - _12 = (*_8); + _12 = copy (*_8); _11 = opaque::(move _12) -> [return: bb4, unwind unreachable]; } @@ -88,7 +88,7 @@ _13 = &raw mut (*_1); StorageLive(_14); StorageLive(_15); - _15 = (*_13); + _15 = copy (*_13); _14 = opaque::(move _15) -> [return: bb5, unwind unreachable]; } @@ -97,7 +97,7 @@ StorageDead(_14); StorageLive(_16); StorageLive(_17); - _17 = (*_13); + _17 = copy (*_13); _16 = opaque::(move _17) -> [return: bb6, unwind unreachable]; } @@ -109,9 +109,9 @@ StorageLive(_19); - StorageLive(_20); + nop; - _20 = (*_18); + _20 = copy (*_18); - _19 = opaque::(move _20) -> [return: bb7, unwind unreachable]; -+ _19 = opaque::(_20) -> [return: bb7, unwind unreachable]; ++ _19 = opaque::(copy _20) -> [return: bb7, unwind unreachable]; } bb7: { @@ -120,10 +120,10 @@ StorageDead(_19); StorageLive(_21); StorageLive(_22); -- _22 = (*_18); +- _22 = copy (*_18); - _21 = opaque::(move _22) -> [return: bb8, unwind unreachable]; -+ _22 = _20; -+ _21 = opaque::(_20) -> [return: bb8, unwind unreachable]; ++ _22 = copy _20; ++ _21 = opaque::(copy _20) -> [return: bb8, unwind unreachable]; } bb8: { @@ -140,7 +140,7 @@ StorageDead(_23); StorageLive(_25); StorageLive(_26); - _26 = (*_2); + _26 = copy (*_2); _25 = opaque::(move _26) -> [return: bb10, unwind unreachable]; } @@ -149,7 +149,7 @@ StorageDead(_25); StorageLive(_27); StorageLive(_28); - _28 = (*_2); + _28 = copy (*_2); _27 = opaque::(move _28) -> [return: bb11, unwind unreachable]; } @@ -159,9 +159,9 @@ StorageLive(_29); - StorageLive(_30); + nop; - _30 = ((*_3).0: u32); + _30 = copy ((*_3).0: u32); - _29 = opaque::(move _30) -> [return: bb12, unwind unreachable]; -+ _29 = opaque::(_30) -> [return: bb12, unwind unreachable]; ++ _29 = opaque::(copy _30) -> [return: bb12, unwind unreachable]; } bb12: { @@ -170,10 +170,10 @@ StorageDead(_29); StorageLive(_31); StorageLive(_32); -- _32 = ((*_3).0: u32); +- _32 = copy ((*_3).0: u32); - _31 = opaque::(move _32) -> [return: bb13, unwind unreachable]; -+ _32 = _30; -+ _31 = opaque::(_30) -> [return: bb13, unwind unreachable]; ++ _32 = copy _30; ++ _31 = opaque::(copy _30) -> [return: bb13, unwind unreachable]; } bb13: { diff --git a/tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff b/tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff index 006b5da646c..ca6fda48364 100644 --- a/tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff @@ -48,7 +48,7 @@ bb0: { StorageLive(_4); StorageLive(_5); - _5 = (*_1); + _5 = copy (*_1); _4 = opaque::(move _5) -> [return: bb1, unwind continue]; } @@ -57,7 +57,7 @@ StorageDead(_4); StorageLive(_6); StorageLive(_7); - _7 = (*_1); + _7 = copy (*_1); _6 = opaque::(move _7) -> [return: bb2, unwind continue]; } @@ -68,7 +68,7 @@ _8 = &raw const (*_1); StorageLive(_9); StorageLive(_10); - _10 = (*_8); + _10 = copy (*_8); _9 = opaque::(move _10) -> [return: bb3, unwind continue]; } @@ -77,7 +77,7 @@ StorageDead(_9); StorageLive(_11); StorageLive(_12); - _12 = (*_8); + _12 = copy (*_8); _11 = opaque::(move _12) -> [return: bb4, unwind continue]; } @@ -88,7 +88,7 @@ _13 = &raw mut (*_1); StorageLive(_14); StorageLive(_15); - _15 = (*_13); + _15 = copy (*_13); _14 = opaque::(move _15) -> [return: bb5, unwind continue]; } @@ -97,7 +97,7 @@ StorageDead(_14); StorageLive(_16); StorageLive(_17); - _17 = (*_13); + _17 = copy (*_13); _16 = opaque::(move _17) -> [return: bb6, unwind continue]; } @@ -109,9 +109,9 @@ StorageLive(_19); - StorageLive(_20); + nop; - _20 = (*_18); + _20 = copy (*_18); - _19 = opaque::(move _20) -> [return: bb7, unwind continue]; -+ _19 = opaque::(_20) -> [return: bb7, unwind continue]; ++ _19 = opaque::(copy _20) -> [return: bb7, unwind continue]; } bb7: { @@ -120,10 +120,10 @@ StorageDead(_19); StorageLive(_21); StorageLive(_22); -- _22 = (*_18); +- _22 = copy (*_18); - _21 = opaque::(move _22) -> [return: bb8, unwind continue]; -+ _22 = _20; -+ _21 = opaque::(_20) -> [return: bb8, unwind continue]; ++ _22 = copy _20; ++ _21 = opaque::(copy _20) -> [return: bb8, unwind continue]; } bb8: { @@ -140,7 +140,7 @@ StorageDead(_23); StorageLive(_25); StorageLive(_26); - _26 = (*_2); + _26 = copy (*_2); _25 = opaque::(move _26) -> [return: bb10, unwind continue]; } @@ -149,7 +149,7 @@ StorageDead(_25); StorageLive(_27); StorageLive(_28); - _28 = (*_2); + _28 = copy (*_2); _27 = opaque::(move _28) -> [return: bb11, unwind continue]; } @@ -159,9 +159,9 @@ StorageLive(_29); - StorageLive(_30); + nop; - _30 = ((*_3).0: u32); + _30 = copy ((*_3).0: u32); - _29 = opaque::(move _30) -> [return: bb12, unwind continue]; -+ _29 = opaque::(_30) -> [return: bb12, unwind continue]; ++ _29 = opaque::(copy _30) -> [return: bb12, unwind continue]; } bb12: { @@ -170,10 +170,10 @@ StorageDead(_29); StorageLive(_31); StorageLive(_32); -- _32 = ((*_3).0: u32); +- _32 = copy ((*_3).0: u32); - _31 = opaque::(move _32) -> [return: bb13, unwind continue]; -+ _32 = _30; -+ _31 = opaque::(_30) -> [return: bb13, unwind continue]; ++ _32 = copy _30; ++ _31 = opaque::(copy _30) -> [return: bb13, unwind continue]; } bb13: { diff --git a/tests/mir-opt/gvn.duplicate_slice.GVN.panic-abort.diff b/tests/mir-opt/gvn.duplicate_slice.GVN.panic-abort.diff index 7ae1fae68e8..18c2897d528 100644 --- a/tests/mir-opt/gvn.duplicate_slice.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.duplicate_slice.GVN.panic-abort.diff @@ -16,22 +16,22 @@ bb0: { _7 = (const "a",); - _1 = (_7.0: &str) as u128 (Transmute); - _5 = identity::<&str>((_7.0: &str)) -> [return: bb1, unwind unreachable]; + _1 = copy (_7.0: &str) as u128 (Transmute); + _5 = identity::<&str>(copy (_7.0: &str)) -> [return: bb1, unwind unreachable]; } bb1: { - _3 = _5 as u128 (Transmute); + _3 = copy _5 as u128 (Transmute); _8 = const "a"; - _2 = _8 as u128 (Transmute); - _6 = identity::<&str>(_8) -> [return: bb2, unwind unreachable]; + _2 = copy _8 as u128 (Transmute); + _6 = identity::<&str>(copy _8) -> [return: bb2, unwind unreachable]; } bb2: { - _4 = _6 as u128 (Transmute); - _9 = Eq(_1, _2); - _10 = Eq(_3, _4); - _0 = (_9, _10); + _4 = copy _6 as u128 (Transmute); + _9 = Eq(copy _1, copy _2); + _10 = Eq(copy _3, copy _4); + _0 = (copy _9, copy _10); return; } } diff --git a/tests/mir-opt/gvn.duplicate_slice.GVN.panic-unwind.diff b/tests/mir-opt/gvn.duplicate_slice.GVN.panic-unwind.diff index 8c96edaa280..55f382e926e 100644 --- a/tests/mir-opt/gvn.duplicate_slice.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.duplicate_slice.GVN.panic-unwind.diff @@ -16,22 +16,22 @@ bb0: { _7 = (const "a",); - _1 = (_7.0: &str) as u128 (Transmute); - _5 = identity::<&str>((_7.0: &str)) -> [return: bb1, unwind continue]; + _1 = copy (_7.0: &str) as u128 (Transmute); + _5 = identity::<&str>(copy (_7.0: &str)) -> [return: bb1, unwind continue]; } bb1: { - _3 = _5 as u128 (Transmute); + _3 = copy _5 as u128 (Transmute); _8 = const "a"; - _2 = _8 as u128 (Transmute); - _6 = identity::<&str>(_8) -> [return: bb2, unwind continue]; + _2 = copy _8 as u128 (Transmute); + _6 = identity::<&str>(copy _8) -> [return: bb2, unwind continue]; } bb2: { - _4 = _6 as u128 (Transmute); - _9 = Eq(_1, _2); - _10 = Eq(_3, _4); - _0 = (_9, _10); + _4 = copy _6 as u128 (Transmute); + _9 = Eq(copy _1, copy _2); + _10 = Eq(copy _3, copy _4); + _0 = (copy _9, copy _10); return; } } diff --git a/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff b/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff index b5c0cee7846..292b812b50c 100644 --- a/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff @@ -8,10 +8,10 @@ let mut _3: fn(u8) -> u8; let _5: (); let mut _6: fn(u8) -> u8; - let mut _9: {closure@$DIR/gvn.rs:615:19: 615:21}; + let mut _9: {closure@$DIR/gvn.rs:614:19: 614:21}; let _10: (); let mut _11: fn(); - let mut _13: {closure@$DIR/gvn.rs:615:19: 615:21}; + let mut _13: {closure@$DIR/gvn.rs:614:19: 614:21}; let _14: (); let mut _15: fn(); scope 1 { @@ -19,7 +19,7 @@ let _4: fn(u8) -> u8; scope 2 { debug g => _4; - let _7: {closure@$DIR/gvn.rs:615:19: 615:21}; + let _7: {closure@$DIR/gvn.rs:614:19: 614:21}; scope 3 { debug closure => _7; let _8: fn(); @@ -40,9 +40,9 @@ _1 = identity:: as fn(u8) -> u8 (PointerCoercion(ReifyFnPointer)); StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; - _2 = opaque:: u8>(move _3) -> [return: bb1, unwind unreachable]; -+ _2 = opaque:: u8>(_1) -> [return: bb1, unwind unreachable]; ++ _2 = opaque:: u8>(copy _1) -> [return: bb1, unwind unreachable]; } bb1: { @@ -53,31 +53,31 @@ _4 = identity:: as fn(u8) -> u8 (PointerCoercion(ReifyFnPointer)); StorageLive(_5); StorageLive(_6); - _6 = _4; + _6 = copy _4; - _5 = opaque:: u8>(move _6) -> [return: bb2, unwind unreachable]; -+ _5 = opaque:: u8>(_4) -> [return: bb2, unwind unreachable]; ++ _5 = opaque:: u8>(copy _4) -> [return: bb2, unwind unreachable]; } bb2: { StorageDead(_6); StorageDead(_5); - StorageLive(_7); -- _7 = {closure@$DIR/gvn.rs:615:19: 615:21}; +- _7 = {closure@$DIR/gvn.rs:614:19: 614:21}; - StorageLive(_8); + nop; -+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21}; ++ _7 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21}; + nop; StorageLive(_9); -- _9 = _7; +- _9 = copy _7; - _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Safe))); -+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21}; -+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21} as fn() (PointerCoercion(ClosureFnPointer(Safe))); ++ _9 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21}; ++ _8 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21} as fn() (PointerCoercion(ClosureFnPointer(Safe))); StorageDead(_9); StorageLive(_10); StorageLive(_11); - _11 = _8; + _11 = copy _8; - _10 = opaque::(move _11) -> [return: bb3, unwind unreachable]; -+ _10 = opaque::(_8) -> [return: bb3, unwind unreachable]; ++ _10 = opaque::(copy _8) -> [return: bb3, unwind unreachable]; } bb3: { @@ -86,16 +86,16 @@ - StorageLive(_12); + nop; StorageLive(_13); -- _13 = _7; +- _13 = copy _7; - _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Safe))); -+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21}; -+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21} as fn() (PointerCoercion(ClosureFnPointer(Safe))); ++ _13 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21}; ++ _12 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21} as fn() (PointerCoercion(ClosureFnPointer(Safe))); StorageDead(_13); StorageLive(_14); StorageLive(_15); - _15 = _12; + _15 = copy _12; - _14 = opaque::(move _15) -> [return: bb4, unwind unreachable]; -+ _14 = opaque::(_12) -> [return: bb4, unwind unreachable]; ++ _14 = opaque::(copy _12) -> [return: bb4, unwind unreachable]; } bb4: { diff --git a/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff b/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff index 7bc6573c13d..a60d986132e 100644 --- a/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff @@ -8,10 +8,10 @@ let mut _3: fn(u8) -> u8; let _5: (); let mut _6: fn(u8) -> u8; - let mut _9: {closure@$DIR/gvn.rs:615:19: 615:21}; + let mut _9: {closure@$DIR/gvn.rs:614:19: 614:21}; let _10: (); let mut _11: fn(); - let mut _13: {closure@$DIR/gvn.rs:615:19: 615:21}; + let mut _13: {closure@$DIR/gvn.rs:614:19: 614:21}; let _14: (); let mut _15: fn(); scope 1 { @@ -19,7 +19,7 @@ let _4: fn(u8) -> u8; scope 2 { debug g => _4; - let _7: {closure@$DIR/gvn.rs:615:19: 615:21}; + let _7: {closure@$DIR/gvn.rs:614:19: 614:21}; scope 3 { debug closure => _7; let _8: fn(); @@ -40,9 +40,9 @@ _1 = identity:: as fn(u8) -> u8 (PointerCoercion(ReifyFnPointer)); StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; - _2 = opaque:: u8>(move _3) -> [return: bb1, unwind continue]; -+ _2 = opaque:: u8>(_1) -> [return: bb1, unwind continue]; ++ _2 = opaque:: u8>(copy _1) -> [return: bb1, unwind continue]; } bb1: { @@ -53,31 +53,31 @@ _4 = identity:: as fn(u8) -> u8 (PointerCoercion(ReifyFnPointer)); StorageLive(_5); StorageLive(_6); - _6 = _4; + _6 = copy _4; - _5 = opaque:: u8>(move _6) -> [return: bb2, unwind continue]; -+ _5 = opaque:: u8>(_4) -> [return: bb2, unwind continue]; ++ _5 = opaque:: u8>(copy _4) -> [return: bb2, unwind continue]; } bb2: { StorageDead(_6); StorageDead(_5); - StorageLive(_7); -- _7 = {closure@$DIR/gvn.rs:615:19: 615:21}; +- _7 = {closure@$DIR/gvn.rs:614:19: 614:21}; - StorageLive(_8); + nop; -+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21}; ++ _7 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21}; + nop; StorageLive(_9); -- _9 = _7; +- _9 = copy _7; - _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Safe))); -+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21}; -+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21} as fn() (PointerCoercion(ClosureFnPointer(Safe))); ++ _9 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21}; ++ _8 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21} as fn() (PointerCoercion(ClosureFnPointer(Safe))); StorageDead(_9); StorageLive(_10); StorageLive(_11); - _11 = _8; + _11 = copy _8; - _10 = opaque::(move _11) -> [return: bb3, unwind continue]; -+ _10 = opaque::(_8) -> [return: bb3, unwind continue]; ++ _10 = opaque::(copy _8) -> [return: bb3, unwind continue]; } bb3: { @@ -86,16 +86,16 @@ - StorageLive(_12); + nop; StorageLive(_13); -- _13 = _7; +- _13 = copy _7; - _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Safe))); -+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21}; -+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21} as fn() (PointerCoercion(ClosureFnPointer(Safe))); ++ _13 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21}; ++ _12 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21} as fn() (PointerCoercion(ClosureFnPointer(Safe))); StorageDead(_13); StorageLive(_14); StorageLive(_15); - _15 = _12; + _15 = copy _12; - _14 = opaque::(move _15) -> [return: bb4, unwind continue]; -+ _14 = opaque::(_12) -> [return: bb4, unwind continue]; ++ _14 = opaque::(copy _12) -> [return: bb4, unwind continue]; } bb4: { diff --git a/tests/mir-opt/gvn.generic_cast_metadata.GVN.panic-abort.diff b/tests/mir-opt/gvn.generic_cast_metadata.GVN.panic-abort.diff index 1d462a8a23c..770c6730775 100644 --- a/tests/mir-opt/gvn.generic_cast_metadata.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.generic_cast_metadata.GVN.panic-abort.diff @@ -17,21 +17,21 @@ let mut _15: ::Metadata; bb0: { - _4 = _1 as *const T (PtrToPtr); - _5 = PtrMetadata(_4); - _6 = _1 as *const (&A, [T]) (PtrToPtr); -- _7 = PtrMetadata(_6); -+ _7 = PtrMetadata(_1); - _8 = _2 as *const (T, B) (PtrToPtr); - _9 = PtrMetadata(_8); - _10 = _2 as *const (T, A) (PtrToPtr); -- _11 = PtrMetadata(_10); -+ _11 = PtrMetadata(_2); - _12 = _3 as *mut A (PtrToPtr); - _13 = PtrMetadata(_12); - _14 = _3 as *mut B (PtrToPtr); -- _15 = PtrMetadata(_14); -+ _15 = PtrMetadata(_3); + _4 = copy _1 as *const T (PtrToPtr); + _5 = PtrMetadata(copy _4); + _6 = copy _1 as *const (&A, [T]) (PtrToPtr); +- _7 = PtrMetadata(copy _6); ++ _7 = PtrMetadata(copy _1); + _8 = copy _2 as *const (T, B) (PtrToPtr); + _9 = PtrMetadata(copy _8); + _10 = copy _2 as *const (T, A) (PtrToPtr); +- _11 = PtrMetadata(copy _10); ++ _11 = PtrMetadata(copy _2); + _12 = copy _3 as *mut A (PtrToPtr); + _13 = PtrMetadata(copy _12); + _14 = copy _3 as *mut B (PtrToPtr); +- _15 = PtrMetadata(copy _14); ++ _15 = PtrMetadata(copy _3); return; } } diff --git a/tests/mir-opt/gvn.generic_cast_metadata.GVN.panic-unwind.diff b/tests/mir-opt/gvn.generic_cast_metadata.GVN.panic-unwind.diff index 1d462a8a23c..770c6730775 100644 --- a/tests/mir-opt/gvn.generic_cast_metadata.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.generic_cast_metadata.GVN.panic-unwind.diff @@ -17,21 +17,21 @@ let mut _15: ::Metadata; bb0: { - _4 = _1 as *const T (PtrToPtr); - _5 = PtrMetadata(_4); - _6 = _1 as *const (&A, [T]) (PtrToPtr); -- _7 = PtrMetadata(_6); -+ _7 = PtrMetadata(_1); - _8 = _2 as *const (T, B) (PtrToPtr); - _9 = PtrMetadata(_8); - _10 = _2 as *const (T, A) (PtrToPtr); -- _11 = PtrMetadata(_10); -+ _11 = PtrMetadata(_2); - _12 = _3 as *mut A (PtrToPtr); - _13 = PtrMetadata(_12); - _14 = _3 as *mut B (PtrToPtr); -- _15 = PtrMetadata(_14); -+ _15 = PtrMetadata(_3); + _4 = copy _1 as *const T (PtrToPtr); + _5 = PtrMetadata(copy _4); + _6 = copy _1 as *const (&A, [T]) (PtrToPtr); +- _7 = PtrMetadata(copy _6); ++ _7 = PtrMetadata(copy _1); + _8 = copy _2 as *const (T, B) (PtrToPtr); + _9 = PtrMetadata(copy _8); + _10 = copy _2 as *const (T, A) (PtrToPtr); +- _11 = PtrMetadata(copy _10); ++ _11 = PtrMetadata(copy _2); + _12 = copy _3 as *mut A (PtrToPtr); + _13 = PtrMetadata(copy _12); + _14 = copy _3 as *mut B (PtrToPtr); +- _15 = PtrMetadata(copy _14); ++ _15 = PtrMetadata(copy _3); return; } } diff --git a/tests/mir-opt/gvn.indirect_static.GVN.panic-abort.diff b/tests/mir-opt/gvn.indirect_static.GVN.panic-abort.diff index e84f91e495d..97f41f89fb2 100644 --- a/tests/mir-opt/gvn.indirect_static.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.indirect_static.GVN.panic-abort.diff @@ -8,7 +8,7 @@ bb0: { _1 = const {ALLOC0: &Option}; - _2 = (((*_1) as variant#1).0: u8); + _2 = copy (((*_1) as variant#1).0: u8); return; } } diff --git a/tests/mir-opt/gvn.indirect_static.GVN.panic-unwind.diff b/tests/mir-opt/gvn.indirect_static.GVN.panic-unwind.diff index e84f91e495d..97f41f89fb2 100644 --- a/tests/mir-opt/gvn.indirect_static.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.indirect_static.GVN.panic-unwind.diff @@ -8,7 +8,7 @@ bb0: { _1 = const {ALLOC0: &Option}; - _2 = (((*_1) as variant#1).0: u8); + _2 = copy (((*_1) as variant#1).0: u8); return; } } diff --git a/tests/mir-opt/gvn.manual_slice_mut_len.GVN.panic-abort.diff b/tests/mir-opt/gvn.manual_slice_mut_len.GVN.panic-abort.diff index c877d8a3c0e..936fa3db82a 100644 --- a/tests/mir-opt/gvn.manual_slice_mut_len.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.manual_slice_mut_len.GVN.panic-abort.diff @@ -22,14 +22,14 @@ - StorageLive(_3); + nop; StorageLive(_4); - _4 = _2; + _4 = copy _2; - _3 = move _4 as *const [i32] (PtrToPtr); -+ _3 = _2 as *const [i32] (PtrToPtr); ++ _3 = copy _2 as *const [i32] (PtrToPtr); StorageDead(_4); StorageLive(_5); - _5 = _3; + _5 = copy _3; - _0 = PtrMetadata(move _5); -+ _0 = PtrMetadata(_1); ++ _0 = PtrMetadata(copy _1); StorageDead(_5); - StorageDead(_3); - StorageDead(_2); diff --git a/tests/mir-opt/gvn.manual_slice_mut_len.GVN.panic-unwind.diff b/tests/mir-opt/gvn.manual_slice_mut_len.GVN.panic-unwind.diff index c877d8a3c0e..936fa3db82a 100644 --- a/tests/mir-opt/gvn.manual_slice_mut_len.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.manual_slice_mut_len.GVN.panic-unwind.diff @@ -22,14 +22,14 @@ - StorageLive(_3); + nop; StorageLive(_4); - _4 = _2; + _4 = copy _2; - _3 = move _4 as *const [i32] (PtrToPtr); -+ _3 = _2 as *const [i32] (PtrToPtr); ++ _3 = copy _2 as *const [i32] (PtrToPtr); StorageDead(_4); StorageLive(_5); - _5 = _3; + _5 = copy _3; - _0 = PtrMetadata(move _5); -+ _0 = PtrMetadata(_1); ++ _0 = PtrMetadata(copy _1); StorageDead(_5); - StorageDead(_3); - StorageDead(_2); diff --git a/tests/mir-opt/gvn.meta_of_ref_to_slice.GVN.panic-abort.diff b/tests/mir-opt/gvn.meta_of_ref_to_slice.GVN.panic-abort.diff index 73dbabb56b3..3ed6c2b5308 100644 --- a/tests/mir-opt/gvn.meta_of_ref_to_slice.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.meta_of_ref_to_slice.GVN.panic-abort.diff @@ -15,12 +15,12 @@ - StorageLive(_2); + nop; StorageLive(_3); - _3 = _1; + _3 = copy _1; - _2 = *const [i32] from (move _3, const 1_usize); -+ _2 = *const [i32] from (_1, const 1_usize); ++ _2 = *const [i32] from (copy _1, const 1_usize); StorageDead(_3); StorageLive(_4); - _4 = _2; + _4 = copy _2; - _0 = PtrMetadata(move _4); + _0 = const 1_usize; StorageDead(_4); diff --git a/tests/mir-opt/gvn.meta_of_ref_to_slice.GVN.panic-unwind.diff b/tests/mir-opt/gvn.meta_of_ref_to_slice.GVN.panic-unwind.diff index 73dbabb56b3..3ed6c2b5308 100644 --- a/tests/mir-opt/gvn.meta_of_ref_to_slice.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.meta_of_ref_to_slice.GVN.panic-unwind.diff @@ -15,12 +15,12 @@ - StorageLive(_2); + nop; StorageLive(_3); - _3 = _1; + _3 = copy _1; - _2 = *const [i32] from (move _3, const 1_usize); -+ _2 = *const [i32] from (_1, const 1_usize); ++ _2 = *const [i32] from (copy _1, const 1_usize); StorageDead(_3); StorageLive(_4); - _4 = _2; + _4 = copy _2; - _0 = PtrMetadata(move _4); + _0 = const 1_usize; StorageDead(_4); diff --git a/tests/mir-opt/gvn.multiple_branches.GVN.panic-abort.diff b/tests/mir-opt/gvn.multiple_branches.GVN.panic-abort.diff index 29ca1ba5902..f300ce7e884 100644 --- a/tests/mir-opt/gvn.multiple_branches.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.multiple_branches.GVN.panic-abort.diff @@ -41,9 +41,9 @@ bb0: { StorageLive(_4); StorageLive(_5); - _5 = _1; + _5 = copy _1; - switchInt(move _5) -> [0: bb4, otherwise: bb1]; -+ switchInt(_1) -> [0: bb4, otherwise: bb1]; ++ switchInt(copy _1) -> [0: bb4, otherwise: bb1]; } bb1: { @@ -51,15 +51,15 @@ - StorageLive(_7); + nop; StorageLive(_8); - _8 = _2; + _8 = copy _2; StorageLive(_9); - _9 = _3; + _9 = copy _3; - _7 = Add(move _8, move _9); -+ _7 = Add(_2, _3); ++ _7 = Add(copy _2, copy _3); StorageDead(_9); StorageDead(_8); - _6 = opaque::(move _7) -> [return: bb2, unwind unreachable]; -+ _6 = opaque::(_7) -> [return: bb2, unwind unreachable]; ++ _6 = opaque::(copy _7) -> [return: bb2, unwind unreachable]; } bb2: { @@ -69,15 +69,15 @@ StorageLive(_10); StorageLive(_11); StorageLive(_12); - _12 = _2; + _12 = copy _2; StorageLive(_13); - _13 = _3; + _13 = copy _3; - _11 = Add(move _12, move _13); -+ _11 = _7; ++ _11 = copy _7; StorageDead(_13); StorageDead(_12); - _10 = opaque::(move _11) -> [return: bb3, unwind unreachable]; -+ _10 = opaque::(_7) -> [return: bb3, unwind unreachable]; ++ _10 = opaque::(copy _7) -> [return: bb3, unwind unreachable]; } bb3: { @@ -92,15 +92,15 @@ - StorageLive(_15); + nop; StorageLive(_16); - _16 = _2; + _16 = copy _2; StorageLive(_17); - _17 = _3; + _17 = copy _3; - _15 = Add(move _16, move _17); -+ _15 = Add(_2, _3); ++ _15 = Add(copy _2, copy _3); StorageDead(_17); StorageDead(_16); - _14 = opaque::(move _15) -> [return: bb5, unwind unreachable]; -+ _14 = opaque::(_15) -> [return: bb5, unwind unreachable]; ++ _14 = opaque::(copy _15) -> [return: bb5, unwind unreachable]; } bb5: { @@ -110,15 +110,15 @@ StorageLive(_18); StorageLive(_19); StorageLive(_20); - _20 = _2; + _20 = copy _2; StorageLive(_21); - _21 = _3; + _21 = copy _3; - _19 = Add(move _20, move _21); -+ _19 = _15; ++ _19 = copy _15; StorageDead(_21); StorageDead(_20); - _18 = opaque::(move _19) -> [return: bb6, unwind unreachable]; -+ _18 = opaque::(_15) -> [return: bb6, unwind unreachable]; ++ _18 = opaque::(copy _15) -> [return: bb6, unwind unreachable]; } bb6: { @@ -135,15 +135,15 @@ - StorageLive(_23); + nop; StorageLive(_24); - _24 = _2; + _24 = copy _2; StorageLive(_25); - _25 = _3; + _25 = copy _3; - _23 = Add(move _24, move _25); -+ _23 = Add(_2, _3); ++ _23 = Add(copy _2, copy _3); StorageDead(_25); StorageDead(_24); - _22 = opaque::(move _23) -> [return: bb8, unwind unreachable]; -+ _22 = opaque::(_23) -> [return: bb8, unwind unreachable]; ++ _22 = opaque::(copy _23) -> [return: bb8, unwind unreachable]; } bb8: { @@ -151,24 +151,24 @@ + nop; StorageDead(_22); StorageLive(_26); - _26 = _1; + _26 = copy _1; - switchInt(move _26) -> [0: bb11, otherwise: bb9]; -+ switchInt(_1) -> [0: bb11, otherwise: bb9]; ++ switchInt(copy _1) -> [0: bb11, otherwise: bb9]; } bb9: { StorageLive(_27); StorageLive(_28); StorageLive(_29); - _29 = _2; + _29 = copy _2; StorageLive(_30); - _30 = _3; + _30 = copy _3; - _28 = Add(move _29, move _30); -+ _28 = _23; ++ _28 = copy _23; StorageDead(_30); StorageDead(_29); - _27 = opaque::(move _28) -> [return: bb10, unwind unreachable]; -+ _27 = opaque::(_23) -> [return: bb10, unwind unreachable]; ++ _27 = opaque::(copy _23) -> [return: bb10, unwind unreachable]; } bb10: { @@ -182,15 +182,15 @@ StorageLive(_31); StorageLive(_32); StorageLive(_33); - _33 = _2; + _33 = copy _2; StorageLive(_34); - _34 = _3; + _34 = copy _3; - _32 = Add(move _33, move _34); -+ _32 = _23; ++ _32 = copy _23; StorageDead(_34); StorageDead(_33); - _31 = opaque::(move _32) -> [return: bb12, unwind unreachable]; -+ _31 = opaque::(_23) -> [return: bb12, unwind unreachable]; ++ _31 = opaque::(copy _23) -> [return: bb12, unwind unreachable]; } bb12: { diff --git a/tests/mir-opt/gvn.multiple_branches.GVN.panic-unwind.diff b/tests/mir-opt/gvn.multiple_branches.GVN.panic-unwind.diff index 5394dc8be8a..f34765534cc 100644 --- a/tests/mir-opt/gvn.multiple_branches.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.multiple_branches.GVN.panic-unwind.diff @@ -41,9 +41,9 @@ bb0: { StorageLive(_4); StorageLive(_5); - _5 = _1; + _5 = copy _1; - switchInt(move _5) -> [0: bb4, otherwise: bb1]; -+ switchInt(_1) -> [0: bb4, otherwise: bb1]; ++ switchInt(copy _1) -> [0: bb4, otherwise: bb1]; } bb1: { @@ -51,15 +51,15 @@ - StorageLive(_7); + nop; StorageLive(_8); - _8 = _2; + _8 = copy _2; StorageLive(_9); - _9 = _3; + _9 = copy _3; - _7 = Add(move _8, move _9); -+ _7 = Add(_2, _3); ++ _7 = Add(copy _2, copy _3); StorageDead(_9); StorageDead(_8); - _6 = opaque::(move _7) -> [return: bb2, unwind continue]; -+ _6 = opaque::(_7) -> [return: bb2, unwind continue]; ++ _6 = opaque::(copy _7) -> [return: bb2, unwind continue]; } bb2: { @@ -69,15 +69,15 @@ StorageLive(_10); StorageLive(_11); StorageLive(_12); - _12 = _2; + _12 = copy _2; StorageLive(_13); - _13 = _3; + _13 = copy _3; - _11 = Add(move _12, move _13); -+ _11 = _7; ++ _11 = copy _7; StorageDead(_13); StorageDead(_12); - _10 = opaque::(move _11) -> [return: bb3, unwind continue]; -+ _10 = opaque::(_7) -> [return: bb3, unwind continue]; ++ _10 = opaque::(copy _7) -> [return: bb3, unwind continue]; } bb3: { @@ -92,15 +92,15 @@ - StorageLive(_15); + nop; StorageLive(_16); - _16 = _2; + _16 = copy _2; StorageLive(_17); - _17 = _3; + _17 = copy _3; - _15 = Add(move _16, move _17); -+ _15 = Add(_2, _3); ++ _15 = Add(copy _2, copy _3); StorageDead(_17); StorageDead(_16); - _14 = opaque::(move _15) -> [return: bb5, unwind continue]; -+ _14 = opaque::(_15) -> [return: bb5, unwind continue]; ++ _14 = opaque::(copy _15) -> [return: bb5, unwind continue]; } bb5: { @@ -110,15 +110,15 @@ StorageLive(_18); StorageLive(_19); StorageLive(_20); - _20 = _2; + _20 = copy _2; StorageLive(_21); - _21 = _3; + _21 = copy _3; - _19 = Add(move _20, move _21); -+ _19 = _15; ++ _19 = copy _15; StorageDead(_21); StorageDead(_20); - _18 = opaque::(move _19) -> [return: bb6, unwind continue]; -+ _18 = opaque::(_15) -> [return: bb6, unwind continue]; ++ _18 = opaque::(copy _15) -> [return: bb6, unwind continue]; } bb6: { @@ -135,15 +135,15 @@ - StorageLive(_23); + nop; StorageLive(_24); - _24 = _2; + _24 = copy _2; StorageLive(_25); - _25 = _3; + _25 = copy _3; - _23 = Add(move _24, move _25); -+ _23 = Add(_2, _3); ++ _23 = Add(copy _2, copy _3); StorageDead(_25); StorageDead(_24); - _22 = opaque::(move _23) -> [return: bb8, unwind continue]; -+ _22 = opaque::(_23) -> [return: bb8, unwind continue]; ++ _22 = opaque::(copy _23) -> [return: bb8, unwind continue]; } bb8: { @@ -151,24 +151,24 @@ + nop; StorageDead(_22); StorageLive(_26); - _26 = _1; + _26 = copy _1; - switchInt(move _26) -> [0: bb11, otherwise: bb9]; -+ switchInt(_1) -> [0: bb11, otherwise: bb9]; ++ switchInt(copy _1) -> [0: bb11, otherwise: bb9]; } bb9: { StorageLive(_27); StorageLive(_28); StorageLive(_29); - _29 = _2; + _29 = copy _2; StorageLive(_30); - _30 = _3; + _30 = copy _3; - _28 = Add(move _29, move _30); -+ _28 = _23; ++ _28 = copy _23; StorageDead(_30); StorageDead(_29); - _27 = opaque::(move _28) -> [return: bb10, unwind continue]; -+ _27 = opaque::(_23) -> [return: bb10, unwind continue]; ++ _27 = opaque::(copy _23) -> [return: bb10, unwind continue]; } bb10: { @@ -182,15 +182,15 @@ StorageLive(_31); StorageLive(_32); StorageLive(_33); - _33 = _2; + _33 = copy _2; StorageLive(_34); - _34 = _3; + _34 = copy _3; - _32 = Add(move _33, move _34); -+ _32 = _23; ++ _32 = copy _23; StorageDead(_34); StorageDead(_33); - _31 = opaque::(move _32) -> [return: bb12, unwind continue]; -+ _31 = opaque::(_23) -> [return: bb12, unwind continue]; ++ _31 = opaque::(copy _23) -> [return: bb12, unwind continue]; } bb12: { diff --git a/tests/mir-opt/gvn.non_freeze.GVN.panic-abort.diff b/tests/mir-opt/gvn.non_freeze.GVN.panic-abort.diff index 7b6ed096118..377b4d7670c 100644 --- a/tests/mir-opt/gvn.non_freeze.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.non_freeze.GVN.panic-abort.diff @@ -7,17 +7,17 @@ let mut _3: &T; bb0: { - _2 = _1; + _2 = copy _1; _3 = &_1; - _0 = opaque::<&T>(_3) -> [return: bb1, unwind unreachable]; + _0 = opaque::<&T>(copy _3) -> [return: bb1, unwind unreachable]; } bb1: { - _0 = opaque::(_2) -> [return: bb2, unwind unreachable]; + _0 = opaque::(copy _2) -> [return: bb2, unwind unreachable]; } bb2: { - _0 = opaque::((*_3)) -> [return: bb3, unwind unreachable]; + _0 = opaque::(copy (*_3)) -> [return: bb3, unwind unreachable]; } bb3: { diff --git a/tests/mir-opt/gvn.non_freeze.GVN.panic-unwind.diff b/tests/mir-opt/gvn.non_freeze.GVN.panic-unwind.diff index 641a2f4609a..988eee07cc9 100644 --- a/tests/mir-opt/gvn.non_freeze.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.non_freeze.GVN.panic-unwind.diff @@ -7,17 +7,17 @@ let mut _3: &T; bb0: { - _2 = _1; + _2 = copy _1; _3 = &_1; - _0 = opaque::<&T>(_3) -> [return: bb1, unwind continue]; + _0 = opaque::<&T>(copy _3) -> [return: bb1, unwind continue]; } bb1: { - _0 = opaque::(_2) -> [return: bb2, unwind continue]; + _0 = opaque::(copy _2) -> [return: bb2, unwind continue]; } bb2: { - _0 = opaque::((*_3)) -> [return: bb3, unwind continue]; + _0 = opaque::(copy (*_3)) -> [return: bb3, unwind continue]; } bb3: { diff --git a/tests/mir-opt/gvn.references.GVN.panic-abort.diff b/tests/mir-opt/gvn.references.GVN.panic-abort.diff index 7799c611445..62a487dee82 100644 --- a/tests/mir-opt/gvn.references.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.references.GVN.panic-abort.diff @@ -120,11 +120,11 @@ StorageLive(_21); - _21 = move _18; - _20 = S::<&mut impl Sized>(move _21); -+ _21 = _18; -+ _20 = S::<&mut impl Sized>(_18); ++ _21 = copy _18; ++ _20 = S::<&mut impl Sized>(copy _18); StorageDead(_21); - _19 = move (_20.0: &mut impl Sized); -+ _19 = _18; ++ _19 = copy _18; StorageDead(_20); StorageLive(_22); StorageLive(_23); diff --git a/tests/mir-opt/gvn.references.GVN.panic-unwind.diff b/tests/mir-opt/gvn.references.GVN.panic-unwind.diff index 880e7913fa9..6dd986907fc 100644 --- a/tests/mir-opt/gvn.references.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.references.GVN.panic-unwind.diff @@ -120,11 +120,11 @@ StorageLive(_21); - _21 = move _18; - _20 = S::<&mut impl Sized>(move _21); -+ _21 = _18; -+ _20 = S::<&mut impl Sized>(_18); ++ _21 = copy _18; ++ _20 = S::<&mut impl Sized>(copy _18); StorageDead(_21); - _19 = move (_20.0: &mut impl Sized); -+ _19 = _18; ++ _19 = copy _18; StorageDead(_20); StorageLive(_22); StorageLive(_23); diff --git a/tests/mir-opt/gvn.remove_casts_must_change_both_sides.GVN.panic-abort.diff b/tests/mir-opt/gvn.remove_casts_must_change_both_sides.GVN.panic-abort.diff index 8b4bfb70401..98cb34810bc 100644 --- a/tests/mir-opt/gvn.remove_casts_must_change_both_sides.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.remove_casts_must_change_both_sides.GVN.panic-abort.diff @@ -7,9 +7,9 @@ let mut _4: *const u8; bb0: { - _3 = (*_1) as *const u8 (PtrToPtr); - _4 = _2 as *const u8 (PtrToPtr); - _0 = Eq(_3, _4); + _3 = copy (*_1) as *const u8 (PtrToPtr); + _4 = copy _2 as *const u8 (PtrToPtr); + _0 = Eq(copy _3, copy _4); return; } } diff --git a/tests/mir-opt/gvn.remove_casts_must_change_both_sides.GVN.panic-unwind.diff b/tests/mir-opt/gvn.remove_casts_must_change_both_sides.GVN.panic-unwind.diff index 8b4bfb70401..98cb34810bc 100644 --- a/tests/mir-opt/gvn.remove_casts_must_change_both_sides.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.remove_casts_must_change_both_sides.GVN.panic-unwind.diff @@ -7,9 +7,9 @@ let mut _4: *const u8; bb0: { - _3 = (*_1) as *const u8 (PtrToPtr); - _4 = _2 as *const u8 (PtrToPtr); - _0 = Eq(_3, _4); + _3 = copy (*_1) as *const u8 (PtrToPtr); + _4 = copy _2 as *const u8 (PtrToPtr); + _0 = Eq(copy _3, copy _4); return; } } diff --git a/tests/mir-opt/gvn.repeat.GVN.panic-abort.diff b/tests/mir-opt/gvn.repeat.GVN.panic-abort.diff index 37915f8578d..ef2eb1a6677 100644 --- a/tests/mir-opt/gvn.repeat.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.repeat.GVN.panic-abort.diff @@ -28,34 +28,34 @@ _1 = const 5_i32; StorageLive(_2); StorageLive(_3); -- _3 = _1; +- _3 = copy _1; + _3 = const 5_i32; StorageLive(_4); -- _4 = _1; +- _4 = copy _1; + _4 = const 5_i32; StorageLive(_5); -- _5 = _1; +- _5 = copy _1; + _5 = const 5_i32; StorageLive(_6); -- _6 = _1; +- _6 = copy _1; + _6 = const 5_i32; StorageLive(_7); -- _7 = _1; +- _7 = copy _1; + _7 = const 5_i32; StorageLive(_8); -- _8 = _1; +- _8 = copy _1; + _8 = const 5_i32; StorageLive(_9); -- _9 = _1; +- _9 = copy _1; + _9 = const 5_i32; StorageLive(_10); -- _10 = _1; +- _10 = copy _1; + _10 = const 5_i32; StorageLive(_11); -- _11 = _1; +- _11 = copy _1; + _11 = const 5_i32; StorageLive(_12); -- _12 = _1; +- _12 = copy _1; - _2 = [move _3, move _4, move _5, move _6, move _7, move _8, move _9, move _10, move _11, move _12]; + _12 = const 5_i32; + _2 = [const 5_i32; 10]; diff --git a/tests/mir-opt/gvn.repeat.GVN.panic-unwind.diff b/tests/mir-opt/gvn.repeat.GVN.panic-unwind.diff index 37915f8578d..ef2eb1a6677 100644 --- a/tests/mir-opt/gvn.repeat.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.repeat.GVN.panic-unwind.diff @@ -28,34 +28,34 @@ _1 = const 5_i32; StorageLive(_2); StorageLive(_3); -- _3 = _1; +- _3 = copy _1; + _3 = const 5_i32; StorageLive(_4); -- _4 = _1; +- _4 = copy _1; + _4 = const 5_i32; StorageLive(_5); -- _5 = _1; +- _5 = copy _1; + _5 = const 5_i32; StorageLive(_6); -- _6 = _1; +- _6 = copy _1; + _6 = const 5_i32; StorageLive(_7); -- _7 = _1; +- _7 = copy _1; + _7 = const 5_i32; StorageLive(_8); -- _8 = _1; +- _8 = copy _1; + _8 = const 5_i32; StorageLive(_9); -- _9 = _1; +- _9 = copy _1; + _9 = const 5_i32; StorageLive(_10); -- _10 = _1; +- _10 = copy _1; + _10 = const 5_i32; StorageLive(_11); -- _11 = _1; +- _11 = copy _1; + _11 = const 5_i32; StorageLive(_12); -- _12 = _1; +- _12 = copy _1; - _2 = [move _3, move _4, move _5, move _6, move _7, move _8, move _9, move _10, move _11, move _12]; + _12 = const 5_i32; + _2 = [const 5_i32; 10]; diff --git a/tests/mir-opt/gvn.repeated_index.GVN.panic-abort.diff b/tests/mir-opt/gvn.repeated_index.GVN.panic-abort.diff index 8ce05c9b340..d4b22d05f6c 100644 --- a/tests/mir-opt/gvn.repeated_index.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.repeated_index.GVN.panic-abort.diff @@ -24,27 +24,27 @@ bb0: { StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; - _3 = [move _4; N]; -+ _3 = [_1; N]; ++ _3 = [copy _1; N]; StorageDead(_4); StorageLive(_5); StorageLive(_6); StorageLive(_7); _7 = const 0_usize; - _8 = Len(_3); -- _9 = Lt(_7, _8); -- assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, _7) -> [success: bb1, unwind unreachable]; +- _9 = Lt(copy _7, copy _8); +- assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, copy _7) -> [success: bb1, unwind unreachable]; + _8 = const N; + _9 = Lt(const 0_usize, const N); + assert(move _9, "index out of bounds: the length is {} but the index is {}", const N, const 0_usize) -> [success: bb1, unwind unreachable]; } bb1: { -- _6 = _3[_7]; +- _6 = copy _3[_7]; - _5 = opaque::(move _6) -> [return: bb2, unwind unreachable]; -+ _6 = _1; -+ _5 = opaque::(_1) -> [return: bb2, unwind unreachable]; ++ _6 = copy _1; ++ _5 = opaque::(copy _1) -> [return: bb2, unwind unreachable]; } bb2: { @@ -54,20 +54,20 @@ StorageLive(_10); StorageLive(_11); StorageLive(_12); - _12 = _2; + _12 = copy _2; - _13 = Len(_3); -- _14 = Lt(_12, _13); -- assert(move _14, "index out of bounds: the length is {} but the index is {}", move _13, _12) -> [success: bb3, unwind unreachable]; +- _14 = Lt(copy _12, copy _13); +- assert(move _14, "index out of bounds: the length is {} but the index is {}", move _13, copy _12) -> [success: bb3, unwind unreachable]; + _13 = const N; -+ _14 = Lt(_2, const N); -+ assert(move _14, "index out of bounds: the length is {} but the index is {}", const N, _2) -> [success: bb3, unwind unreachable]; ++ _14 = Lt(copy _2, const N); ++ assert(move _14, "index out of bounds: the length is {} but the index is {}", const N, copy _2) -> [success: bb3, unwind unreachable]; } bb3: { -- _11 = _3[_12]; +- _11 = copy _3[_12]; - _10 = opaque::(move _11) -> [return: bb4, unwind unreachable]; -+ _11 = _1; -+ _10 = opaque::(_1) -> [return: bb4, unwind unreachable]; ++ _11 = copy _1; ++ _10 = opaque::(copy _1) -> [return: bb4, unwind unreachable]; } bb4: { diff --git a/tests/mir-opt/gvn.repeated_index.GVN.panic-unwind.diff b/tests/mir-opt/gvn.repeated_index.GVN.panic-unwind.diff index 7ed547eeb4a..708c0f92e54 100644 --- a/tests/mir-opt/gvn.repeated_index.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.repeated_index.GVN.panic-unwind.diff @@ -24,27 +24,27 @@ bb0: { StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; - _3 = [move _4; N]; -+ _3 = [_1; N]; ++ _3 = [copy _1; N]; StorageDead(_4); StorageLive(_5); StorageLive(_6); StorageLive(_7); _7 = const 0_usize; - _8 = Len(_3); -- _9 = Lt(_7, _8); -- assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, _7) -> [success: bb1, unwind continue]; +- _9 = Lt(copy _7, copy _8); +- assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, copy _7) -> [success: bb1, unwind continue]; + _8 = const N; + _9 = Lt(const 0_usize, const N); + assert(move _9, "index out of bounds: the length is {} but the index is {}", const N, const 0_usize) -> [success: bb1, unwind continue]; } bb1: { -- _6 = _3[_7]; +- _6 = copy _3[_7]; - _5 = opaque::(move _6) -> [return: bb2, unwind continue]; -+ _6 = _1; -+ _5 = opaque::(_1) -> [return: bb2, unwind continue]; ++ _6 = copy _1; ++ _5 = opaque::(copy _1) -> [return: bb2, unwind continue]; } bb2: { @@ -54,20 +54,20 @@ StorageLive(_10); StorageLive(_11); StorageLive(_12); - _12 = _2; + _12 = copy _2; - _13 = Len(_3); -- _14 = Lt(_12, _13); -- assert(move _14, "index out of bounds: the length is {} but the index is {}", move _13, _12) -> [success: bb3, unwind continue]; +- _14 = Lt(copy _12, copy _13); +- assert(move _14, "index out of bounds: the length is {} but the index is {}", move _13, copy _12) -> [success: bb3, unwind continue]; + _13 = const N; -+ _14 = Lt(_2, const N); -+ assert(move _14, "index out of bounds: the length is {} but the index is {}", const N, _2) -> [success: bb3, unwind continue]; ++ _14 = Lt(copy _2, const N); ++ assert(move _14, "index out of bounds: the length is {} but the index is {}", const N, copy _2) -> [success: bb3, unwind continue]; } bb3: { -- _11 = _3[_12]; +- _11 = copy _3[_12]; - _10 = opaque::(move _11) -> [return: bb4, unwind continue]; -+ _11 = _1; -+ _10 = opaque::(_1) -> [return: bb4, unwind continue]; ++ _11 = copy _1; ++ _10 = opaque::(copy _1) -> [return: bb4, unwind continue]; } bb4: { diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs index 430f979fec7..faa6faa7017 100644 --- a/tests/mir-opt/gvn.rs +++ b/tests/mir-opt/gvn.rs @@ -3,7 +3,6 @@ // EMIT_MIR_FOR_EACH_PANIC_STRATEGY //@ only-64bit -#![feature(raw_ref_op)] #![feature(rustc_attrs)] #![feature(custom_mir)] #![feature(core_intrinsics)] @@ -21,91 +20,91 @@ struct S(T); fn subexpression_elimination(x: u64, y: u64, mut z: u64) { // CHECK-LABEL: fn subexpression_elimination( - // CHECK: [[add:_.*]] = Add(_1, _2); - // CHECK: opaque::([[add]]) + // CHECK: [[add:_.*]] = Add(copy _1, copy _2); + // CHECK: opaque::(copy [[add]]) opaque(x + y); - // CHECK: [[mul:_.*]] = Mul(_1, _2); - // CHECK: opaque::([[mul]]) + // CHECK: [[mul:_.*]] = Mul(copy _1, copy _2); + // CHECK: opaque::(copy [[mul]]) opaque(x * y); - // CHECK: [[sub:_.*]] = Sub(_1, _2); - // CHECK: opaque::([[sub]]) + // CHECK: [[sub:_.*]] = Sub(copy _1, copy _2); + // CHECK: opaque::(copy [[sub]]) opaque(x - y); - // CHECK: [[div:_.*]] = Div(_1, _2); - // CHECK: opaque::([[div]]) + // CHECK: [[div:_.*]] = Div(copy _1, copy _2); + // CHECK: opaque::(copy [[div]]) opaque(x / y); - // CHECK: [[rem:_.*]] = Rem(_1, _2); - // CHECK: opaque::([[rem]]) + // CHECK: [[rem:_.*]] = Rem(copy _1, copy _2); + // CHECK: opaque::(copy [[rem]]) opaque(x % y); - // CHECK: [[and:_.*]] = BitAnd(_1, _2); - // CHECK: opaque::([[and]]) + // CHECK: [[and:_.*]] = BitAnd(copy _1, copy _2); + // CHECK: opaque::(copy [[and]]) opaque(x & y); - // CHECK: [[or:_.*]] = BitOr(_1, _2); - // CHECK: opaque::([[or]]) + // CHECK: [[or:_.*]] = BitOr(copy _1, copy _2); + // CHECK: opaque::(copy [[or]]) opaque(x | y); - // CHECK: [[xor:_.*]] = BitXor(_1, _2); - // CHECK: opaque::([[xor]]) + // CHECK: [[xor:_.*]] = BitXor(copy _1, copy _2); + // CHECK: opaque::(copy [[xor]]) opaque(x ^ y); - // CHECK: [[shl:_.*]] = Shl(_1, _2); - // CHECK: opaque::([[shl]]) + // CHECK: [[shl:_.*]] = Shl(copy _1, copy _2); + // CHECK: opaque::(copy [[shl]]) opaque(x << y); - // CHECK: [[shr:_.*]] = Shr(_1, _2); - // CHECK: opaque::([[shr]]) + // CHECK: [[shr:_.*]] = Shr(copy _1, copy _2); + // CHECK: opaque::(copy [[shr]]) opaque(x >> y); - // CHECK: [[int:_.*]] = _1 as u32 (IntToInt); - // CHECK: opaque::([[int]]) + // CHECK: [[int:_.*]] = copy _1 as u32 (IntToInt); + // CHECK: opaque::(copy [[int]]) opaque(x as u32); - // CHECK: [[float:_.*]] = _1 as f32 (IntToFloat); - // CHECK: opaque::([[float]]) + // CHECK: [[float:_.*]] = copy _1 as f32 (IntToFloat); + // CHECK: opaque::(copy [[float]]) opaque(x as f32); - // CHECK: [[wrap:_.*]] = S::(_1); - // CHECK: opaque::>([[wrap]]) + // CHECK: [[wrap:_.*]] = S::(copy _1); + // CHECK: opaque::>(copy [[wrap]]) opaque(S(x)); - // CHECK: opaque::(_1) + // CHECK: opaque::(copy _1) opaque(S(x).0); // Those are duplicates to substitute somehow. - // CHECK: opaque::([[add]]) + // CHECK: opaque::(copy [[add]]) opaque(x + y); - // CHECK: opaque::([[mul]]) + // CHECK: opaque::(copy [[mul]]) opaque(x * y); - // CHECK: opaque::([[sub]]) + // CHECK: opaque::(copy [[sub]]) opaque(x - y); - // CHECK: opaque::([[div]]) + // CHECK: opaque::(copy [[div]]) opaque(x / y); - // CHECK: opaque::([[rem]]) + // CHECK: opaque::(copy [[rem]]) opaque(x % y); - // CHECK: opaque::([[and]]) + // CHECK: opaque::(copy [[and]]) opaque(x & y); - // CHECK: opaque::([[or]]) + // CHECK: opaque::(copy [[or]]) opaque(x | y); - // CHECK: opaque::([[xor]]) + // CHECK: opaque::(copy [[xor]]) opaque(x ^ y); - // CHECK: opaque::([[shl]]) + // CHECK: opaque::(copy [[shl]]) opaque(x << y); - // CHECK: opaque::([[shr]]) + // CHECK: opaque::(copy [[shr]]) opaque(x >> y); - // CHECK: opaque::([[int]]) + // CHECK: opaque::(copy [[int]]) opaque(x as u32); - // CHECK: opaque::([[float]]) + // CHECK: opaque::(copy [[float]]) opaque(x as f32); - // CHECK: opaque::>([[wrap]]) + // CHECK: opaque::>(copy [[wrap]]) opaque(S(x)); - // CHECK: opaque::(_1) + // CHECK: opaque::(copy _1) opaque(S(x).0); // We can substitute through a complex expression. - // CHECK: [[compound:_.*]] = Sub([[mul]], _2); - // CHECK: opaque::([[compound]]) - // CHECK: opaque::([[compound]]) + // CHECK: [[compound:_.*]] = Sub(copy [[mul]], copy _2); + // CHECK: opaque::(copy [[compound]]) + // CHECK: opaque::(copy [[compound]]) opaque((x * y) - y); opaque((x * y) - y); // We can substitute through an immutable reference too. // CHECK: [[ref:_.*]] = &_3; - // CHECK: [[deref:_.*]] = (*[[ref]]); - // CHECK: [[addref:_.*]] = Add([[deref]], _1); - // CHECK: opaque::([[addref]]) - // CHECK: opaque::([[addref]]) + // CHECK: [[deref:_.*]] = copy (*[[ref]]); + // CHECK: [[addref:_.*]] = Add(copy [[deref]], copy _1); + // CHECK: opaque::(copy [[addref]]) + // CHECK: opaque::(copy [[addref]]) let a = &z; opaque(*a + x); opaque(*a + x); @@ -141,10 +140,10 @@ fn subexpression_elimination(x: u64, y: u64, mut z: u64) { // We can substitute again, but not with the earlier computations. // Important: `e` is not `a`! // CHECK: [[ref2:_.*]] = &_3; - // CHECK: [[deref2:_.*]] = (*[[ref2]]); - // CHECK: [[addref2:_.*]] = Add([[deref2]], _1); - // CHECK: opaque::([[addref2]]) - // CHECK: opaque::([[addref2]]) + // CHECK: [[deref2:_.*]] = copy (*[[ref2]]); + // CHECK: [[addref2:_.*]] = Add(copy [[deref2]], copy _1); + // CHECK: opaque::(copy [[addref2]]) + // CHECK: opaque::(copy [[addref2]]) let e = &z; opaque(*e + x); opaque(*e + x); @@ -152,9 +151,9 @@ fn subexpression_elimination(x: u64, y: u64, mut z: u64) { fn wrap_unwrap(x: T) -> T { // CHECK-LABEL: fn wrap_unwrap( - // CHECK: [[some:_.*]] = Option::::Some(_1); + // CHECK: [[some:_.*]] = Option::::Some(copy _1); // CHECK: switchInt(const 1_isize) - // CHECK: _0 = _1; + // CHECK: _0 = copy _1; match Some(x) { Some(y) => y, None => panic!(), @@ -163,35 +162,35 @@ fn wrap_unwrap(x: T) -> T { fn repeated_index(x: T, idx: usize) { // CHECK-LABEL: fn repeated_index( - // CHECK: [[a:_.*]] = [_1; N]; + // CHECK: [[a:_.*]] = [copy _1; N]; let a = [x; N]; - // CHECK: opaque::(_1) + // CHECK: opaque::(copy _1) opaque(a[0]); - // CHECK: opaque::(_1) + // CHECK: opaque::(copy _1) opaque(a[idx]); } fn unary(x: i64) { // CHECK-LABEL: fn unary( - // CHECK: opaque::(_1) + // CHECK: opaque::(copy _1) opaque(--x); // This is `x`. - // CHECK: [[b:_.*]] = Lt(_1, const 13_i64); - // CHECK: opaque::([[b]]) + // CHECK: [[b:_.*]] = Lt(copy _1, const 13_i64); + // CHECK: opaque::(copy [[b]]) let b = x < 13; opaque(!!b); // This is `b`. // Both lines should test the same thing. - // CHECK: [[c:_.*]] = Ne(_1, const 15_i64); - // CHECK: opaque::([[c]]) - // CHECK: opaque::([[c]]) + // CHECK: [[c:_.*]] = Ne(copy _1, const 15_i64); + // CHECK: opaque::(copy [[c]]) + // CHECK: opaque::(copy [[c]]) opaque(x != 15); opaque(!(x == 15)); // Both lines should test the same thing. - // CHECK: [[d:_.*]] = Eq(_1, const 35_i64); - // CHECK: opaque::([[d]]) - // CHECK: opaque::([[d]]) + // CHECK: [[d:_.*]] = Eq(copy _1, const 35_i64); + // CHECK: opaque::(copy [[d]]) + // CHECK: opaque::(copy [[d]]) opaque(x == 35); opaque(!(x != 35)); } @@ -199,53 +198,53 @@ fn unary(x: i64) { /// Verify symbolic integer arithmetic simplifications. fn arithmetic(x: u64) { // CHECK-LABEL: fn arithmetic( - // CHECK: opaque::(_1) + // CHECK: opaque::(copy _1) opaque(x + 0); - // CHECK: opaque::(_1) + // CHECK: opaque::(copy _1) opaque(x - 0); // CHECK: opaque::(const 0_u64) opaque(x - x); // CHECK: opaque::(const 0_u64) opaque(x * 0); - // CHECK: opaque::(_1) + // CHECK: opaque::(copy _1) opaque(x * 1); // CHECK: assert(!const true, "attempt to divide `{}` by zero", - // CHECK: [[div0:_.*]] = Div(_1, const 0_u64); + // CHECK: [[div0:_.*]] = Div(copy _1, const 0_u64); // CHECK: opaque::(move [[div0]]) opaque(x / 0); - // CHECK: opaque::(_1) + // CHECK: opaque::(copy _1) opaque(x / 1); // CHECK: opaque::(const 0_u64) opaque(0 / x); - // CHECK: [[odiv:_.*]] = Div(const 1_u64, _1); + // CHECK: [[odiv:_.*]] = Div(const 1_u64, copy _1); // CHECK: opaque::(move [[odiv]]) opaque(1 / x); // CHECK: assert(!const true, "attempt to calculate the remainder of `{}` with a divisor of zero" - // CHECK: [[rem0:_.*]] = Rem(_1, const 0_u64); + // CHECK: [[rem0:_.*]] = Rem(copy _1, const 0_u64); // CHECK: opaque::(move [[rem0]]) opaque(x % 0); // CHECK: opaque::(const 0_u64) opaque(x % 1); // CHECK: opaque::(const 0_u64) opaque(0 % x); - // CHECK: [[orem:_.*]] = Rem(const 1_u64, _1); + // CHECK: [[orem:_.*]] = Rem(const 1_u64, copy _1); // CHECK: opaque::(move [[orem]]) opaque(1 % x); // CHECK: opaque::(const 0_u64) opaque(x & 0); - // CHECK: opaque::(_1) + // CHECK: opaque::(copy _1) opaque(x & u64::MAX); - // CHECK: opaque::(_1) + // CHECK: opaque::(copy _1) opaque(x | 0); // CHECK: opaque::(const u64::MAX) opaque(x | u64::MAX); - // CHECK: opaque::(_1) + // CHECK: opaque::(copy _1) opaque(x ^ 0); // CHECK: opaque::(const 0_u64) opaque(x ^ x); - // CHECK: opaque::(_1) + // CHECK: opaque::(copy _1) opaque(x >> 0); - // CHECK: opaque::(_1) + // CHECK: opaque::(copy _1) opaque(x << 0); } @@ -255,10 +254,10 @@ fn comparison(x: u64, y: u64) { opaque(x == x); // CHECK: opaque::(const false) opaque(x != x); - // CHECK: [[eqxy:_.*]] = Eq(_1, _2); + // CHECK: [[eqxy:_.*]] = Eq(copy _1, copy _2); // CHECK: opaque::(move [[eqxy]]) opaque(x == y); - // CHECK: [[nexy:_.*]] = Ne(_1, _2); + // CHECK: [[nexy:_.*]] = Ne(copy _1, copy _2); // CHECK: opaque::(move [[nexy]]) opaque(x != y); } @@ -268,10 +267,10 @@ fn comparison(x: u64, y: u64) { fn arithmetic_checked(x: u64) { // CHECK-LABEL: fn arithmetic_checked( // CHECK: assert(!const false, - // CHECK: opaque::(_1) + // CHECK: opaque::(copy _1) opaque(x + 0); // CHECK: assert(!const false, - // CHECK: opaque::(_1) + // CHECK: opaque::(copy _1) opaque(x - 0); // CHECK: assert(!const false, // CHECK: opaque::(const 0_u64) @@ -280,39 +279,39 @@ fn arithmetic_checked(x: u64) { // CHECK: opaque::(const 0_u64) opaque(x * 0); // CHECK: assert(!const false, - // CHECK: opaque::(_1) + // CHECK: opaque::(copy _1) opaque(x * 1); } /// Verify that we do not apply arithmetic simplifications on floats. fn arithmetic_float(x: f64) { // CHECK-LABEL: fn arithmetic_float( - // CHECK: [[add:_.*]] = Add(_1, const 0f64); + // CHECK: [[add:_.*]] = Add(copy _1, const 0f64); // CHECK: opaque::(move [[add]]) opaque(x + 0.); - // CHECK: [[sub:_.*]] = Sub(_1, const 0f64); + // CHECK: [[sub:_.*]] = Sub(copy _1, const 0f64); // CHECK: opaque::(move [[sub]]) opaque(x - 0.); - // CHECK: [[mul:_.*]] = Mul(_1, const 0f64); + // CHECK: [[mul:_.*]] = Mul(copy _1, const 0f64); // CHECK: opaque::(move [[mul]]) opaque(x * 0.); - // CHECK: [[div0:_.*]] = Div(_1, const 0f64); + // CHECK: [[div0:_.*]] = Div(copy _1, const 0f64); // CHECK: opaque::(move [[div0]]) opaque(x / 0.); - // CHECK: [[zdiv:_.*]] = Div(const 0f64, _1); + // CHECK: [[zdiv:_.*]] = Div(const 0f64, copy _1); // CHECK: opaque::(move [[zdiv]]) opaque(0. / x); - // CHECK: [[rem0:_.*]] = Rem(_1, const 0f64); + // CHECK: [[rem0:_.*]] = Rem(copy _1, const 0f64); // CHECK: opaque::(move [[rem0]]) opaque(x % 0.); - // CHECK: [[zrem:_.*]] = Rem(const 0f64, _1); + // CHECK: [[zrem:_.*]] = Rem(const 0f64, copy _1); // CHECK: opaque::(move [[zrem]]) opaque(0. % x); // Those are not simplifiable to `true`/`false`, thanks to NaNs. - // CHECK: [[eq:_.*]] = Eq(_1, _1); + // CHECK: [[eq:_.*]] = Eq(copy _1, copy _1); // CHECK: opaque::(move [[eq]]) opaque(x == x); - // CHECK: [[ne:_.*]] = Ne(_1, _1); + // CHECK: [[ne:_.*]] = Ne(copy _1, copy _1); // CHECK: opaque::(move [[ne]]) opaque(x != x); } @@ -386,36 +385,36 @@ fn cast() { fn multiple_branches(t: bool, x: u8, y: u8) { // CHECK-LABEL: fn multiple_branches( - // CHECK: switchInt(_1) -> [0: [[bbf:bb.*]], otherwise: [[bbt:bb.*]]]; + // CHECK: switchInt(copy _1) -> [0: [[bbf:bb.*]], otherwise: [[bbt:bb.*]]]; if t { // CHECK: [[bbt]]: { - // CHECK: [[a:_.*]] = Add(_2, _3); - // CHECK: opaque::([[a]]) - // CHECK: opaque::([[a]]) + // CHECK: [[a:_.*]] = Add(copy _2, copy _3); + // CHECK: opaque::(copy [[a]]) + // CHECK: opaque::(copy [[a]]) // CHECK: goto -> [[bbc:bb.*]]; opaque(x + y); opaque(x + y); } else { // CHECK: [[bbf]]: { - // CHECK: [[b:_.*]] = Add(_2, _3); - // CHECK: opaque::([[b]]) - // CHECK: opaque::([[b]]) + // CHECK: [[b:_.*]] = Add(copy _2, copy _3); + // CHECK: opaque::(copy [[b]]) + // CHECK: opaque::(copy [[b]]) // CHECK: goto -> [[bbc:bb.*]]; opaque(x + y); opaque(x + y); } // Neither `a` nor `b` dominate `c`, so we cannot reuse any of them. // CHECK: [[bbc]]: { - // CHECK: [[c:_.*]] = Add(_2, _3); - // CHECK: opaque::([[c]]) + // CHECK: [[c:_.*]] = Add(copy _2, copy _3); + // CHECK: opaque::(copy [[c]]) opaque(x + y); // `c` dominates both calls, so we can reuse it. if t { - // CHECK: opaque::([[c]]) + // CHECK: opaque::(copy [[c]]) opaque(x + y); } else { - // CHECK: opaque::([[c]]) + // CHECK: opaque::(copy [[c]]) opaque(x + y); } } @@ -469,18 +468,18 @@ fn dereferences(t: &mut u32, u: &impl Copy, s: &S) { // CHECK-LABEL: fn dereferences( // Do not reuse dereferences of `&mut`. - // CHECK: [[st1:_.*]] = (*_1); + // CHECK: [[st1:_.*]] = copy (*_1); // CHECK: opaque::(move [[st1]]) - // CHECK: [[st2:_.*]] = (*_1); + // CHECK: [[st2:_.*]] = copy (*_1); // CHECK: opaque::(move [[st2]]) opaque(*t); opaque(*t); // Do not reuse dereferences of `*const`. // CHECK: [[raw:_.*]] = &raw const (*_1); - // CHECK: [[st3:_.*]] = (*[[raw]]); + // CHECK: [[st3:_.*]] = copy (*[[raw]]); // CHECK: opaque::(move [[st3]]) - // CHECK: [[st4:_.*]] = (*[[raw]]); + // CHECK: [[st4:_.*]] = copy (*[[raw]]); // CHECK: opaque::(move [[st4]]) let z = &raw const *t; unsafe { opaque(*z) }; @@ -488,9 +487,9 @@ fn dereferences(t: &mut u32, u: &impl Copy, s: &S) { // Do not reuse dereferences of `*mut`. // CHECK: [[ptr:_.*]] = &raw mut (*_1); - // CHECK: [[st5:_.*]] = (*[[ptr]]); + // CHECK: [[st5:_.*]] = copy (*[[ptr]]); // CHECK: opaque::(move [[st5]]) - // CHECK: [[st6:_.*]] = (*[[ptr]]); + // CHECK: [[st6:_.*]] = copy (*[[ptr]]); // CHECK: opaque::(move [[st6]]) let z = &raw mut *t; unsafe { opaque(*z) }; @@ -498,9 +497,9 @@ fn dereferences(t: &mut u32, u: &impl Copy, s: &S) { // We can reuse dereferences of `&Freeze`. // CHECK: [[ref:_.*]] = &(*_1); - // CHECK: [[st7:_.*]] = (*[[ref]]); - // CHECK: opaque::([[st7]]) - // CHECK: opaque::([[st7]]) + // CHECK: [[st7:_.*]] = copy (*[[ref]]); + // CHECK: opaque::(copy [[st7]]) + // CHECK: opaque::(copy [[st7]]) let z = &*t; opaque(*z); opaque(*z); @@ -510,17 +509,17 @@ fn dereferences(t: &mut u32, u: &impl Copy, s: &S) { opaque(&*z); // `*u` is not Freeze, so we cannot reuse. - // CHECK: [[st8:_.*]] = (*_2); + // CHECK: [[st8:_.*]] = copy (*_2); // CHECK: opaque::(move [[st8]]) - // CHECK: [[st9:_.*]] = (*_2); + // CHECK: [[st9:_.*]] = copy (*_2); // CHECK: opaque::(move [[st9]]) opaque(*u); opaque(*u); - // `*s` is not Copy, by `(*s).0` is, so we can reuse. - // CHECK: [[st10:_.*]] = ((*_3).0: u32); - // CHECK: opaque::([[st10]]) - // CHECK: opaque::([[st10]]) + // `*s` is not Copy, but `(*s).0` is, so we can reuse. + // CHECK: [[st10:_.*]] = copy ((*_3).0: u32); + // CHECK: opaque::(copy [[st10]]) + // CHECK: opaque::(copy [[st10]]) opaque(s.0); opaque(s.0); } @@ -551,38 +550,38 @@ fn duplicate_slice() -> (bool, bool) { let d: &str; { // CHECK: [[a:_.*]] = (const "a",); - // CHECK: [[au:_.*]] = ([[a]].0: &str) as u128 (Transmute); + // CHECK: [[au:_.*]] = copy ([[a]].0: &str) as u128 (Transmute); let a = ("a",); Call(au = transmute::<_, u128>(a.0), ReturnTo(bb1), UnwindContinue()) } bb1 = { - // CHECK: [[c:_.*]] = identity::<&str>(([[a]].0: &str)) + // CHECK: [[c:_.*]] = identity::<&str>(copy ([[a]].0: &str)) Call(c = identity(a.0), ReturnTo(bb2), UnwindContinue()) } bb2 = { - // CHECK: [[cu:_.*]] = [[c]] as u128 (Transmute); + // CHECK: [[cu:_.*]] = copy [[c]] as u128 (Transmute); Call(cu = transmute::<_, u128>(c), ReturnTo(bb3), UnwindContinue()) } bb3 = { // This slice is different from `a.0`. Hence `bu` is not `au`. // CHECK: [[b:_.*]] = const "a"; - // CHECK: [[bu:_.*]] = [[b]] as u128 (Transmute); + // CHECK: [[bu:_.*]] = copy [[b]] as u128 (Transmute); let b = "a"; Call(bu = transmute::<_, u128>(b), ReturnTo(bb4), UnwindContinue()) } bb4 = { // This returns a copy of `b`, which is not `a`. - // CHECK: [[d:_.*]] = identity::<&str>([[b]]) + // CHECK: [[d:_.*]] = identity::<&str>(copy [[b]]) Call(d = identity(b), ReturnTo(bb5), UnwindContinue()) } bb5 = { - // CHECK: [[du:_.*]] = [[d]] as u128 (Transmute); + // CHECK: [[du:_.*]] = copy [[d]] as u128 (Transmute); Call(du = transmute::<_, u128>(d), ReturnTo(bb6), UnwindContinue()) } bb6 = { // `direct` must not fold to `true`, as `indirect` will not. - // CHECK: = Eq([[au]], [[bu]]); - // CHECK: = Eq([[cu]], [[du]]); + // CHECK: = Eq(copy [[au]], copy [[bu]]); + // CHECK: = Eq(copy [[cu]], copy [[du]]); let direct = au == bu; let indirect = cu == du; RET = (direct, indirect); @@ -602,21 +601,21 @@ fn repeat() { fn fn_pointers() { // CHECK-LABEL: fn fn_pointers( // CHECK: [[f:_.*]] = identity:: as fn(u8) -> u8 (PointerCoercion(ReifyFnPointer - // CHECK: opaque:: u8>([[f]]) + // CHECK: opaque:: u8>(copy [[f]]) let f = identity as fn(u8) -> u8; opaque(f); // CHECK: [[g:_.*]] = identity:: as fn(u8) -> u8 (PointerCoercion(ReifyFnPointer - // CHECK: opaque:: u8>([[g]]) + // CHECK: opaque:: u8>(copy [[g]]) let g = identity as fn(u8) -> u8; opaque(g); // CHECK: [[cf:_.*]] = const {{.*}} as fn() (PointerCoercion(ClosureFnPointer - // CHECK: opaque::([[cf]]) + // CHECK: opaque::(copy [[cf]]) let closure = || {}; let cf = closure as fn(); opaque(cf); // CHECK: [[cg:_.*]] = const {{.*}} as fn() (PointerCoercion(ClosureFnPointer - // CHECK: opaque::([[cg]]) + // CHECK: opaque::(copy [[cg]]) let cg = closure as fn(); opaque(cg); } @@ -642,9 +641,9 @@ fn constant_index_overflow(x: &[T]) { // CHECK: debug b => [[b:_.*]]; // CHECK: [[a]] = const usize::MAX; // CHECK-NOT: = (*_1)[{{.*}} of 0]; - // CHECK: [[b]] = (*_1)[[[a]]]; + // CHECK: [[b]] = copy (*_1)[[[a]]]; // CHECK-NOT: = (*_1)[{{.*}} of 0]; - // CHECK: [[b]] = (*_1)[0 of 1]; + // CHECK: [[b]] = copy (*_1)[0 of 1]; // CHECK-NOT: = (*_1)[{{.*}} of 0]; let a = u64::MAX as usize; let b = if a < x.len() { x[a] } else { x[0] }; @@ -657,22 +656,22 @@ fn wide_ptr_provenance() { let a: *const dyn Send = &1 as &dyn Send; let b: *const dyn Send = &1 as &dyn Send; - // CHECK: [[eqp:_.*]] = Eq([[a:_.*]], [[b:_.*]]); + // CHECK: [[eqp:_.*]] = Eq(copy [[a:_.*]], copy [[b:_.*]]); // CHECK: opaque::(move [[eqp]]) opaque(a == b); - // CHECK: [[nep:_.*]] = Ne([[a]], [[b]]); + // CHECK: [[nep:_.*]] = Ne(copy [[a]], copy [[b]]); // CHECK: opaque::(move [[nep]]) opaque(a != b); - // CHECK: [[ltp:_.*]] = Lt([[a]], [[b]]); + // CHECK: [[ltp:_.*]] = Lt(copy [[a]], copy [[b]]); // CHECK: opaque::(move [[ltp]]) opaque(a < b); - // CHECK: [[lep:_.*]] = Le([[a]], [[b]]); + // CHECK: [[lep:_.*]] = Le(copy [[a]], copy [[b]]); // CHECK: opaque::(move [[lep]]) opaque(a <= b); - // CHECK: [[gtp:_.*]] = Gt([[a]], [[b]]); + // CHECK: [[gtp:_.*]] = Gt(copy [[a]], copy [[b]]); // CHECK: opaque::(move [[gtp]]) opaque(a > b); - // CHECK: [[gep:_.*]] = Ge([[a]], [[b]]); + // CHECK: [[gep:_.*]] = Ge(copy [[a]], copy [[b]]); // CHECK: opaque::(move [[gep]]) opaque(a >= b); } @@ -684,22 +683,22 @@ fn wide_ptr_same_provenance() { let a: *const dyn Send = &slice[0] as &dyn Send; let b: *const dyn Send = &slice[1] as &dyn Send; - // CHECK: [[eqp:_.*]] = Eq([[a:_.*]], [[b:_.*]]); + // CHECK: [[eqp:_.*]] = Eq(copy [[a:_.*]], copy [[b:_.*]]); // CHECK: opaque::(move [[eqp]]) opaque(a == b); - // CHECK: [[nep:_.*]] = Ne([[a]], [[b]]); + // CHECK: [[nep:_.*]] = Ne(copy [[a]], copy [[b]]); // CHECK: opaque::(move [[nep]]) opaque(a != b); - // CHECK: [[ltp:_.*]] = Lt([[a]], [[b]]); + // CHECK: [[ltp:_.*]] = Lt(copy [[a]], copy [[b]]); // CHECK: opaque::(move [[ltp]]) opaque(a < b); - // CHECK: [[lep:_.*]] = Le([[a]], [[b]]); + // CHECK: [[lep:_.*]] = Le(copy [[a]], copy [[b]]); // CHECK: opaque::(move [[lep]]) opaque(a <= b); - // CHECK: [[gtp:_.*]] = Gt([[a]], [[b]]); + // CHECK: [[gtp:_.*]] = Gt(copy [[a]], copy [[b]]); // CHECK: opaque::(move [[gtp]]) opaque(a > b); - // CHECK: [[gep:_.*]] = Ge([[a]], [[b]]); + // CHECK: [[gep:_.*]] = Ge(copy [[a]], copy [[b]]); // CHECK: opaque::(move [[gep]]) opaque(a >= b); } @@ -731,13 +730,13 @@ fn wide_ptr_integer() { fn borrowed(x: T) { // CHECK-LABEL: fn borrowed( // CHECK: bb0: { - // CHECK-NEXT: _2 = _1; + // CHECK-NEXT: _2 = copy _1; // CHECK-NEXT: _3 = &_1; - // CHECK-NEXT: _0 = opaque::<&T>(_3) + // CHECK-NEXT: _0 = opaque::<&T>(copy _3) // CHECK: bb1: { - // CHECK-NEXT: _0 = opaque::(_1) + // CHECK-NEXT: _0 = opaque::(copy _1) // CHECK: bb2: { - // CHECK-NEXT: _0 = opaque::(_1) + // CHECK-NEXT: _0 = opaque::(copy _1) mir! { { let a = x; @@ -761,13 +760,13 @@ fn borrowed(x: T) { fn non_freeze(x: T) { // CHECK-LABEL: fn non_freeze( // CHECK: bb0: { - // CHECK-NEXT: _2 = _1; + // CHECK-NEXT: _2 = copy _1; // CHECK-NEXT: _3 = &_1; - // CHECK-NEXT: _0 = opaque::<&T>(_3) + // CHECK-NEXT: _0 = opaque::<&T>(copy _3) // CHECK: bb1: { - // CHECK-NEXT: _0 = opaque::(_2) + // CHECK-NEXT: _0 = opaque::(copy _2) // CHECK: bb2: { - // CHECK-NEXT: _0 = opaque::((*_3)) + // CHECK-NEXT: _0 = opaque::(copy (*_3)) mir! { { let a = x; @@ -789,7 +788,7 @@ fn non_freeze(x: T) { // Check that we can const-prop into `from_raw_parts` fn slice_const_length(x: &[i32]) -> *const [i32] { // CHECK-LABEL: fn slice_const_length( - // CHECK: _0 = *const [i32] from ({{_[0-9]+}}, const 123_usize); + // CHECK: _0 = *const [i32] from (copy {{_[0-9]+}}, const 123_usize); let ptr = x.as_ptr(); let len = 123; std::intrinsics::aggregate_raw_ptr(ptr, len) @@ -804,15 +803,15 @@ fn meta_of_ref_to_slice(x: *const i32) -> usize { fn slice_from_raw_parts_as_ptr(x: *const u16, n: usize) -> (*const u16, *const f32) { // CHECK-LABEL: fn slice_from_raw_parts_as_ptr - // CHECK: _8 = _1 as *const f32 (PtrToPtr); - // CHECK: _0 = (_1, move _8); + // CHECK: _8 = copy _1 as *const f32 (PtrToPtr); + // CHECK: _0 = (copy _1, move _8); let ptr: *const [u16] = std::intrinsics::aggregate_raw_ptr(x, n); (ptr as *const u16, ptr as *const f32) } fn casts_before_aggregate_raw_ptr(x: *const u32) -> *const [u8] { // CHECK-LABEL: fn casts_before_aggregate_raw_ptr - // CHECK: _0 = *const [u8] from (_1, const 4_usize); + // CHECK: _0 = *const [u8] from (copy _1, const 4_usize); let x = x as *const [u8; 4]; let x = x as *const u8; let x = x as *const (); @@ -821,7 +820,7 @@ fn casts_before_aggregate_raw_ptr(x: *const u32) -> *const [u8] { fn manual_slice_mut_len(x: &mut [i32]) -> usize { // CHECK-LABEL: fn manual_slice_mut_len - // CHECK: _0 = PtrMetadata(_1); + // CHECK: _0 = PtrMetadata(copy _1); let x: *mut [i32] = x; let x: *const [i32] = x; std::intrinsics::ptr_metadata(x) @@ -844,38 +843,38 @@ fn generic_cast_metadata(ps: *const [T], pa: *const A, // when the pointee metadata do or don't match, respectively. // Metadata usize -> (), do not optimize. - // CHECK: [[T:_.+]] = _1 as - // CHECK-NEXT: PtrMetadata([[T]]) + // CHECK: [[T:_.+]] = copy _1 as + // CHECK-NEXT: PtrMetadata(copy [[T]]) let t1 = CastPtrToPtr::<_, *const T>(ps); let m1 = PtrMetadata(t1); // `(&A, [T])` has `usize` metadata, same as `[T]`, yes optimize. - // CHECK: [[T:_.+]] = _1 as - // CHECK-NEXT: PtrMetadata(_1) + // CHECK: [[T:_.+]] = copy _1 as + // CHECK-NEXT: PtrMetadata(copy _1) let t2 = CastPtrToPtr::<_, *const (&A, [T])>(ps); let m2 = PtrMetadata(t2); // Tail `A` and tail `B`, do not optimize. - // CHECK: [[T:_.+]] = _2 as - // CHECK-NEXT: PtrMetadata([[T]]) + // CHECK: [[T:_.+]] = copy _2 as + // CHECK-NEXT: PtrMetadata(copy [[T]]) let t3 = CastPtrToPtr::<_, *const (T, B)>(pa); let m3 = PtrMetadata(t3); // Both have tail `A`, yes optimize. - // CHECK: [[T:_.+]] = _2 as - // CHECK-NEXT: PtrMetadata(_2) + // CHECK: [[T:_.+]] = copy _2 as + // CHECK-NEXT: PtrMetadata(copy _2) let t4 = CastPtrToPtr::<_, *const (T, A)>(pa); let m4 = PtrMetadata(t4); // Tail `B` and tail `A`, do not optimize. - // CHECK: [[T:_.+]] = _3 as - // CHECK-NEXT: PtrMetadata([[T]]) + // CHECK: [[T:_.+]] = copy _3 as + // CHECK-NEXT: PtrMetadata(copy [[T]]) let t5 = CastPtrToPtr::<_, *mut A>(pb); let m5 = PtrMetadata(t5); // Both have tail `B`, yes optimize. - // CHECK: [[T:_.+]] = _3 as - // CHECK-NEXT: PtrMetadata(_3) + // CHECK: [[T:_.+]] = copy _3 as + // CHECK-NEXT: PtrMetadata(copy _3) let t6 = CastPtrToPtr::<_, *mut B>(pb); let m6 = PtrMetadata(t6); @@ -891,21 +890,21 @@ fn cast_pointer_eq(p1: *mut u8, p2: *mut u32, p3: *mut u32, p4: *mut [u32]) { // CHECK: debug p3 => [[P3:_3]]; // CHECK: debug p4 => [[P4:_4]]; - // CHECK: [[M1:_.+]] = [[P1]] as *const u32 (PtrToPtr); - // CHECK: [[M2:_.+]] = [[P2]] as *const u32 (PtrToPtr); - // CHECK: [[M3:_.+]] = [[P3]] as *const u32 (PtrToPtr); - // CHECK: [[M4:_.+]] = [[P4]] as *const u32 (PtrToPtr); + // CHECK: [[M1:_.+]] = copy [[P1]] as *const u32 (PtrToPtr); + // CHECK: [[M2:_.+]] = copy [[P2]] as *const u32 (PtrToPtr); + // CHECK: [[M3:_.+]] = copy [[P3]] as *const u32 (PtrToPtr); + // CHECK: [[M4:_.+]] = copy [[P4]] as *const u32 (PtrToPtr); let m1 = p1 as *const u32; let m2 = p2 as *const u32; let m3 = p3 as *const u32; let m4 = p4 as *const u32; // CHECK-NOT: Eq - // CHECK: Eq([[M1]], [[M2]]) + // CHECK: Eq(copy [[M1]], copy [[M2]]) // CHECK-NOT: Eq - // CHECK: Eq([[P2]], [[P3]]) + // CHECK: Eq(copy [[P2]], copy [[P3]]) // CHECK-NOT: Eq - // CHECK: Eq([[M3]], [[M4]]) + // CHECK: Eq(copy [[M3]], copy [[M4]]) // CHECK-NOT: Eq let eq_different_thing = m1 == m2; let eq_optimize = m2 == m3; @@ -918,11 +917,11 @@ fn cast_pointer_eq(p1: *mut u8, p2: *mut u32, p3: *mut u32, p4: *mut [u32]) { unsafe fn cast_pointer_then_transmute(thin: *mut u32, fat: *mut [u8]) { // CHECK-LABEL: fn cast_pointer_then_transmute - // CHECK: [[UNUSED:_.+]] = _1 as *const () (PtrToPtr); - // CHECK: = _1 as usize (Transmute); + // CHECK: [[UNUSED:_.+]] = copy _1 as *const () (PtrToPtr); + // CHECK: = copy _1 as usize (Transmute); let thin_addr: usize = std::intrinsics::transmute(thin as *const ()); - // CHECK: [[TEMP2:_.+]] = _2 as *const () (PtrToPtr); + // CHECK: [[TEMP2:_.+]] = copy _2 as *const () (PtrToPtr); // CHECK: = move [[TEMP2]] as usize (Transmute); let fat_addr: usize = std::intrinsics::transmute(fat as *const ()); } @@ -935,11 +934,11 @@ fn remove_casts_must_change_both_sides(mut_a: &*mut u8, mut_b: *mut u8) -> bool // to be locals, so make sure we don't change one without the other, as // that would be a type error. { - // CHECK: [[A:_.+]] = (*_1) as *const u8 (PtrToPtr); + // CHECK: [[A:_.+]] = copy (*_1) as *const u8 (PtrToPtr); let a = *mut_a as *const u8; - // CHECK: [[B:_.+]] = _2 as *const u8 (PtrToPtr); + // CHECK: [[B:_.+]] = copy _2 as *const u8 (PtrToPtr); let b = mut_b as *const u8; - // CHECK: _0 = Eq([[A]], [[B]]); + // CHECK: _0 = Eq(copy [[A]], copy [[B]]); RET = a == b; Return() } diff --git a/tests/mir-opt/gvn.slice_const_length.GVN.panic-abort.diff b/tests/mir-opt/gvn.slice_const_length.GVN.panic-abort.diff index fd5fa035d81..1a6204e4ac8 100644 --- a/tests/mir-opt/gvn.slice_const_length.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.slice_const_length.GVN.panic-abort.diff @@ -30,12 +30,12 @@ + nop; _4 = const 123_usize; StorageLive(_5); - _5 = _2; + _5 = copy _2; StorageLive(_6); -- _6 = _4; +- _6 = copy _4; - _0 = *const [i32] from (move _5, move _6); + _6 = const 123_usize; -+ _0 = *const [i32] from (_2, const 123_usize); ++ _0 = *const [i32] from (copy _2, const 123_usize); StorageDead(_6); StorageDead(_5); - StorageDead(_4); diff --git a/tests/mir-opt/gvn.slice_const_length.GVN.panic-unwind.diff b/tests/mir-opt/gvn.slice_const_length.GVN.panic-unwind.diff index 98945cf9724..62d57b0fe28 100644 --- a/tests/mir-opt/gvn.slice_const_length.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.slice_const_length.GVN.panic-unwind.diff @@ -30,12 +30,12 @@ + nop; _4 = const 123_usize; StorageLive(_5); - _5 = _2; + _5 = copy _2; StorageLive(_6); -- _6 = _4; +- _6 = copy _4; - _0 = *const [i32] from (move _5, move _6); + _6 = const 123_usize; -+ _0 = *const [i32] from (_2, const 123_usize); ++ _0 = *const [i32] from (copy _2, const 123_usize); StorageDead(_6); StorageDead(_5); - StorageDead(_4); diff --git a/tests/mir-opt/gvn.slice_from_raw_parts_as_ptr.GVN.panic-abort.diff b/tests/mir-opt/gvn.slice_from_raw_parts_as_ptr.GVN.panic-abort.diff index 75bcd2a8d72..4a2cc251891 100644 --- a/tests/mir-opt/gvn.slice_from_raw_parts_as_ptr.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.slice_from_raw_parts_as_ptr.GVN.panic-abort.diff @@ -20,27 +20,27 @@ - StorageLive(_3); + nop; StorageLive(_4); - _4 = _1; + _4 = copy _1; StorageLive(_5); - _5 = _2; + _5 = copy _2; - _3 = *const [u16] from (move _4, move _5); -+ _3 = *const [u16] from (_1, _2); ++ _3 = *const [u16] from (copy _1, copy _2); StorageDead(_5); StorageDead(_4); StorageLive(_6); StorageLive(_7); - _7 = _3; + _7 = copy _3; - _6 = move _7 as *const u16 (PtrToPtr); -+ _6 = _1; ++ _6 = copy _1; StorageDead(_7); StorageLive(_8); StorageLive(_9); - _9 = _3; + _9 = copy _3; - _8 = move _9 as *const f32 (PtrToPtr); -+ _8 = _1 as *const f32 (PtrToPtr); ++ _8 = copy _1 as *const f32 (PtrToPtr); StorageDead(_9); - _0 = (move _6, move _8); -+ _0 = (_1, move _8); ++ _0 = (copy _1, move _8); StorageDead(_8); StorageDead(_6); - StorageDead(_3); diff --git a/tests/mir-opt/gvn.slice_from_raw_parts_as_ptr.GVN.panic-unwind.diff b/tests/mir-opt/gvn.slice_from_raw_parts_as_ptr.GVN.panic-unwind.diff index 75bcd2a8d72..4a2cc251891 100644 --- a/tests/mir-opt/gvn.slice_from_raw_parts_as_ptr.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.slice_from_raw_parts_as_ptr.GVN.panic-unwind.diff @@ -20,27 +20,27 @@ - StorageLive(_3); + nop; StorageLive(_4); - _4 = _1; + _4 = copy _1; StorageLive(_5); - _5 = _2; + _5 = copy _2; - _3 = *const [u16] from (move _4, move _5); -+ _3 = *const [u16] from (_1, _2); ++ _3 = *const [u16] from (copy _1, copy _2); StorageDead(_5); StorageDead(_4); StorageLive(_6); StorageLive(_7); - _7 = _3; + _7 = copy _3; - _6 = move _7 as *const u16 (PtrToPtr); -+ _6 = _1; ++ _6 = copy _1; StorageDead(_7); StorageLive(_8); StorageLive(_9); - _9 = _3; + _9 = copy _3; - _8 = move _9 as *const f32 (PtrToPtr); -+ _8 = _1 as *const f32 (PtrToPtr); ++ _8 = copy _1 as *const f32 (PtrToPtr); StorageDead(_9); - _0 = (move _6, move _8); -+ _0 = (_1, move _8); ++ _0 = (copy _1, move _8); StorageDead(_8); StorageDead(_6); - StorageDead(_3); diff --git a/tests/mir-opt/gvn.slices.GVN.panic-abort.diff b/tests/mir-opt/gvn.slices.GVN.panic-abort.diff index fb67e3d5994..e8e99b44e72 100644 --- a/tests/mir-opt/gvn.slices.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.slices.GVN.panic-abort.diff @@ -87,22 +87,22 @@ _1 = const "my favourite slice"; StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; - _2 = opaque::<&str>(move _3) -> [return: bb1, unwind unreachable]; -+ _2 = opaque::<&str>(_1) -> [return: bb1, unwind unreachable]; ++ _2 = opaque::<&str>(copy _1) -> [return: bb1, unwind unreachable]; } bb1: { StorageDead(_3); StorageDead(_2); StorageLive(_4); - _4 = _1; + _4 = copy _1; StorageLive(_5); StorageLive(_6); -- _6 = _4; +- _6 = copy _4; - _5 = opaque::<&str>(move _6) -> [return: bb2, unwind unreachable]; -+ _6 = _1; -+ _5 = opaque::<&str>(_1) -> [return: bb2, unwind unreachable]; ++ _6 = copy _1; ++ _5 = opaque::<&str>(copy _1) -> [return: bb2, unwind unreachable]; } bb2: { @@ -138,24 +138,24 @@ - _8 = (move _9, move _12); - StorageDead(_12); - StorageDead(_9); -+ _8 = (_9, _12); ++ _8 = (copy _9, copy _12); + nop; + nop; StorageLive(_15); -- _15 = (_8.0: &*const u8); -+ _15 = _9; +- _15 = copy (_8.0: &*const u8); ++ _15 = copy _9; StorageLive(_16); -- _16 = (_8.1: &*const u8); -+ _16 = _12; +- _16 = copy (_8.1: &*const u8); ++ _16 = copy _12; StorageLive(_17); StorageLive(_18); -- _18 = (*_15); -+ _18 = _10; +- _18 = copy (*_15); ++ _18 = copy _10; StorageLive(_19); -- _19 = (*_16); +- _19 = copy (*_16); - _17 = Eq(move _18, move _19); -+ _19 = _13; -+ _17 = Eq(_10, _13); ++ _19 = copy _13; ++ _17 = Eq(copy _10, copy _13); switchInt(move _17) -> [0: bb6, otherwise: bb5]; } @@ -180,9 +180,9 @@ StorageDead(_30); StorageLive(_31); StorageLive(_32); - _32 = _29; + _32 = copy _29; - _31 = opaque::<&[u8]>(move _32) -> [return: bb7, unwind unreachable]; -+ _31 = opaque::<&[u8]>(_29) -> [return: bb7, unwind unreachable]; ++ _31 = opaque::<&[u8]>(copy _29) -> [return: bb7, unwind unreachable]; } bb6: { @@ -244,24 +244,24 @@ - _34 = (move _35, move _38); - StorageDead(_38); - StorageDead(_35); -+ _34 = (_35, _38); ++ _34 = (copy _35, copy _38); + nop; + nop; StorageLive(_41); -- _41 = (_34.0: &*const u8); -+ _41 = _35; +- _41 = copy (_34.0: &*const u8); ++ _41 = copy _35; StorageLive(_42); -- _42 = (_34.1: &*const u8); -+ _42 = _38; +- _42 = copy (_34.1: &*const u8); ++ _42 = copy _38; StorageLive(_43); StorageLive(_44); -- _44 = (*_41); -+ _44 = _36; +- _44 = copy (*_41); ++ _44 = copy _36; StorageLive(_45); -- _45 = (*_42); +- _45 = copy (*_42); - _43 = Eq(move _44, move _45); -+ _45 = _39; -+ _43 = Eq(_36, _39); ++ _45 = copy _39; ++ _43 = Eq(copy _36, copy _39); switchInt(move _43) -> [0: bb11, otherwise: bb10]; } diff --git a/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff b/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff index ae3013b011e..4296d4d4a59 100644 --- a/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff @@ -87,22 +87,22 @@ _1 = const "my favourite slice"; StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; - _2 = opaque::<&str>(move _3) -> [return: bb1, unwind continue]; -+ _2 = opaque::<&str>(_1) -> [return: bb1, unwind continue]; ++ _2 = opaque::<&str>(copy _1) -> [return: bb1, unwind continue]; } bb1: { StorageDead(_3); StorageDead(_2); StorageLive(_4); - _4 = _1; + _4 = copy _1; StorageLive(_5); StorageLive(_6); -- _6 = _4; +- _6 = copy _4; - _5 = opaque::<&str>(move _6) -> [return: bb2, unwind continue]; -+ _6 = _1; -+ _5 = opaque::<&str>(_1) -> [return: bb2, unwind continue]; ++ _6 = copy _1; ++ _5 = opaque::<&str>(copy _1) -> [return: bb2, unwind continue]; } bb2: { @@ -138,24 +138,24 @@ - _8 = (move _9, move _12); - StorageDead(_12); - StorageDead(_9); -+ _8 = (_9, _12); ++ _8 = (copy _9, copy _12); + nop; + nop; StorageLive(_15); -- _15 = (_8.0: &*const u8); -+ _15 = _9; +- _15 = copy (_8.0: &*const u8); ++ _15 = copy _9; StorageLive(_16); -- _16 = (_8.1: &*const u8); -+ _16 = _12; +- _16 = copy (_8.1: &*const u8); ++ _16 = copy _12; StorageLive(_17); StorageLive(_18); -- _18 = (*_15); -+ _18 = _10; +- _18 = copy (*_15); ++ _18 = copy _10; StorageLive(_19); -- _19 = (*_16); +- _19 = copy (*_16); - _17 = Eq(move _18, move _19); -+ _19 = _13; -+ _17 = Eq(_10, _13); ++ _19 = copy _13; ++ _17 = Eq(copy _10, copy _13); switchInt(move _17) -> [0: bb6, otherwise: bb5]; } @@ -180,9 +180,9 @@ StorageDead(_30); StorageLive(_31); StorageLive(_32); - _32 = _29; + _32 = copy _29; - _31 = opaque::<&[u8]>(move _32) -> [return: bb7, unwind continue]; -+ _31 = opaque::<&[u8]>(_29) -> [return: bb7, unwind continue]; ++ _31 = opaque::<&[u8]>(copy _29) -> [return: bb7, unwind continue]; } bb6: { @@ -244,24 +244,24 @@ - _34 = (move _35, move _38); - StorageDead(_38); - StorageDead(_35); -+ _34 = (_35, _38); ++ _34 = (copy _35, copy _38); + nop; + nop; StorageLive(_41); -- _41 = (_34.0: &*const u8); -+ _41 = _35; +- _41 = copy (_34.0: &*const u8); ++ _41 = copy _35; StorageLive(_42); -- _42 = (_34.1: &*const u8); -+ _42 = _38; +- _42 = copy (_34.1: &*const u8); ++ _42 = copy _38; StorageLive(_43); StorageLive(_44); -- _44 = (*_41); -+ _44 = _36; +- _44 = copy (*_41); ++ _44 = copy _36; StorageLive(_45); -- _45 = (*_42); +- _45 = copy (*_42); - _43 = Eq(move _44, move _45); -+ _45 = _39; -+ _43 = Eq(_36, _39); ++ _45 = copy _39; ++ _43 = Eq(copy _36, copy _39); switchInt(move _43) -> [0: bb11, otherwise: bb10]; } diff --git a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff index ba9e507560d..7a479bc55da 100644 --- a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff @@ -195,15 +195,15 @@ - StorageLive(_5); + nop; StorageLive(_6); - _6 = _1; + _6 = copy _1; StorageLive(_7); - _7 = _2; + _7 = copy _2; - _5 = Add(move _6, move _7); -+ _5 = Add(_1, _2); ++ _5 = Add(copy _1, copy _2); StorageDead(_7); StorageDead(_6); - _4 = opaque::(move _5) -> [return: bb1, unwind unreachable]; -+ _4 = opaque::(_5) -> [return: bb1, unwind unreachable]; ++ _4 = opaque::(copy _5) -> [return: bb1, unwind unreachable]; } bb1: { @@ -214,15 +214,15 @@ - StorageLive(_9); + nop; StorageLive(_10); - _10 = _1; + _10 = copy _1; StorageLive(_11); - _11 = _2; + _11 = copy _2; - _9 = Mul(move _10, move _11); -+ _9 = Mul(_1, _2); ++ _9 = Mul(copy _1, copy _2); StorageDead(_11); StorageDead(_10); - _8 = opaque::(move _9) -> [return: bb2, unwind unreachable]; -+ _8 = opaque::(_9) -> [return: bb2, unwind unreachable]; ++ _8 = opaque::(copy _9) -> [return: bb2, unwind unreachable]; } bb2: { @@ -233,15 +233,15 @@ - StorageLive(_13); + nop; StorageLive(_14); - _14 = _1; + _14 = copy _1; StorageLive(_15); - _15 = _2; + _15 = copy _2; - _13 = Sub(move _14, move _15); -+ _13 = Sub(_1, _2); ++ _13 = Sub(copy _1, copy _2); StorageDead(_15); StorageDead(_14); - _12 = opaque::(move _13) -> [return: bb3, unwind unreachable]; -+ _12 = opaque::(_13) -> [return: bb3, unwind unreachable]; ++ _12 = opaque::(copy _13) -> [return: bb3, unwind unreachable]; } bb3: { @@ -252,22 +252,22 @@ - StorageLive(_17); + nop; StorageLive(_18); - _18 = _1; + _18 = copy _1; StorageLive(_19); - _19 = _2; -- _20 = Eq(_19, const 0_u64); -- assert(!move _20, "attempt to divide `{}` by zero", _18) -> [success: bb4, unwind unreachable]; -+ _20 = Eq(_2, const 0_u64); -+ assert(!_20, "attempt to divide `{}` by zero", _1) -> [success: bb4, unwind unreachable]; + _19 = copy _2; +- _20 = Eq(copy _19, const 0_u64); +- assert(!move _20, "attempt to divide `{}` by zero", copy _18) -> [success: bb4, unwind unreachable]; ++ _20 = Eq(copy _2, const 0_u64); ++ assert(!copy _20, "attempt to divide `{}` by zero", copy _1) -> [success: bb4, unwind unreachable]; } bb4: { - _17 = Div(move _18, move _19); -+ _17 = Div(_1, _2); ++ _17 = Div(copy _1, copy _2); StorageDead(_19); StorageDead(_18); - _16 = opaque::(move _17) -> [return: bb5, unwind unreachable]; -+ _16 = opaque::(_17) -> [return: bb5, unwind unreachable]; ++ _16 = opaque::(copy _17) -> [return: bb5, unwind unreachable]; } bb5: { @@ -278,22 +278,22 @@ - StorageLive(_22); + nop; StorageLive(_23); - _23 = _1; + _23 = copy _1; StorageLive(_24); - _24 = _2; -- _25 = Eq(_24, const 0_u64); -- assert(!move _25, "attempt to calculate the remainder of `{}` with a divisor of zero", _23) -> [success: bb6, unwind unreachable]; -+ _25 = _20; -+ assert(!_20, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb6, unwind unreachable]; + _24 = copy _2; +- _25 = Eq(copy _24, const 0_u64); +- assert(!move _25, "attempt to calculate the remainder of `{}` with a divisor of zero", copy _23) -> [success: bb6, unwind unreachable]; ++ _25 = copy _20; ++ assert(!copy _20, "attempt to calculate the remainder of `{}` with a divisor of zero", copy _1) -> [success: bb6, unwind unreachable]; } bb6: { - _22 = Rem(move _23, move _24); -+ _22 = Rem(_1, _2); ++ _22 = Rem(copy _1, copy _2); StorageDead(_24); StorageDead(_23); - _21 = opaque::(move _22) -> [return: bb7, unwind unreachable]; -+ _21 = opaque::(_22) -> [return: bb7, unwind unreachable]; ++ _21 = opaque::(copy _22) -> [return: bb7, unwind unreachable]; } bb7: { @@ -304,15 +304,15 @@ - StorageLive(_27); + nop; StorageLive(_28); - _28 = _1; + _28 = copy _1; StorageLive(_29); - _29 = _2; + _29 = copy _2; - _27 = BitAnd(move _28, move _29); -+ _27 = BitAnd(_1, _2); ++ _27 = BitAnd(copy _1, copy _2); StorageDead(_29); StorageDead(_28); - _26 = opaque::(move _27) -> [return: bb8, unwind unreachable]; -+ _26 = opaque::(_27) -> [return: bb8, unwind unreachable]; ++ _26 = opaque::(copy _27) -> [return: bb8, unwind unreachable]; } bb8: { @@ -323,15 +323,15 @@ - StorageLive(_31); + nop; StorageLive(_32); - _32 = _1; + _32 = copy _1; StorageLive(_33); - _33 = _2; + _33 = copy _2; - _31 = BitOr(move _32, move _33); -+ _31 = BitOr(_1, _2); ++ _31 = BitOr(copy _1, copy _2); StorageDead(_33); StorageDead(_32); - _30 = opaque::(move _31) -> [return: bb9, unwind unreachable]; -+ _30 = opaque::(_31) -> [return: bb9, unwind unreachable]; ++ _30 = opaque::(copy _31) -> [return: bb9, unwind unreachable]; } bb9: { @@ -342,15 +342,15 @@ - StorageLive(_35); + nop; StorageLive(_36); - _36 = _1; + _36 = copy _1; StorageLive(_37); - _37 = _2; + _37 = copy _2; - _35 = BitXor(move _36, move _37); -+ _35 = BitXor(_1, _2); ++ _35 = BitXor(copy _1, copy _2); StorageDead(_37); StorageDead(_36); - _34 = opaque::(move _35) -> [return: bb10, unwind unreachable]; -+ _34 = opaque::(_35) -> [return: bb10, unwind unreachable]; ++ _34 = opaque::(copy _35) -> [return: bb10, unwind unreachable]; } bb10: { @@ -361,15 +361,15 @@ - StorageLive(_39); + nop; StorageLive(_40); - _40 = _1; + _40 = copy _1; StorageLive(_41); - _41 = _2; + _41 = copy _2; - _39 = Shl(move _40, move _41); -+ _39 = Shl(_1, _2); ++ _39 = Shl(copy _1, copy _2); StorageDead(_41); StorageDead(_40); - _38 = opaque::(move _39) -> [return: bb11, unwind unreachable]; -+ _38 = opaque::(_39) -> [return: bb11, unwind unreachable]; ++ _38 = opaque::(copy _39) -> [return: bb11, unwind unreachable]; } bb11: { @@ -380,15 +380,15 @@ - StorageLive(_43); + nop; StorageLive(_44); - _44 = _1; + _44 = copy _1; StorageLive(_45); - _45 = _2; + _45 = copy _2; - _43 = Shr(move _44, move _45); -+ _43 = Shr(_1, _2); ++ _43 = Shr(copy _1, copy _2); StorageDead(_45); StorageDead(_44); - _42 = opaque::(move _43) -> [return: bb12, unwind unreachable]; -+ _42 = opaque::(_43) -> [return: bb12, unwind unreachable]; ++ _42 = opaque::(copy _43) -> [return: bb12, unwind unreachable]; } bb12: { @@ -399,12 +399,12 @@ - StorageLive(_47); + nop; StorageLive(_48); - _48 = _1; + _48 = copy _1; - _47 = move _48 as u32 (IntToInt); -+ _47 = _1 as u32 (IntToInt); ++ _47 = copy _1 as u32 (IntToInt); StorageDead(_48); - _46 = opaque::(move _47) -> [return: bb13, unwind unreachable]; -+ _46 = opaque::(_47) -> [return: bb13, unwind unreachable]; ++ _46 = opaque::(copy _47) -> [return: bb13, unwind unreachable]; } bb13: { @@ -415,12 +415,12 @@ - StorageLive(_50); + nop; StorageLive(_51); - _51 = _1; + _51 = copy _1; - _50 = move _51 as f32 (IntToFloat); -+ _50 = _1 as f32 (IntToFloat); ++ _50 = copy _1 as f32 (IntToFloat); StorageDead(_51); - _49 = opaque::(move _50) -> [return: bb14, unwind unreachable]; -+ _49 = opaque::(_50) -> [return: bb14, unwind unreachable]; ++ _49 = opaque::(copy _50) -> [return: bb14, unwind unreachable]; } bb14: { @@ -431,12 +431,12 @@ - StorageLive(_53); + nop; StorageLive(_54); - _54 = _1; + _54 = copy _1; - _53 = S::(move _54); -+ _53 = S::(_1); ++ _53 = S::(copy _1); StorageDead(_54); - _52 = opaque::>(move _53) -> [return: bb15, unwind unreachable]; -+ _52 = opaque::>(_53) -> [return: bb15, unwind unreachable]; ++ _52 = opaque::>(copy _53) -> [return: bb15, unwind unreachable]; } bb15: { @@ -447,14 +447,14 @@ StorageLive(_56); StorageLive(_57); StorageLive(_58); - _58 = _1; + _58 = copy _1; - _57 = S::(move _58); -+ _57 = _53; ++ _57 = copy _53; StorageDead(_58); -- _56 = (_57.0: u64); +- _56 = copy (_57.0: u64); - _55 = opaque::(move _56) -> [return: bb16, unwind unreachable]; -+ _56 = _1; -+ _55 = opaque::(_1) -> [return: bb16, unwind unreachable]; ++ _56 = copy _1; ++ _55 = opaque::(copy _1) -> [return: bb16, unwind unreachable]; } bb16: { @@ -464,15 +464,15 @@ StorageLive(_59); StorageLive(_60); StorageLive(_61); - _61 = _1; + _61 = copy _1; StorageLive(_62); - _62 = _2; + _62 = copy _2; - _60 = Add(move _61, move _62); -+ _60 = _5; ++ _60 = copy _5; StorageDead(_62); StorageDead(_61); - _59 = opaque::(move _60) -> [return: bb17, unwind unreachable]; -+ _59 = opaque::(_5) -> [return: bb17, unwind unreachable]; ++ _59 = opaque::(copy _5) -> [return: bb17, unwind unreachable]; } bb17: { @@ -481,15 +481,15 @@ StorageLive(_63); StorageLive(_64); StorageLive(_65); - _65 = _1; + _65 = copy _1; StorageLive(_66); - _66 = _2; + _66 = copy _2; - _64 = Mul(move _65, move _66); -+ _64 = _9; ++ _64 = copy _9; StorageDead(_66); StorageDead(_65); - _63 = opaque::(move _64) -> [return: bb18, unwind unreachable]; -+ _63 = opaque::(_9) -> [return: bb18, unwind unreachable]; ++ _63 = opaque::(copy _9) -> [return: bb18, unwind unreachable]; } bb18: { @@ -498,15 +498,15 @@ StorageLive(_67); StorageLive(_68); StorageLive(_69); - _69 = _1; + _69 = copy _1; StorageLive(_70); - _70 = _2; + _70 = copy _2; - _68 = Sub(move _69, move _70); -+ _68 = _13; ++ _68 = copy _13; StorageDead(_70); StorageDead(_69); - _67 = opaque::(move _68) -> [return: bb19, unwind unreachable]; -+ _67 = opaque::(_13) -> [return: bb19, unwind unreachable]; ++ _67 = opaque::(copy _13) -> [return: bb19, unwind unreachable]; } bb19: { @@ -515,22 +515,22 @@ StorageLive(_71); StorageLive(_72); StorageLive(_73); - _73 = _1; + _73 = copy _1; StorageLive(_74); - _74 = _2; -- _75 = Eq(_74, const 0_u64); -- assert(!move _75, "attempt to divide `{}` by zero", _73) -> [success: bb20, unwind unreachable]; -+ _75 = _20; -+ assert(!_20, "attempt to divide `{}` by zero", _1) -> [success: bb20, unwind unreachable]; + _74 = copy _2; +- _75 = Eq(copy _74, const 0_u64); +- assert(!move _75, "attempt to divide `{}` by zero", copy _73) -> [success: bb20, unwind unreachable]; ++ _75 = copy _20; ++ assert(!copy _20, "attempt to divide `{}` by zero", copy _1) -> [success: bb20, unwind unreachable]; } bb20: { - _72 = Div(move _73, move _74); -+ _72 = _17; ++ _72 = copy _17; StorageDead(_74); StorageDead(_73); - _71 = opaque::(move _72) -> [return: bb21, unwind unreachable]; -+ _71 = opaque::(_17) -> [return: bb21, unwind unreachable]; ++ _71 = opaque::(copy _17) -> [return: bb21, unwind unreachable]; } bb21: { @@ -539,22 +539,22 @@ StorageLive(_76); StorageLive(_77); StorageLive(_78); - _78 = _1; + _78 = copy _1; StorageLive(_79); - _79 = _2; -- _80 = Eq(_79, const 0_u64); -- assert(!move _80, "attempt to calculate the remainder of `{}` with a divisor of zero", _78) -> [success: bb22, unwind unreachable]; -+ _80 = _20; -+ assert(!_20, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb22, unwind unreachable]; + _79 = copy _2; +- _80 = Eq(copy _79, const 0_u64); +- assert(!move _80, "attempt to calculate the remainder of `{}` with a divisor of zero", copy _78) -> [success: bb22, unwind unreachable]; ++ _80 = copy _20; ++ assert(!copy _20, "attempt to calculate the remainder of `{}` with a divisor of zero", copy _1) -> [success: bb22, unwind unreachable]; } bb22: { - _77 = Rem(move _78, move _79); -+ _77 = _22; ++ _77 = copy _22; StorageDead(_79); StorageDead(_78); - _76 = opaque::(move _77) -> [return: bb23, unwind unreachable]; -+ _76 = opaque::(_22) -> [return: bb23, unwind unreachable]; ++ _76 = opaque::(copy _22) -> [return: bb23, unwind unreachable]; } bb23: { @@ -563,15 +563,15 @@ StorageLive(_81); StorageLive(_82); StorageLive(_83); - _83 = _1; + _83 = copy _1; StorageLive(_84); - _84 = _2; + _84 = copy _2; - _82 = BitAnd(move _83, move _84); -+ _82 = _27; ++ _82 = copy _27; StorageDead(_84); StorageDead(_83); - _81 = opaque::(move _82) -> [return: bb24, unwind unreachable]; -+ _81 = opaque::(_27) -> [return: bb24, unwind unreachable]; ++ _81 = opaque::(copy _27) -> [return: bb24, unwind unreachable]; } bb24: { @@ -580,15 +580,15 @@ StorageLive(_85); StorageLive(_86); StorageLive(_87); - _87 = _1; + _87 = copy _1; StorageLive(_88); - _88 = _2; + _88 = copy _2; - _86 = BitOr(move _87, move _88); -+ _86 = _31; ++ _86 = copy _31; StorageDead(_88); StorageDead(_87); - _85 = opaque::(move _86) -> [return: bb25, unwind unreachable]; -+ _85 = opaque::(_31) -> [return: bb25, unwind unreachable]; ++ _85 = opaque::(copy _31) -> [return: bb25, unwind unreachable]; } bb25: { @@ -597,15 +597,15 @@ StorageLive(_89); StorageLive(_90); StorageLive(_91); - _91 = _1; + _91 = copy _1; StorageLive(_92); - _92 = _2; + _92 = copy _2; - _90 = BitXor(move _91, move _92); -+ _90 = _35; ++ _90 = copy _35; StorageDead(_92); StorageDead(_91); - _89 = opaque::(move _90) -> [return: bb26, unwind unreachable]; -+ _89 = opaque::(_35) -> [return: bb26, unwind unreachable]; ++ _89 = opaque::(copy _35) -> [return: bb26, unwind unreachable]; } bb26: { @@ -614,15 +614,15 @@ StorageLive(_93); StorageLive(_94); StorageLive(_95); - _95 = _1; + _95 = copy _1; StorageLive(_96); - _96 = _2; + _96 = copy _2; - _94 = Shl(move _95, move _96); -+ _94 = _39; ++ _94 = copy _39; StorageDead(_96); StorageDead(_95); - _93 = opaque::(move _94) -> [return: bb27, unwind unreachable]; -+ _93 = opaque::(_39) -> [return: bb27, unwind unreachable]; ++ _93 = opaque::(copy _39) -> [return: bb27, unwind unreachable]; } bb27: { @@ -631,15 +631,15 @@ StorageLive(_97); StorageLive(_98); StorageLive(_99); - _99 = _1; + _99 = copy _1; StorageLive(_100); - _100 = _2; + _100 = copy _2; - _98 = Shr(move _99, move _100); -+ _98 = _43; ++ _98 = copy _43; StorageDead(_100); StorageDead(_99); - _97 = opaque::(move _98) -> [return: bb28, unwind unreachable]; -+ _97 = opaque::(_43) -> [return: bb28, unwind unreachable]; ++ _97 = opaque::(copy _43) -> [return: bb28, unwind unreachable]; } bb28: { @@ -648,12 +648,12 @@ StorageLive(_101); StorageLive(_102); StorageLive(_103); - _103 = _1; + _103 = copy _1; - _102 = move _103 as u32 (IntToInt); -+ _102 = _47; ++ _102 = copy _47; StorageDead(_103); - _101 = opaque::(move _102) -> [return: bb29, unwind unreachable]; -+ _101 = opaque::(_47) -> [return: bb29, unwind unreachable]; ++ _101 = opaque::(copy _47) -> [return: bb29, unwind unreachable]; } bb29: { @@ -662,12 +662,12 @@ StorageLive(_104); StorageLive(_105); StorageLive(_106); - _106 = _1; + _106 = copy _1; - _105 = move _106 as f32 (IntToFloat); -+ _105 = _50; ++ _105 = copy _50; StorageDead(_106); - _104 = opaque::(move _105) -> [return: bb30, unwind unreachable]; -+ _104 = opaque::(_50) -> [return: bb30, unwind unreachable]; ++ _104 = opaque::(copy _50) -> [return: bb30, unwind unreachable]; } bb30: { @@ -676,12 +676,12 @@ StorageLive(_107); StorageLive(_108); StorageLive(_109); - _109 = _1; + _109 = copy _1; - _108 = S::(move _109); -+ _108 = _53; ++ _108 = copy _53; StorageDead(_109); - _107 = opaque::>(move _108) -> [return: bb31, unwind unreachable]; -+ _107 = opaque::>(_53) -> [return: bb31, unwind unreachable]; ++ _107 = opaque::>(copy _53) -> [return: bb31, unwind unreachable]; } bb31: { @@ -691,14 +691,14 @@ StorageLive(_111); StorageLive(_112); StorageLive(_113); - _113 = _1; + _113 = copy _1; - _112 = S::(move _113); -+ _112 = _53; ++ _112 = copy _53; StorageDead(_113); -- _111 = (_112.0: u64); +- _111 = copy (_112.0: u64); - _110 = opaque::(move _111) -> [return: bb32, unwind unreachable]; -+ _111 = _1; -+ _110 = opaque::(_1) -> [return: bb32, unwind unreachable]; ++ _111 = copy _1; ++ _110 = opaque::(copy _1) -> [return: bb32, unwind unreachable]; } bb32: { @@ -710,21 +710,21 @@ + nop; StorageLive(_116); StorageLive(_117); - _117 = _1; + _117 = copy _1; StorageLive(_118); - _118 = _2; + _118 = copy _2; - _116 = Mul(move _117, move _118); -+ _116 = _9; ++ _116 = copy _9; StorageDead(_118); StorageDead(_117); StorageLive(_119); - _119 = _2; + _119 = copy _2; - _115 = Sub(move _116, move _119); -+ _115 = Sub(_9, _2); ++ _115 = Sub(copy _9, copy _2); StorageDead(_119); StorageDead(_116); - _114 = opaque::(move _115) -> [return: bb33, unwind unreachable]; -+ _114 = opaque::(_115) -> [return: bb33, unwind unreachable]; ++ _114 = opaque::(copy _115) -> [return: bb33, unwind unreachable]; } bb33: { @@ -735,21 +735,21 @@ StorageLive(_121); StorageLive(_122); StorageLive(_123); - _123 = _1; + _123 = copy _1; StorageLive(_124); - _124 = _2; + _124 = copy _2; - _122 = Mul(move _123, move _124); -+ _122 = _9; ++ _122 = copy _9; StorageDead(_124); StorageDead(_123); StorageLive(_125); - _125 = _2; + _125 = copy _2; - _121 = Sub(move _122, move _125); -+ _121 = _115; ++ _121 = copy _115; StorageDead(_125); StorageDead(_122); - _120 = opaque::(move _121) -> [return: bb34, unwind unreachable]; -+ _120 = opaque::(_115) -> [return: bb34, unwind unreachable]; ++ _120 = opaque::(copy _115) -> [return: bb34, unwind unreachable]; } bb34: { @@ -762,16 +762,16 @@ - StorageLive(_129); + nop; + nop; - _129 = (*_126); + _129 = copy (*_126); StorageLive(_130); - _130 = _1; + _130 = copy _1; - _128 = Add(move _129, move _130); -+ _128 = Add(_129, _1); ++ _128 = Add(copy _129, copy _1); StorageDead(_130); - StorageDead(_129); - _127 = opaque::(move _128) -> [return: bb35, unwind unreachable]; + nop; -+ _127 = opaque::(_128) -> [return: bb35, unwind unreachable]; ++ _127 = opaque::(copy _128) -> [return: bb35, unwind unreachable]; } bb35: { @@ -781,16 +781,16 @@ StorageLive(_131); StorageLive(_132); StorageLive(_133); -- _133 = (*_126); -+ _133 = _129; +- _133 = copy (*_126); ++ _133 = copy _129; StorageLive(_134); - _134 = _1; + _134 = copy _1; - _132 = Add(move _133, move _134); -+ _132 = _128; ++ _132 = copy _128; StorageDead(_134); StorageDead(_133); - _131 = opaque::(move _132) -> [return: bb36, unwind unreachable]; -+ _131 = opaque::(_128) -> [return: bb36, unwind unreachable]; ++ _131 = opaque::(copy _128) -> [return: bb36, unwind unreachable]; } bb36: { @@ -801,11 +801,11 @@ StorageLive(_136); StorageLive(_137); StorageLive(_138); - _138 = (*_135); + _138 = copy (*_135); StorageLive(_139); - _139 = _1; + _139 = copy _1; - _137 = Add(move _138, move _139); -+ _137 = Add(move _138, _1); ++ _137 = Add(move _138, copy _1); StorageDead(_139); StorageDead(_138); _136 = opaque::(move _137) -> [return: bb37, unwind unreachable]; @@ -817,11 +817,11 @@ StorageLive(_140); StorageLive(_141); StorageLive(_142); - _142 = (*_135); + _142 = copy (*_135); StorageLive(_143); - _143 = _1; + _143 = copy _1; - _141 = Add(move _142, move _143); -+ _141 = Add(move _142, _1); ++ _141 = Add(move _142, copy _1); StorageDead(_143); StorageDead(_142); _140 = opaque::(move _141) -> [return: bb38, unwind unreachable]; @@ -836,11 +836,11 @@ StorageLive(_146); StorageLive(_147); StorageLive(_148); - _148 = (*_145); + _148 = copy (*_145); StorageLive(_149); - _149 = _1; + _149 = copy _1; - _147 = Add(move _148, move _149); -+ _147 = Add(move _148, _1); ++ _147 = Add(move _148, copy _1); StorageDead(_149); StorageDead(_148); _146 = opaque::(move _147) -> [return: bb39, unwind unreachable]; @@ -852,11 +852,11 @@ StorageLive(_150); StorageLive(_151); StorageLive(_152); - _152 = (*_145); + _152 = copy (*_145); StorageLive(_153); - _153 = _1; + _153 = copy _1; - _151 = Add(move _152, move _153); -+ _151 = Add(move _152, _1); ++ _151 = Add(move _152, copy _1); StorageDead(_153); StorageDead(_152); _150 = opaque::(move _151) -> [return: bb40, unwind unreachable]; @@ -870,11 +870,11 @@ StorageLive(_155); StorageLive(_156); StorageLive(_157); - _157 = (*_154); + _157 = copy (*_154); StorageLive(_158); - _158 = _1; + _158 = copy _1; - _156 = Add(move _157, move _158); -+ _156 = Add(move _157, _1); ++ _156 = Add(move _157, copy _1); StorageDead(_158); StorageDead(_157); _155 = opaque::(move _156) -> [return: bb41, unwind unreachable]; @@ -886,11 +886,11 @@ StorageLive(_159); StorageLive(_160); StorageLive(_161); - _161 = (*_154); + _161 = copy (*_154); StorageLive(_162); - _162 = _1; + _162 = copy _1; - _160 = Add(move _161, move _162); -+ _160 = Add(move _161, _1); ++ _160 = Add(move _161, copy _1); StorageDead(_162); StorageDead(_161); _159 = opaque::(move _160) -> [return: bb42, unwind unreachable]; @@ -910,16 +910,16 @@ - StorageLive(_166); + nop; + nop; - _166 = (*_163); + _166 = copy (*_163); StorageLive(_167); - _167 = _1; + _167 = copy _1; - _165 = Add(move _166, move _167); -+ _165 = Add(_166, _1); ++ _165 = Add(copy _166, copy _1); StorageDead(_167); - StorageDead(_166); - _164 = opaque::(move _165) -> [return: bb43, unwind unreachable]; + nop; -+ _164 = opaque::(_165) -> [return: bb43, unwind unreachable]; ++ _164 = opaque::(copy _165) -> [return: bb43, unwind unreachable]; } bb43: { @@ -929,16 +929,16 @@ StorageLive(_168); StorageLive(_169); StorageLive(_170); -- _170 = (*_163); -+ _170 = _166; +- _170 = copy (*_163); ++ _170 = copy _166; StorageLive(_171); - _171 = _1; + _171 = copy _1; - _169 = Add(move _170, move _171); -+ _169 = _165; ++ _169 = copy _165; StorageDead(_171); StorageDead(_170); - _168 = opaque::(move _169) -> [return: bb44, unwind unreachable]; -+ _168 = opaque::(_165) -> [return: bb44, unwind unreachable]; ++ _168 = opaque::(copy _165) -> [return: bb44, unwind unreachable]; } bb44: { diff --git a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff index 41c01536130..3ca5238663c 100644 --- a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff @@ -195,15 +195,15 @@ - StorageLive(_5); + nop; StorageLive(_6); - _6 = _1; + _6 = copy _1; StorageLive(_7); - _7 = _2; + _7 = copy _2; - _5 = Add(move _6, move _7); -+ _5 = Add(_1, _2); ++ _5 = Add(copy _1, copy _2); StorageDead(_7); StorageDead(_6); - _4 = opaque::(move _5) -> [return: bb1, unwind continue]; -+ _4 = opaque::(_5) -> [return: bb1, unwind continue]; ++ _4 = opaque::(copy _5) -> [return: bb1, unwind continue]; } bb1: { @@ -214,15 +214,15 @@ - StorageLive(_9); + nop; StorageLive(_10); - _10 = _1; + _10 = copy _1; StorageLive(_11); - _11 = _2; + _11 = copy _2; - _9 = Mul(move _10, move _11); -+ _9 = Mul(_1, _2); ++ _9 = Mul(copy _1, copy _2); StorageDead(_11); StorageDead(_10); - _8 = opaque::(move _9) -> [return: bb2, unwind continue]; -+ _8 = opaque::(_9) -> [return: bb2, unwind continue]; ++ _8 = opaque::(copy _9) -> [return: bb2, unwind continue]; } bb2: { @@ -233,15 +233,15 @@ - StorageLive(_13); + nop; StorageLive(_14); - _14 = _1; + _14 = copy _1; StorageLive(_15); - _15 = _2; + _15 = copy _2; - _13 = Sub(move _14, move _15); -+ _13 = Sub(_1, _2); ++ _13 = Sub(copy _1, copy _2); StorageDead(_15); StorageDead(_14); - _12 = opaque::(move _13) -> [return: bb3, unwind continue]; -+ _12 = opaque::(_13) -> [return: bb3, unwind continue]; ++ _12 = opaque::(copy _13) -> [return: bb3, unwind continue]; } bb3: { @@ -252,22 +252,22 @@ - StorageLive(_17); + nop; StorageLive(_18); - _18 = _1; + _18 = copy _1; StorageLive(_19); - _19 = _2; -- _20 = Eq(_19, const 0_u64); -- assert(!move _20, "attempt to divide `{}` by zero", _18) -> [success: bb4, unwind continue]; -+ _20 = Eq(_2, const 0_u64); -+ assert(!_20, "attempt to divide `{}` by zero", _1) -> [success: bb4, unwind continue]; + _19 = copy _2; +- _20 = Eq(copy _19, const 0_u64); +- assert(!move _20, "attempt to divide `{}` by zero", copy _18) -> [success: bb4, unwind continue]; ++ _20 = Eq(copy _2, const 0_u64); ++ assert(!copy _20, "attempt to divide `{}` by zero", copy _1) -> [success: bb4, unwind continue]; } bb4: { - _17 = Div(move _18, move _19); -+ _17 = Div(_1, _2); ++ _17 = Div(copy _1, copy _2); StorageDead(_19); StorageDead(_18); - _16 = opaque::(move _17) -> [return: bb5, unwind continue]; -+ _16 = opaque::(_17) -> [return: bb5, unwind continue]; ++ _16 = opaque::(copy _17) -> [return: bb5, unwind continue]; } bb5: { @@ -278,22 +278,22 @@ - StorageLive(_22); + nop; StorageLive(_23); - _23 = _1; + _23 = copy _1; StorageLive(_24); - _24 = _2; -- _25 = Eq(_24, const 0_u64); -- assert(!move _25, "attempt to calculate the remainder of `{}` with a divisor of zero", _23) -> [success: bb6, unwind continue]; -+ _25 = _20; -+ assert(!_20, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb6, unwind continue]; + _24 = copy _2; +- _25 = Eq(copy _24, const 0_u64); +- assert(!move _25, "attempt to calculate the remainder of `{}` with a divisor of zero", copy _23) -> [success: bb6, unwind continue]; ++ _25 = copy _20; ++ assert(!copy _20, "attempt to calculate the remainder of `{}` with a divisor of zero", copy _1) -> [success: bb6, unwind continue]; } bb6: { - _22 = Rem(move _23, move _24); -+ _22 = Rem(_1, _2); ++ _22 = Rem(copy _1, copy _2); StorageDead(_24); StorageDead(_23); - _21 = opaque::(move _22) -> [return: bb7, unwind continue]; -+ _21 = opaque::(_22) -> [return: bb7, unwind continue]; ++ _21 = opaque::(copy _22) -> [return: bb7, unwind continue]; } bb7: { @@ -304,15 +304,15 @@ - StorageLive(_27); + nop; StorageLive(_28); - _28 = _1; + _28 = copy _1; StorageLive(_29); - _29 = _2; + _29 = copy _2; - _27 = BitAnd(move _28, move _29); -+ _27 = BitAnd(_1, _2); ++ _27 = BitAnd(copy _1, copy _2); StorageDead(_29); StorageDead(_28); - _26 = opaque::(move _27) -> [return: bb8, unwind continue]; -+ _26 = opaque::(_27) -> [return: bb8, unwind continue]; ++ _26 = opaque::(copy _27) -> [return: bb8, unwind continue]; } bb8: { @@ -323,15 +323,15 @@ - StorageLive(_31); + nop; StorageLive(_32); - _32 = _1; + _32 = copy _1; StorageLive(_33); - _33 = _2; + _33 = copy _2; - _31 = BitOr(move _32, move _33); -+ _31 = BitOr(_1, _2); ++ _31 = BitOr(copy _1, copy _2); StorageDead(_33); StorageDead(_32); - _30 = opaque::(move _31) -> [return: bb9, unwind continue]; -+ _30 = opaque::(_31) -> [return: bb9, unwind continue]; ++ _30 = opaque::(copy _31) -> [return: bb9, unwind continue]; } bb9: { @@ -342,15 +342,15 @@ - StorageLive(_35); + nop; StorageLive(_36); - _36 = _1; + _36 = copy _1; StorageLive(_37); - _37 = _2; + _37 = copy _2; - _35 = BitXor(move _36, move _37); -+ _35 = BitXor(_1, _2); ++ _35 = BitXor(copy _1, copy _2); StorageDead(_37); StorageDead(_36); - _34 = opaque::(move _35) -> [return: bb10, unwind continue]; -+ _34 = opaque::(_35) -> [return: bb10, unwind continue]; ++ _34 = opaque::(copy _35) -> [return: bb10, unwind continue]; } bb10: { @@ -361,15 +361,15 @@ - StorageLive(_39); + nop; StorageLive(_40); - _40 = _1; + _40 = copy _1; StorageLive(_41); - _41 = _2; + _41 = copy _2; - _39 = Shl(move _40, move _41); -+ _39 = Shl(_1, _2); ++ _39 = Shl(copy _1, copy _2); StorageDead(_41); StorageDead(_40); - _38 = opaque::(move _39) -> [return: bb11, unwind continue]; -+ _38 = opaque::(_39) -> [return: bb11, unwind continue]; ++ _38 = opaque::(copy _39) -> [return: bb11, unwind continue]; } bb11: { @@ -380,15 +380,15 @@ - StorageLive(_43); + nop; StorageLive(_44); - _44 = _1; + _44 = copy _1; StorageLive(_45); - _45 = _2; + _45 = copy _2; - _43 = Shr(move _44, move _45); -+ _43 = Shr(_1, _2); ++ _43 = Shr(copy _1, copy _2); StorageDead(_45); StorageDead(_44); - _42 = opaque::(move _43) -> [return: bb12, unwind continue]; -+ _42 = opaque::(_43) -> [return: bb12, unwind continue]; ++ _42 = opaque::(copy _43) -> [return: bb12, unwind continue]; } bb12: { @@ -399,12 +399,12 @@ - StorageLive(_47); + nop; StorageLive(_48); - _48 = _1; + _48 = copy _1; - _47 = move _48 as u32 (IntToInt); -+ _47 = _1 as u32 (IntToInt); ++ _47 = copy _1 as u32 (IntToInt); StorageDead(_48); - _46 = opaque::(move _47) -> [return: bb13, unwind continue]; -+ _46 = opaque::(_47) -> [return: bb13, unwind continue]; ++ _46 = opaque::(copy _47) -> [return: bb13, unwind continue]; } bb13: { @@ -415,12 +415,12 @@ - StorageLive(_50); + nop; StorageLive(_51); - _51 = _1; + _51 = copy _1; - _50 = move _51 as f32 (IntToFloat); -+ _50 = _1 as f32 (IntToFloat); ++ _50 = copy _1 as f32 (IntToFloat); StorageDead(_51); - _49 = opaque::(move _50) -> [return: bb14, unwind continue]; -+ _49 = opaque::(_50) -> [return: bb14, unwind continue]; ++ _49 = opaque::(copy _50) -> [return: bb14, unwind continue]; } bb14: { @@ -431,12 +431,12 @@ - StorageLive(_53); + nop; StorageLive(_54); - _54 = _1; + _54 = copy _1; - _53 = S::(move _54); -+ _53 = S::(_1); ++ _53 = S::(copy _1); StorageDead(_54); - _52 = opaque::>(move _53) -> [return: bb15, unwind continue]; -+ _52 = opaque::>(_53) -> [return: bb15, unwind continue]; ++ _52 = opaque::>(copy _53) -> [return: bb15, unwind continue]; } bb15: { @@ -447,14 +447,14 @@ StorageLive(_56); StorageLive(_57); StorageLive(_58); - _58 = _1; + _58 = copy _1; - _57 = S::(move _58); -+ _57 = _53; ++ _57 = copy _53; StorageDead(_58); -- _56 = (_57.0: u64); +- _56 = copy (_57.0: u64); - _55 = opaque::(move _56) -> [return: bb16, unwind continue]; -+ _56 = _1; -+ _55 = opaque::(_1) -> [return: bb16, unwind continue]; ++ _56 = copy _1; ++ _55 = opaque::(copy _1) -> [return: bb16, unwind continue]; } bb16: { @@ -464,15 +464,15 @@ StorageLive(_59); StorageLive(_60); StorageLive(_61); - _61 = _1; + _61 = copy _1; StorageLive(_62); - _62 = _2; + _62 = copy _2; - _60 = Add(move _61, move _62); -+ _60 = _5; ++ _60 = copy _5; StorageDead(_62); StorageDead(_61); - _59 = opaque::(move _60) -> [return: bb17, unwind continue]; -+ _59 = opaque::(_5) -> [return: bb17, unwind continue]; ++ _59 = opaque::(copy _5) -> [return: bb17, unwind continue]; } bb17: { @@ -481,15 +481,15 @@ StorageLive(_63); StorageLive(_64); StorageLive(_65); - _65 = _1; + _65 = copy _1; StorageLive(_66); - _66 = _2; + _66 = copy _2; - _64 = Mul(move _65, move _66); -+ _64 = _9; ++ _64 = copy _9; StorageDead(_66); StorageDead(_65); - _63 = opaque::(move _64) -> [return: bb18, unwind continue]; -+ _63 = opaque::(_9) -> [return: bb18, unwind continue]; ++ _63 = opaque::(copy _9) -> [return: bb18, unwind continue]; } bb18: { @@ -498,15 +498,15 @@ StorageLive(_67); StorageLive(_68); StorageLive(_69); - _69 = _1; + _69 = copy _1; StorageLive(_70); - _70 = _2; + _70 = copy _2; - _68 = Sub(move _69, move _70); -+ _68 = _13; ++ _68 = copy _13; StorageDead(_70); StorageDead(_69); - _67 = opaque::(move _68) -> [return: bb19, unwind continue]; -+ _67 = opaque::(_13) -> [return: bb19, unwind continue]; ++ _67 = opaque::(copy _13) -> [return: bb19, unwind continue]; } bb19: { @@ -515,22 +515,22 @@ StorageLive(_71); StorageLive(_72); StorageLive(_73); - _73 = _1; + _73 = copy _1; StorageLive(_74); - _74 = _2; -- _75 = Eq(_74, const 0_u64); -- assert(!move _75, "attempt to divide `{}` by zero", _73) -> [success: bb20, unwind continue]; -+ _75 = _20; -+ assert(!_20, "attempt to divide `{}` by zero", _1) -> [success: bb20, unwind continue]; + _74 = copy _2; +- _75 = Eq(copy _74, const 0_u64); +- assert(!move _75, "attempt to divide `{}` by zero", copy _73) -> [success: bb20, unwind continue]; ++ _75 = copy _20; ++ assert(!copy _20, "attempt to divide `{}` by zero", copy _1) -> [success: bb20, unwind continue]; } bb20: { - _72 = Div(move _73, move _74); -+ _72 = _17; ++ _72 = copy _17; StorageDead(_74); StorageDead(_73); - _71 = opaque::(move _72) -> [return: bb21, unwind continue]; -+ _71 = opaque::(_17) -> [return: bb21, unwind continue]; ++ _71 = opaque::(copy _17) -> [return: bb21, unwind continue]; } bb21: { @@ -539,22 +539,22 @@ StorageLive(_76); StorageLive(_77); StorageLive(_78); - _78 = _1; + _78 = copy _1; StorageLive(_79); - _79 = _2; -- _80 = Eq(_79, const 0_u64); -- assert(!move _80, "attempt to calculate the remainder of `{}` with a divisor of zero", _78) -> [success: bb22, unwind continue]; -+ _80 = _20; -+ assert(!_20, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb22, unwind continue]; + _79 = copy _2; +- _80 = Eq(copy _79, const 0_u64); +- assert(!move _80, "attempt to calculate the remainder of `{}` with a divisor of zero", copy _78) -> [success: bb22, unwind continue]; ++ _80 = copy _20; ++ assert(!copy _20, "attempt to calculate the remainder of `{}` with a divisor of zero", copy _1) -> [success: bb22, unwind continue]; } bb22: { - _77 = Rem(move _78, move _79); -+ _77 = _22; ++ _77 = copy _22; StorageDead(_79); StorageDead(_78); - _76 = opaque::(move _77) -> [return: bb23, unwind continue]; -+ _76 = opaque::(_22) -> [return: bb23, unwind continue]; ++ _76 = opaque::(copy _22) -> [return: bb23, unwind continue]; } bb23: { @@ -563,15 +563,15 @@ StorageLive(_81); StorageLive(_82); StorageLive(_83); - _83 = _1; + _83 = copy _1; StorageLive(_84); - _84 = _2; + _84 = copy _2; - _82 = BitAnd(move _83, move _84); -+ _82 = _27; ++ _82 = copy _27; StorageDead(_84); StorageDead(_83); - _81 = opaque::(move _82) -> [return: bb24, unwind continue]; -+ _81 = opaque::(_27) -> [return: bb24, unwind continue]; ++ _81 = opaque::(copy _27) -> [return: bb24, unwind continue]; } bb24: { @@ -580,15 +580,15 @@ StorageLive(_85); StorageLive(_86); StorageLive(_87); - _87 = _1; + _87 = copy _1; StorageLive(_88); - _88 = _2; + _88 = copy _2; - _86 = BitOr(move _87, move _88); -+ _86 = _31; ++ _86 = copy _31; StorageDead(_88); StorageDead(_87); - _85 = opaque::(move _86) -> [return: bb25, unwind continue]; -+ _85 = opaque::(_31) -> [return: bb25, unwind continue]; ++ _85 = opaque::(copy _31) -> [return: bb25, unwind continue]; } bb25: { @@ -597,15 +597,15 @@ StorageLive(_89); StorageLive(_90); StorageLive(_91); - _91 = _1; + _91 = copy _1; StorageLive(_92); - _92 = _2; + _92 = copy _2; - _90 = BitXor(move _91, move _92); -+ _90 = _35; ++ _90 = copy _35; StorageDead(_92); StorageDead(_91); - _89 = opaque::(move _90) -> [return: bb26, unwind continue]; -+ _89 = opaque::(_35) -> [return: bb26, unwind continue]; ++ _89 = opaque::(copy _35) -> [return: bb26, unwind continue]; } bb26: { @@ -614,15 +614,15 @@ StorageLive(_93); StorageLive(_94); StorageLive(_95); - _95 = _1; + _95 = copy _1; StorageLive(_96); - _96 = _2; + _96 = copy _2; - _94 = Shl(move _95, move _96); -+ _94 = _39; ++ _94 = copy _39; StorageDead(_96); StorageDead(_95); - _93 = opaque::(move _94) -> [return: bb27, unwind continue]; -+ _93 = opaque::(_39) -> [return: bb27, unwind continue]; ++ _93 = opaque::(copy _39) -> [return: bb27, unwind continue]; } bb27: { @@ -631,15 +631,15 @@ StorageLive(_97); StorageLive(_98); StorageLive(_99); - _99 = _1; + _99 = copy _1; StorageLive(_100); - _100 = _2; + _100 = copy _2; - _98 = Shr(move _99, move _100); -+ _98 = _43; ++ _98 = copy _43; StorageDead(_100); StorageDead(_99); - _97 = opaque::(move _98) -> [return: bb28, unwind continue]; -+ _97 = opaque::(_43) -> [return: bb28, unwind continue]; ++ _97 = opaque::(copy _43) -> [return: bb28, unwind continue]; } bb28: { @@ -648,12 +648,12 @@ StorageLive(_101); StorageLive(_102); StorageLive(_103); - _103 = _1; + _103 = copy _1; - _102 = move _103 as u32 (IntToInt); -+ _102 = _47; ++ _102 = copy _47; StorageDead(_103); - _101 = opaque::(move _102) -> [return: bb29, unwind continue]; -+ _101 = opaque::(_47) -> [return: bb29, unwind continue]; ++ _101 = opaque::(copy _47) -> [return: bb29, unwind continue]; } bb29: { @@ -662,12 +662,12 @@ StorageLive(_104); StorageLive(_105); StorageLive(_106); - _106 = _1; + _106 = copy _1; - _105 = move _106 as f32 (IntToFloat); -+ _105 = _50; ++ _105 = copy _50; StorageDead(_106); - _104 = opaque::(move _105) -> [return: bb30, unwind continue]; -+ _104 = opaque::(_50) -> [return: bb30, unwind continue]; ++ _104 = opaque::(copy _50) -> [return: bb30, unwind continue]; } bb30: { @@ -676,12 +676,12 @@ StorageLive(_107); StorageLive(_108); StorageLive(_109); - _109 = _1; + _109 = copy _1; - _108 = S::(move _109); -+ _108 = _53; ++ _108 = copy _53; StorageDead(_109); - _107 = opaque::>(move _108) -> [return: bb31, unwind continue]; -+ _107 = opaque::>(_53) -> [return: bb31, unwind continue]; ++ _107 = opaque::>(copy _53) -> [return: bb31, unwind continue]; } bb31: { @@ -691,14 +691,14 @@ StorageLive(_111); StorageLive(_112); StorageLive(_113); - _113 = _1; + _113 = copy _1; - _112 = S::(move _113); -+ _112 = _53; ++ _112 = copy _53; StorageDead(_113); -- _111 = (_112.0: u64); +- _111 = copy (_112.0: u64); - _110 = opaque::(move _111) -> [return: bb32, unwind continue]; -+ _111 = _1; -+ _110 = opaque::(_1) -> [return: bb32, unwind continue]; ++ _111 = copy _1; ++ _110 = opaque::(copy _1) -> [return: bb32, unwind continue]; } bb32: { @@ -710,21 +710,21 @@ + nop; StorageLive(_116); StorageLive(_117); - _117 = _1; + _117 = copy _1; StorageLive(_118); - _118 = _2; + _118 = copy _2; - _116 = Mul(move _117, move _118); -+ _116 = _9; ++ _116 = copy _9; StorageDead(_118); StorageDead(_117); StorageLive(_119); - _119 = _2; + _119 = copy _2; - _115 = Sub(move _116, move _119); -+ _115 = Sub(_9, _2); ++ _115 = Sub(copy _9, copy _2); StorageDead(_119); StorageDead(_116); - _114 = opaque::(move _115) -> [return: bb33, unwind continue]; -+ _114 = opaque::(_115) -> [return: bb33, unwind continue]; ++ _114 = opaque::(copy _115) -> [return: bb33, unwind continue]; } bb33: { @@ -735,21 +735,21 @@ StorageLive(_121); StorageLive(_122); StorageLive(_123); - _123 = _1; + _123 = copy _1; StorageLive(_124); - _124 = _2; + _124 = copy _2; - _122 = Mul(move _123, move _124); -+ _122 = _9; ++ _122 = copy _9; StorageDead(_124); StorageDead(_123); StorageLive(_125); - _125 = _2; + _125 = copy _2; - _121 = Sub(move _122, move _125); -+ _121 = _115; ++ _121 = copy _115; StorageDead(_125); StorageDead(_122); - _120 = opaque::(move _121) -> [return: bb34, unwind continue]; -+ _120 = opaque::(_115) -> [return: bb34, unwind continue]; ++ _120 = opaque::(copy _115) -> [return: bb34, unwind continue]; } bb34: { @@ -762,16 +762,16 @@ - StorageLive(_129); + nop; + nop; - _129 = (*_126); + _129 = copy (*_126); StorageLive(_130); - _130 = _1; + _130 = copy _1; - _128 = Add(move _129, move _130); -+ _128 = Add(_129, _1); ++ _128 = Add(copy _129, copy _1); StorageDead(_130); - StorageDead(_129); - _127 = opaque::(move _128) -> [return: bb35, unwind continue]; + nop; -+ _127 = opaque::(_128) -> [return: bb35, unwind continue]; ++ _127 = opaque::(copy _128) -> [return: bb35, unwind continue]; } bb35: { @@ -781,16 +781,16 @@ StorageLive(_131); StorageLive(_132); StorageLive(_133); -- _133 = (*_126); -+ _133 = _129; +- _133 = copy (*_126); ++ _133 = copy _129; StorageLive(_134); - _134 = _1; + _134 = copy _1; - _132 = Add(move _133, move _134); -+ _132 = _128; ++ _132 = copy _128; StorageDead(_134); StorageDead(_133); - _131 = opaque::(move _132) -> [return: bb36, unwind continue]; -+ _131 = opaque::(_128) -> [return: bb36, unwind continue]; ++ _131 = opaque::(copy _128) -> [return: bb36, unwind continue]; } bb36: { @@ -801,11 +801,11 @@ StorageLive(_136); StorageLive(_137); StorageLive(_138); - _138 = (*_135); + _138 = copy (*_135); StorageLive(_139); - _139 = _1; + _139 = copy _1; - _137 = Add(move _138, move _139); -+ _137 = Add(move _138, _1); ++ _137 = Add(move _138, copy _1); StorageDead(_139); StorageDead(_138); _136 = opaque::(move _137) -> [return: bb37, unwind continue]; @@ -817,11 +817,11 @@ StorageLive(_140); StorageLive(_141); StorageLive(_142); - _142 = (*_135); + _142 = copy (*_135); StorageLive(_143); - _143 = _1; + _143 = copy _1; - _141 = Add(move _142, move _143); -+ _141 = Add(move _142, _1); ++ _141 = Add(move _142, copy _1); StorageDead(_143); StorageDead(_142); _140 = opaque::(move _141) -> [return: bb38, unwind continue]; @@ -836,11 +836,11 @@ StorageLive(_146); StorageLive(_147); StorageLive(_148); - _148 = (*_145); + _148 = copy (*_145); StorageLive(_149); - _149 = _1; + _149 = copy _1; - _147 = Add(move _148, move _149); -+ _147 = Add(move _148, _1); ++ _147 = Add(move _148, copy _1); StorageDead(_149); StorageDead(_148); _146 = opaque::(move _147) -> [return: bb39, unwind continue]; @@ -852,11 +852,11 @@ StorageLive(_150); StorageLive(_151); StorageLive(_152); - _152 = (*_145); + _152 = copy (*_145); StorageLive(_153); - _153 = _1; + _153 = copy _1; - _151 = Add(move _152, move _153); -+ _151 = Add(move _152, _1); ++ _151 = Add(move _152, copy _1); StorageDead(_153); StorageDead(_152); _150 = opaque::(move _151) -> [return: bb40, unwind continue]; @@ -870,11 +870,11 @@ StorageLive(_155); StorageLive(_156); StorageLive(_157); - _157 = (*_154); + _157 = copy (*_154); StorageLive(_158); - _158 = _1; + _158 = copy _1; - _156 = Add(move _157, move _158); -+ _156 = Add(move _157, _1); ++ _156 = Add(move _157, copy _1); StorageDead(_158); StorageDead(_157); _155 = opaque::(move _156) -> [return: bb41, unwind continue]; @@ -886,11 +886,11 @@ StorageLive(_159); StorageLive(_160); StorageLive(_161); - _161 = (*_154); + _161 = copy (*_154); StorageLive(_162); - _162 = _1; + _162 = copy _1; - _160 = Add(move _161, move _162); -+ _160 = Add(move _161, _1); ++ _160 = Add(move _161, copy _1); StorageDead(_162); StorageDead(_161); _159 = opaque::(move _160) -> [return: bb42, unwind continue]; @@ -910,16 +910,16 @@ - StorageLive(_166); + nop; + nop; - _166 = (*_163); + _166 = copy (*_163); StorageLive(_167); - _167 = _1; + _167 = copy _1; - _165 = Add(move _166, move _167); -+ _165 = Add(_166, _1); ++ _165 = Add(copy _166, copy _1); StorageDead(_167); - StorageDead(_166); - _164 = opaque::(move _165) -> [return: bb43, unwind continue]; + nop; -+ _164 = opaque::(_165) -> [return: bb43, unwind continue]; ++ _164 = opaque::(copy _165) -> [return: bb43, unwind continue]; } bb43: { @@ -929,16 +929,16 @@ StorageLive(_168); StorageLive(_169); StorageLive(_170); -- _170 = (*_163); -+ _170 = _166; +- _170 = copy (*_163); ++ _170 = copy _166; StorageLive(_171); - _171 = _1; + _171 = copy _1; - _169 = Add(move _170, move _171); -+ _169 = _165; ++ _169 = copy _165; StorageDead(_171); StorageDead(_170); - _168 = opaque::(move _169) -> [return: bb44, unwind continue]; -+ _168 = opaque::(_165) -> [return: bb44, unwind continue]; ++ _168 = opaque::(copy _165) -> [return: bb44, unwind continue]; } bb44: { diff --git a/tests/mir-opt/gvn.unary.GVN.panic-abort.diff b/tests/mir-opt/gvn.unary.GVN.panic-abort.diff index 9469032f294..d14aec6df5f 100644 --- a/tests/mir-opt/gvn.unary.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.unary.GVN.panic-abort.diff @@ -37,15 +37,15 @@ StorageLive(_3); StorageLive(_4); StorageLive(_5); - _5 = _1; + _5 = copy _1; - _4 = Neg(move _5); -+ _4 = Neg(_1); ++ _4 = Neg(copy _1); StorageDead(_5); - _3 = Neg(move _4); -+ _3 = _1; ++ _3 = copy _1; StorageDead(_4); - _2 = opaque::(move _3) -> [return: bb1, unwind unreachable]; -+ _2 = opaque::(_1) -> [return: bb1, unwind unreachable]; ++ _2 = opaque::(copy _1) -> [return: bb1, unwind unreachable]; } bb1: { @@ -54,23 +54,23 @@ - StorageLive(_6); + nop; StorageLive(_7); - _7 = _1; + _7 = copy _1; - _6 = Lt(move _7, const 13_i64); -+ _6 = Lt(_1, const 13_i64); ++ _6 = Lt(copy _1, const 13_i64); StorageDead(_7); StorageLive(_8); StorageLive(_9); StorageLive(_10); StorageLive(_11); - _11 = _6; + _11 = copy _6; - _10 = Not(move _11); -+ _10 = Not(_6); ++ _10 = Not(copy _6); StorageDead(_11); - _9 = Not(move _10); -+ _9 = _6; ++ _9 = copy _6; StorageDead(_10); - _8 = opaque::(move _9) -> [return: bb2, unwind unreachable]; -+ _8 = opaque::(_6) -> [return: bb2, unwind unreachable]; ++ _8 = opaque::(copy _6) -> [return: bb2, unwind unreachable]; } bb2: { @@ -80,12 +80,12 @@ - StorageLive(_13); + nop; StorageLive(_14); - _14 = _1; + _14 = copy _1; - _13 = Ne(move _14, const 15_i64); -+ _13 = Ne(_1, const 15_i64); ++ _13 = Ne(copy _1, const 15_i64); StorageDead(_14); - _12 = opaque::(move _13) -> [return: bb3, unwind unreachable]; -+ _12 = opaque::(_13) -> [return: bb3, unwind unreachable]; ++ _12 = opaque::(copy _13) -> [return: bb3, unwind unreachable]; } bb3: { @@ -96,15 +96,15 @@ StorageLive(_16); StorageLive(_17); StorageLive(_18); - _18 = _1; + _18 = copy _1; - _17 = Eq(move _18, const 15_i64); -+ _17 = Eq(_1, const 15_i64); ++ _17 = Eq(copy _1, const 15_i64); StorageDead(_18); - _16 = Not(move _17); -+ _16 = _13; ++ _16 = copy _13; StorageDead(_17); - _15 = opaque::(move _16) -> [return: bb4, unwind unreachable]; -+ _15 = opaque::(_13) -> [return: bb4, unwind unreachable]; ++ _15 = opaque::(copy _13) -> [return: bb4, unwind unreachable]; } bb4: { @@ -114,12 +114,12 @@ - StorageLive(_20); + nop; StorageLive(_21); - _21 = _1; + _21 = copy _1; - _20 = Eq(move _21, const 35_i64); -+ _20 = Eq(_1, const 35_i64); ++ _20 = Eq(copy _1, const 35_i64); StorageDead(_21); - _19 = opaque::(move _20) -> [return: bb5, unwind unreachable]; -+ _19 = opaque::(_20) -> [return: bb5, unwind unreachable]; ++ _19 = opaque::(copy _20) -> [return: bb5, unwind unreachable]; } bb5: { @@ -130,15 +130,15 @@ StorageLive(_23); StorageLive(_24); StorageLive(_25); - _25 = _1; + _25 = copy _1; - _24 = Ne(move _25, const 35_i64); -+ _24 = Ne(_1, const 35_i64); ++ _24 = Ne(copy _1, const 35_i64); StorageDead(_25); - _23 = Not(move _24); -+ _23 = _20; ++ _23 = copy _20; StorageDead(_24); - _22 = opaque::(move _23) -> [return: bb6, unwind unreachable]; -+ _22 = opaque::(_20) -> [return: bb6, unwind unreachable]; ++ _22 = opaque::(copy _20) -> [return: bb6, unwind unreachable]; } bb6: { diff --git a/tests/mir-opt/gvn.unary.GVN.panic-unwind.diff b/tests/mir-opt/gvn.unary.GVN.panic-unwind.diff index e672f6fb6ba..5978f1faa1f 100644 --- a/tests/mir-opt/gvn.unary.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.unary.GVN.panic-unwind.diff @@ -37,15 +37,15 @@ StorageLive(_3); StorageLive(_4); StorageLive(_5); - _5 = _1; + _5 = copy _1; - _4 = Neg(move _5); -+ _4 = Neg(_1); ++ _4 = Neg(copy _1); StorageDead(_5); - _3 = Neg(move _4); -+ _3 = _1; ++ _3 = copy _1; StorageDead(_4); - _2 = opaque::(move _3) -> [return: bb1, unwind continue]; -+ _2 = opaque::(_1) -> [return: bb1, unwind continue]; ++ _2 = opaque::(copy _1) -> [return: bb1, unwind continue]; } bb1: { @@ -54,23 +54,23 @@ - StorageLive(_6); + nop; StorageLive(_7); - _7 = _1; + _7 = copy _1; - _6 = Lt(move _7, const 13_i64); -+ _6 = Lt(_1, const 13_i64); ++ _6 = Lt(copy _1, const 13_i64); StorageDead(_7); StorageLive(_8); StorageLive(_9); StorageLive(_10); StorageLive(_11); - _11 = _6; + _11 = copy _6; - _10 = Not(move _11); -+ _10 = Not(_6); ++ _10 = Not(copy _6); StorageDead(_11); - _9 = Not(move _10); -+ _9 = _6; ++ _9 = copy _6; StorageDead(_10); - _8 = opaque::(move _9) -> [return: bb2, unwind continue]; -+ _8 = opaque::(_6) -> [return: bb2, unwind continue]; ++ _8 = opaque::(copy _6) -> [return: bb2, unwind continue]; } bb2: { @@ -80,12 +80,12 @@ - StorageLive(_13); + nop; StorageLive(_14); - _14 = _1; + _14 = copy _1; - _13 = Ne(move _14, const 15_i64); -+ _13 = Ne(_1, const 15_i64); ++ _13 = Ne(copy _1, const 15_i64); StorageDead(_14); - _12 = opaque::(move _13) -> [return: bb3, unwind continue]; -+ _12 = opaque::(_13) -> [return: bb3, unwind continue]; ++ _12 = opaque::(copy _13) -> [return: bb3, unwind continue]; } bb3: { @@ -96,15 +96,15 @@ StorageLive(_16); StorageLive(_17); StorageLive(_18); - _18 = _1; + _18 = copy _1; - _17 = Eq(move _18, const 15_i64); -+ _17 = Eq(_1, const 15_i64); ++ _17 = Eq(copy _1, const 15_i64); StorageDead(_18); - _16 = Not(move _17); -+ _16 = _13; ++ _16 = copy _13; StorageDead(_17); - _15 = opaque::(move _16) -> [return: bb4, unwind continue]; -+ _15 = opaque::(_13) -> [return: bb4, unwind continue]; ++ _15 = opaque::(copy _13) -> [return: bb4, unwind continue]; } bb4: { @@ -114,12 +114,12 @@ - StorageLive(_20); + nop; StorageLive(_21); - _21 = _1; + _21 = copy _1; - _20 = Eq(move _21, const 35_i64); -+ _20 = Eq(_1, const 35_i64); ++ _20 = Eq(copy _1, const 35_i64); StorageDead(_21); - _19 = opaque::(move _20) -> [return: bb5, unwind continue]; -+ _19 = opaque::(_20) -> [return: bb5, unwind continue]; ++ _19 = opaque::(copy _20) -> [return: bb5, unwind continue]; } bb5: { @@ -130,15 +130,15 @@ StorageLive(_23); StorageLive(_24); StorageLive(_25); - _25 = _1; + _25 = copy _1; - _24 = Ne(move _25, const 35_i64); -+ _24 = Ne(_1, const 35_i64); ++ _24 = Ne(copy _1, const 35_i64); StorageDead(_25); - _23 = Not(move _24); -+ _23 = _20; ++ _23 = copy _20; StorageDead(_24); - _22 = opaque::(move _23) -> [return: bb6, unwind continue]; -+ _22 = opaque::(_20) -> [return: bb6, unwind continue]; ++ _22 = opaque::(copy _20) -> [return: bb6, unwind continue]; } bb6: { diff --git a/tests/mir-opt/gvn.wide_ptr_integer.GVN.panic-abort.diff b/tests/mir-opt/gvn.wide_ptr_integer.GVN.panic-abort.diff index 3eed0473f7f..bb938f3ba6a 100644 --- a/tests/mir-opt/gvn.wide_ptr_integer.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.wide_ptr_integer.GVN.panic-abort.diff @@ -58,10 +58,10 @@ StorageLive(_5); StorageLive(_6); StorageLive(_7); -- _7 = _1; +- _7 = copy _1; + _7 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; StorageLive(_8); -- _8 = _3; +- _8 = copy _3; - _6 = Eq(move _7, move _8); + _8 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; + _6 = const false; @@ -77,10 +77,10 @@ StorageLive(_9); StorageLive(_10); StorageLive(_11); -- _11 = _1; +- _11 = copy _1; + _11 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; StorageLive(_12); -- _12 = _3; +- _12 = copy _3; - _10 = Ne(move _11, move _12); + _12 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; + _10 = const true; @@ -96,10 +96,10 @@ StorageLive(_13); StorageLive(_14); StorageLive(_15); -- _15 = _1; +- _15 = copy _1; + _15 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; StorageLive(_16); -- _16 = _3; +- _16 = copy _3; - _14 = Lt(move _15, move _16); + _16 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; + _14 = const true; @@ -115,10 +115,10 @@ StorageLive(_17); StorageLive(_18); StorageLive(_19); -- _19 = _1; +- _19 = copy _1; + _19 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; StorageLive(_20); -- _20 = _3; +- _20 = copy _3; - _18 = Le(move _19, move _20); + _20 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; + _18 = const true; @@ -134,10 +134,10 @@ StorageLive(_21); StorageLive(_22); StorageLive(_23); -- _23 = _1; +- _23 = copy _1; + _23 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; StorageLive(_24); -- _24 = _3; +- _24 = copy _3; - _22 = Gt(move _23, move _24); + _24 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; + _22 = const false; @@ -153,10 +153,10 @@ StorageLive(_25); StorageLive(_26); StorageLive(_27); -- _27 = _1; +- _27 = copy _1; + _27 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; StorageLive(_28); -- _28 = _3; +- _28 = copy _3; - _26 = Ge(move _27, move _28); + _28 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; + _26 = const false; diff --git a/tests/mir-opt/gvn.wide_ptr_integer.GVN.panic-unwind.diff b/tests/mir-opt/gvn.wide_ptr_integer.GVN.panic-unwind.diff index 9a6e255a872..81432d687eb 100644 --- a/tests/mir-opt/gvn.wide_ptr_integer.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.wide_ptr_integer.GVN.panic-unwind.diff @@ -58,10 +58,10 @@ StorageLive(_5); StorageLive(_6); StorageLive(_7); -- _7 = _1; +- _7 = copy _1; + _7 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; StorageLive(_8); -- _8 = _3; +- _8 = copy _3; - _6 = Eq(move _7, move _8); + _8 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; + _6 = const false; @@ -77,10 +77,10 @@ StorageLive(_9); StorageLive(_10); StorageLive(_11); -- _11 = _1; +- _11 = copy _1; + _11 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; StorageLive(_12); -- _12 = _3; +- _12 = copy _3; - _10 = Ne(move _11, move _12); + _12 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; + _10 = const true; @@ -96,10 +96,10 @@ StorageLive(_13); StorageLive(_14); StorageLive(_15); -- _15 = _1; +- _15 = copy _1; + _15 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; StorageLive(_16); -- _16 = _3; +- _16 = copy _3; - _14 = Lt(move _15, move _16); + _16 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; + _14 = const true; @@ -115,10 +115,10 @@ StorageLive(_17); StorageLive(_18); StorageLive(_19); -- _19 = _1; +- _19 = copy _1; + _19 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; StorageLive(_20); -- _20 = _3; +- _20 = copy _3; - _18 = Le(move _19, move _20); + _20 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; + _18 = const true; @@ -134,10 +134,10 @@ StorageLive(_21); StorageLive(_22); StorageLive(_23); -- _23 = _1; +- _23 = copy _1; + _23 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; StorageLive(_24); -- _24 = _3; +- _24 = copy _3; - _22 = Gt(move _23, move _24); + _24 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; + _22 = const false; @@ -153,10 +153,10 @@ StorageLive(_25); StorageLive(_26); StorageLive(_27); -- _27 = _1; +- _27 = copy _1; + _27 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; StorageLive(_28); -- _28 = _3; +- _28 = copy _3; - _26 = Ge(move _27, move _28); + _28 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; + _26 = const false; diff --git a/tests/mir-opt/gvn.wide_ptr_provenance.GVN.panic-abort.diff b/tests/mir-opt/gvn.wide_ptr_provenance.GVN.panic-abort.diff index 629c2225682..c58362e391c 100644 --- a/tests/mir-opt/gvn.wide_ptr_provenance.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.wide_ptr_provenance.GVN.panic-abort.diff @@ -69,7 +69,7 @@ _2 = &raw const (*_3); - _1 = move _2 as *const dyn std::marker::Send (PointerCoercion(Unsize)); - StorageDead(_2); -+ _1 = _2; ++ _1 = copy _2; + nop; StorageDead(_5); StorageDead(_3); @@ -87,24 +87,24 @@ _8 = &raw const (*_9); - _7 = move _8 as *const dyn std::marker::Send (PointerCoercion(Unsize)); - StorageDead(_8); -+ _7 = _8; ++ _7 = copy _8; + nop; StorageDead(_11); StorageDead(_9); StorageLive(_13); StorageLive(_14); StorageLive(_15); -- _15 = _1; -+ _15 = _2; +- _15 = copy _1; ++ _15 = copy _2; StorageLive(_16); StorageLive(_17); -- _17 = _7; +- _17 = copy _7; - _16 = move _17 as *const dyn std::marker::Send (PointerCoercion(Unsize)); -+ _17 = _8; -+ _16 = _8; ++ _17 = copy _8; ++ _16 = copy _8; StorageDead(_17); - _14 = Eq(move _15, move _16); -+ _14 = Eq(_2, _8); ++ _14 = Eq(copy _2, copy _8); StorageDead(_16); StorageDead(_15); _13 = opaque::(move _14) -> [return: bb1, unwind unreachable]; @@ -116,17 +116,17 @@ StorageLive(_18); StorageLive(_19); StorageLive(_20); -- _20 = _1; -+ _20 = _2; +- _20 = copy _1; ++ _20 = copy _2; StorageLive(_21); StorageLive(_22); -- _22 = _7; +- _22 = copy _7; - _21 = move _22 as *const dyn std::marker::Send (PointerCoercion(Unsize)); -+ _22 = _8; -+ _21 = _8; ++ _22 = copy _8; ++ _21 = copy _8; StorageDead(_22); - _19 = Ne(move _20, move _21); -+ _19 = Ne(_2, _8); ++ _19 = Ne(copy _2, copy _8); StorageDead(_21); StorageDead(_20); _18 = opaque::(move _19) -> [return: bb2, unwind unreachable]; @@ -138,17 +138,17 @@ StorageLive(_23); StorageLive(_24); StorageLive(_25); -- _25 = _1; -+ _25 = _2; +- _25 = copy _1; ++ _25 = copy _2; StorageLive(_26); StorageLive(_27); -- _27 = _7; +- _27 = copy _7; - _26 = move _27 as *const dyn std::marker::Send (PointerCoercion(Unsize)); -+ _27 = _8; -+ _26 = _8; ++ _27 = copy _8; ++ _26 = copy _8; StorageDead(_27); - _24 = Lt(move _25, move _26); -+ _24 = Lt(_2, _8); ++ _24 = Lt(copy _2, copy _8); StorageDead(_26); StorageDead(_25); _23 = opaque::(move _24) -> [return: bb3, unwind unreachable]; @@ -160,17 +160,17 @@ StorageLive(_28); StorageLive(_29); StorageLive(_30); -- _30 = _1; -+ _30 = _2; +- _30 = copy _1; ++ _30 = copy _2; StorageLive(_31); StorageLive(_32); -- _32 = _7; +- _32 = copy _7; - _31 = move _32 as *const dyn std::marker::Send (PointerCoercion(Unsize)); -+ _32 = _8; -+ _31 = _8; ++ _32 = copy _8; ++ _31 = copy _8; StorageDead(_32); - _29 = Le(move _30, move _31); -+ _29 = Le(_2, _8); ++ _29 = Le(copy _2, copy _8); StorageDead(_31); StorageDead(_30); _28 = opaque::(move _29) -> [return: bb4, unwind unreachable]; @@ -182,17 +182,17 @@ StorageLive(_33); StorageLive(_34); StorageLive(_35); -- _35 = _1; -+ _35 = _2; +- _35 = copy _1; ++ _35 = copy _2; StorageLive(_36); StorageLive(_37); -- _37 = _7; +- _37 = copy _7; - _36 = move _37 as *const dyn std::marker::Send (PointerCoercion(Unsize)); -+ _37 = _8; -+ _36 = _8; ++ _37 = copy _8; ++ _36 = copy _8; StorageDead(_37); - _34 = Gt(move _35, move _36); -+ _34 = Gt(_2, _8); ++ _34 = Gt(copy _2, copy _8); StorageDead(_36); StorageDead(_35); _33 = opaque::(move _34) -> [return: bb5, unwind unreachable]; @@ -204,17 +204,17 @@ StorageLive(_38); StorageLive(_39); StorageLive(_40); -- _40 = _1; -+ _40 = _2; +- _40 = copy _1; ++ _40 = copy _2; StorageLive(_41); StorageLive(_42); -- _42 = _7; +- _42 = copy _7; - _41 = move _42 as *const dyn std::marker::Send (PointerCoercion(Unsize)); -+ _42 = _8; -+ _41 = _8; ++ _42 = copy _8; ++ _41 = copy _8; StorageDead(_42); - _39 = Ge(move _40, move _41); -+ _39 = Ge(_2, _8); ++ _39 = Ge(copy _2, copy _8); StorageDead(_41); StorageDead(_40); _38 = opaque::(move _39) -> [return: bb6, unwind unreachable]; diff --git a/tests/mir-opt/gvn.wide_ptr_provenance.GVN.panic-unwind.diff b/tests/mir-opt/gvn.wide_ptr_provenance.GVN.panic-unwind.diff index 3380bc84cb8..b29ee862c81 100644 --- a/tests/mir-opt/gvn.wide_ptr_provenance.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.wide_ptr_provenance.GVN.panic-unwind.diff @@ -69,7 +69,7 @@ _2 = &raw const (*_3); - _1 = move _2 as *const dyn std::marker::Send (PointerCoercion(Unsize)); - StorageDead(_2); -+ _1 = _2; ++ _1 = copy _2; + nop; StorageDead(_5); StorageDead(_3); @@ -87,24 +87,24 @@ _8 = &raw const (*_9); - _7 = move _8 as *const dyn std::marker::Send (PointerCoercion(Unsize)); - StorageDead(_8); -+ _7 = _8; ++ _7 = copy _8; + nop; StorageDead(_11); StorageDead(_9); StorageLive(_13); StorageLive(_14); StorageLive(_15); -- _15 = _1; -+ _15 = _2; +- _15 = copy _1; ++ _15 = copy _2; StorageLive(_16); StorageLive(_17); -- _17 = _7; +- _17 = copy _7; - _16 = move _17 as *const dyn std::marker::Send (PointerCoercion(Unsize)); -+ _17 = _8; -+ _16 = _8; ++ _17 = copy _8; ++ _16 = copy _8; StorageDead(_17); - _14 = Eq(move _15, move _16); -+ _14 = Eq(_2, _8); ++ _14 = Eq(copy _2, copy _8); StorageDead(_16); StorageDead(_15); _13 = opaque::(move _14) -> [return: bb1, unwind continue]; @@ -116,17 +116,17 @@ StorageLive(_18); StorageLive(_19); StorageLive(_20); -- _20 = _1; -+ _20 = _2; +- _20 = copy _1; ++ _20 = copy _2; StorageLive(_21); StorageLive(_22); -- _22 = _7; +- _22 = copy _7; - _21 = move _22 as *const dyn std::marker::Send (PointerCoercion(Unsize)); -+ _22 = _8; -+ _21 = _8; ++ _22 = copy _8; ++ _21 = copy _8; StorageDead(_22); - _19 = Ne(move _20, move _21); -+ _19 = Ne(_2, _8); ++ _19 = Ne(copy _2, copy _8); StorageDead(_21); StorageDead(_20); _18 = opaque::(move _19) -> [return: bb2, unwind continue]; @@ -138,17 +138,17 @@ StorageLive(_23); StorageLive(_24); StorageLive(_25); -- _25 = _1; -+ _25 = _2; +- _25 = copy _1; ++ _25 = copy _2; StorageLive(_26); StorageLive(_27); -- _27 = _7; +- _27 = copy _7; - _26 = move _27 as *const dyn std::marker::Send (PointerCoercion(Unsize)); -+ _27 = _8; -+ _26 = _8; ++ _27 = copy _8; ++ _26 = copy _8; StorageDead(_27); - _24 = Lt(move _25, move _26); -+ _24 = Lt(_2, _8); ++ _24 = Lt(copy _2, copy _8); StorageDead(_26); StorageDead(_25); _23 = opaque::(move _24) -> [return: bb3, unwind continue]; @@ -160,17 +160,17 @@ StorageLive(_28); StorageLive(_29); StorageLive(_30); -- _30 = _1; -+ _30 = _2; +- _30 = copy _1; ++ _30 = copy _2; StorageLive(_31); StorageLive(_32); -- _32 = _7; +- _32 = copy _7; - _31 = move _32 as *const dyn std::marker::Send (PointerCoercion(Unsize)); -+ _32 = _8; -+ _31 = _8; ++ _32 = copy _8; ++ _31 = copy _8; StorageDead(_32); - _29 = Le(move _30, move _31); -+ _29 = Le(_2, _8); ++ _29 = Le(copy _2, copy _8); StorageDead(_31); StorageDead(_30); _28 = opaque::(move _29) -> [return: bb4, unwind continue]; @@ -182,17 +182,17 @@ StorageLive(_33); StorageLive(_34); StorageLive(_35); -- _35 = _1; -+ _35 = _2; +- _35 = copy _1; ++ _35 = copy _2; StorageLive(_36); StorageLive(_37); -- _37 = _7; +- _37 = copy _7; - _36 = move _37 as *const dyn std::marker::Send (PointerCoercion(Unsize)); -+ _37 = _8; -+ _36 = _8; ++ _37 = copy _8; ++ _36 = copy _8; StorageDead(_37); - _34 = Gt(move _35, move _36); -+ _34 = Gt(_2, _8); ++ _34 = Gt(copy _2, copy _8); StorageDead(_36); StorageDead(_35); _33 = opaque::(move _34) -> [return: bb5, unwind continue]; @@ -204,17 +204,17 @@ StorageLive(_38); StorageLive(_39); StorageLive(_40); -- _40 = _1; -+ _40 = _2; +- _40 = copy _1; ++ _40 = copy _2; StorageLive(_41); StorageLive(_42); -- _42 = _7; +- _42 = copy _7; - _41 = move _42 as *const dyn std::marker::Send (PointerCoercion(Unsize)); -+ _42 = _8; -+ _41 = _8; ++ _42 = copy _8; ++ _41 = copy _8; StorageDead(_42); - _39 = Ge(move _40, move _41); -+ _39 = Ge(_2, _8); ++ _39 = Ge(copy _2, copy _8); StorageDead(_41); StorageDead(_40); _38 = opaque::(move _39) -> [return: bb6, unwind continue]; diff --git a/tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-abort.diff b/tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-abort.diff index da1662615d2..f4c38b7ab07 100644 --- a/tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-abort.diff @@ -75,8 +75,8 @@ StorageLive(_8); _8 = const 0_usize; - _9 = Len((*_1)); -- _10 = Lt(_8, _9); -- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> [success: bb1, unwind unreachable]; +- _10 = Lt(copy _8, copy _9); +- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, copy _8) -> [success: bb1, unwind unreachable]; + _9 = const 2_usize; + _10 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 2_usize, const 0_usize) -> [success: bb1, unwind unreachable]; @@ -91,7 +91,7 @@ _4 = &raw const (*_5); - _3 = move _4 as *const dyn std::marker::Send (PointerCoercion(Unsize)); - StorageDead(_4); -+ _3 = _4; ++ _3 = copy _4; + nop; StorageDead(_7); StorageDead(_5); @@ -104,8 +104,8 @@ StorageLive(_16); _16 = const 1_usize; - _17 = Len((*_1)); -- _18 = Lt(_16, _17); -- assert(move _18, "index out of bounds: the length is {} but the index is {}", move _17, _16) -> [success: bb2, unwind unreachable]; +- _18 = Lt(copy _16, copy _17); +- assert(move _18, "index out of bounds: the length is {} but the index is {}", move _17, copy _16) -> [success: bb2, unwind unreachable]; + _17 = const 2_usize; + _18 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 2_usize, const 1_usize) -> [success: bb2, unwind unreachable]; @@ -120,24 +120,24 @@ _12 = &raw const (*_13); - _11 = move _12 as *const dyn std::marker::Send (PointerCoercion(Unsize)); - StorageDead(_12); -+ _11 = _12; ++ _11 = copy _12; + nop; StorageDead(_15); StorageDead(_13); StorageLive(_19); StorageLive(_20); StorageLive(_21); -- _21 = _3; -+ _21 = _4; +- _21 = copy _3; ++ _21 = copy _4; StorageLive(_22); StorageLive(_23); -- _23 = _11; +- _23 = copy _11; - _22 = move _23 as *const dyn std::marker::Send (PointerCoercion(Unsize)); -+ _23 = _12; -+ _22 = _12; ++ _23 = copy _12; ++ _22 = copy _12; StorageDead(_23); - _20 = Eq(move _21, move _22); -+ _20 = Eq(_4, _12); ++ _20 = Eq(copy _4, copy _12); StorageDead(_22); StorageDead(_21); _19 = opaque::(move _20) -> [return: bb3, unwind unreachable]; @@ -149,17 +149,17 @@ StorageLive(_24); StorageLive(_25); StorageLive(_26); -- _26 = _3; -+ _26 = _4; +- _26 = copy _3; ++ _26 = copy _4; StorageLive(_27); StorageLive(_28); -- _28 = _11; +- _28 = copy _11; - _27 = move _28 as *const dyn std::marker::Send (PointerCoercion(Unsize)); -+ _28 = _12; -+ _27 = _12; ++ _28 = copy _12; ++ _27 = copy _12; StorageDead(_28); - _25 = Ne(move _26, move _27); -+ _25 = Ne(_4, _12); ++ _25 = Ne(copy _4, copy _12); StorageDead(_27); StorageDead(_26); _24 = opaque::(move _25) -> [return: bb4, unwind unreachable]; @@ -171,17 +171,17 @@ StorageLive(_29); StorageLive(_30); StorageLive(_31); -- _31 = _3; -+ _31 = _4; +- _31 = copy _3; ++ _31 = copy _4; StorageLive(_32); StorageLive(_33); -- _33 = _11; +- _33 = copy _11; - _32 = move _33 as *const dyn std::marker::Send (PointerCoercion(Unsize)); -+ _33 = _12; -+ _32 = _12; ++ _33 = copy _12; ++ _32 = copy _12; StorageDead(_33); - _30 = Lt(move _31, move _32); -+ _30 = Lt(_4, _12); ++ _30 = Lt(copy _4, copy _12); StorageDead(_32); StorageDead(_31); _29 = opaque::(move _30) -> [return: bb5, unwind unreachable]; @@ -193,17 +193,17 @@ StorageLive(_34); StorageLive(_35); StorageLive(_36); -- _36 = _3; -+ _36 = _4; +- _36 = copy _3; ++ _36 = copy _4; StorageLive(_37); StorageLive(_38); -- _38 = _11; +- _38 = copy _11; - _37 = move _38 as *const dyn std::marker::Send (PointerCoercion(Unsize)); -+ _38 = _12; -+ _37 = _12; ++ _38 = copy _12; ++ _37 = copy _12; StorageDead(_38); - _35 = Le(move _36, move _37); -+ _35 = Le(_4, _12); ++ _35 = Le(copy _4, copy _12); StorageDead(_37); StorageDead(_36); _34 = opaque::(move _35) -> [return: bb6, unwind unreachable]; @@ -215,17 +215,17 @@ StorageLive(_39); StorageLive(_40); StorageLive(_41); -- _41 = _3; -+ _41 = _4; +- _41 = copy _3; ++ _41 = copy _4; StorageLive(_42); StorageLive(_43); -- _43 = _11; +- _43 = copy _11; - _42 = move _43 as *const dyn std::marker::Send (PointerCoercion(Unsize)); -+ _43 = _12; -+ _42 = _12; ++ _43 = copy _12; ++ _42 = copy _12; StorageDead(_43); - _40 = Gt(move _41, move _42); -+ _40 = Gt(_4, _12); ++ _40 = Gt(copy _4, copy _12); StorageDead(_42); StorageDead(_41); _39 = opaque::(move _40) -> [return: bb7, unwind unreachable]; @@ -237,17 +237,17 @@ StorageLive(_44); StorageLive(_45); StorageLive(_46); -- _46 = _3; -+ _46 = _4; +- _46 = copy _3; ++ _46 = copy _4; StorageLive(_47); StorageLive(_48); -- _48 = _11; +- _48 = copy _11; - _47 = move _48 as *const dyn std::marker::Send (PointerCoercion(Unsize)); -+ _48 = _12; -+ _47 = _12; ++ _48 = copy _12; ++ _47 = copy _12; StorageDead(_48); - _45 = Ge(move _46, move _47); -+ _45 = Ge(_4, _12); ++ _45 = Ge(copy _4, copy _12); StorageDead(_47); StorageDead(_46); _44 = opaque::(move _45) -> [return: bb8, unwind unreachable]; diff --git a/tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-unwind.diff b/tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-unwind.diff index 6c4f3a91264..03f2d129a9b 100644 --- a/tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-unwind.diff @@ -75,8 +75,8 @@ StorageLive(_8); _8 = const 0_usize; - _9 = Len((*_1)); -- _10 = Lt(_8, _9); -- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> [success: bb1, unwind continue]; +- _10 = Lt(copy _8, copy _9); +- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, copy _8) -> [success: bb1, unwind continue]; + _9 = const 2_usize; + _10 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 2_usize, const 0_usize) -> [success: bb1, unwind continue]; @@ -91,7 +91,7 @@ _4 = &raw const (*_5); - _3 = move _4 as *const dyn std::marker::Send (PointerCoercion(Unsize)); - StorageDead(_4); -+ _3 = _4; ++ _3 = copy _4; + nop; StorageDead(_7); StorageDead(_5); @@ -104,8 +104,8 @@ StorageLive(_16); _16 = const 1_usize; - _17 = Len((*_1)); -- _18 = Lt(_16, _17); -- assert(move _18, "index out of bounds: the length is {} but the index is {}", move _17, _16) -> [success: bb2, unwind continue]; +- _18 = Lt(copy _16, copy _17); +- assert(move _18, "index out of bounds: the length is {} but the index is {}", move _17, copy _16) -> [success: bb2, unwind continue]; + _17 = const 2_usize; + _18 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 2_usize, const 1_usize) -> [success: bb2, unwind continue]; @@ -120,24 +120,24 @@ _12 = &raw const (*_13); - _11 = move _12 as *const dyn std::marker::Send (PointerCoercion(Unsize)); - StorageDead(_12); -+ _11 = _12; ++ _11 = copy _12; + nop; StorageDead(_15); StorageDead(_13); StorageLive(_19); StorageLive(_20); StorageLive(_21); -- _21 = _3; -+ _21 = _4; +- _21 = copy _3; ++ _21 = copy _4; StorageLive(_22); StorageLive(_23); -- _23 = _11; +- _23 = copy _11; - _22 = move _23 as *const dyn std::marker::Send (PointerCoercion(Unsize)); -+ _23 = _12; -+ _22 = _12; ++ _23 = copy _12; ++ _22 = copy _12; StorageDead(_23); - _20 = Eq(move _21, move _22); -+ _20 = Eq(_4, _12); ++ _20 = Eq(copy _4, copy _12); StorageDead(_22); StorageDead(_21); _19 = opaque::(move _20) -> [return: bb3, unwind continue]; @@ -149,17 +149,17 @@ StorageLive(_24); StorageLive(_25); StorageLive(_26); -- _26 = _3; -+ _26 = _4; +- _26 = copy _3; ++ _26 = copy _4; StorageLive(_27); StorageLive(_28); -- _28 = _11; +- _28 = copy _11; - _27 = move _28 as *const dyn std::marker::Send (PointerCoercion(Unsize)); -+ _28 = _12; -+ _27 = _12; ++ _28 = copy _12; ++ _27 = copy _12; StorageDead(_28); - _25 = Ne(move _26, move _27); -+ _25 = Ne(_4, _12); ++ _25 = Ne(copy _4, copy _12); StorageDead(_27); StorageDead(_26); _24 = opaque::(move _25) -> [return: bb4, unwind continue]; @@ -171,17 +171,17 @@ StorageLive(_29); StorageLive(_30); StorageLive(_31); -- _31 = _3; -+ _31 = _4; +- _31 = copy _3; ++ _31 = copy _4; StorageLive(_32); StorageLive(_33); -- _33 = _11; +- _33 = copy _11; - _32 = move _33 as *const dyn std::marker::Send (PointerCoercion(Unsize)); -+ _33 = _12; -+ _32 = _12; ++ _33 = copy _12; ++ _32 = copy _12; StorageDead(_33); - _30 = Lt(move _31, move _32); -+ _30 = Lt(_4, _12); ++ _30 = Lt(copy _4, copy _12); StorageDead(_32); StorageDead(_31); _29 = opaque::(move _30) -> [return: bb5, unwind continue]; @@ -193,17 +193,17 @@ StorageLive(_34); StorageLive(_35); StorageLive(_36); -- _36 = _3; -+ _36 = _4; +- _36 = copy _3; ++ _36 = copy _4; StorageLive(_37); StorageLive(_38); -- _38 = _11; +- _38 = copy _11; - _37 = move _38 as *const dyn std::marker::Send (PointerCoercion(Unsize)); -+ _38 = _12; -+ _37 = _12; ++ _38 = copy _12; ++ _37 = copy _12; StorageDead(_38); - _35 = Le(move _36, move _37); -+ _35 = Le(_4, _12); ++ _35 = Le(copy _4, copy _12); StorageDead(_37); StorageDead(_36); _34 = opaque::(move _35) -> [return: bb6, unwind continue]; @@ -215,17 +215,17 @@ StorageLive(_39); StorageLive(_40); StorageLive(_41); -- _41 = _3; -+ _41 = _4; +- _41 = copy _3; ++ _41 = copy _4; StorageLive(_42); StorageLive(_43); -- _43 = _11; +- _43 = copy _11; - _42 = move _43 as *const dyn std::marker::Send (PointerCoercion(Unsize)); -+ _43 = _12; -+ _42 = _12; ++ _43 = copy _12; ++ _42 = copy _12; StorageDead(_43); - _40 = Gt(move _41, move _42); -+ _40 = Gt(_4, _12); ++ _40 = Gt(copy _4, copy _12); StorageDead(_42); StorageDead(_41); _39 = opaque::(move _40) -> [return: bb7, unwind continue]; @@ -237,17 +237,17 @@ StorageLive(_44); StorageLive(_45); StorageLive(_46); -- _46 = _3; -+ _46 = _4; +- _46 = copy _3; ++ _46 = copy _4; StorageLive(_47); StorageLive(_48); -- _48 = _11; +- _48 = copy _11; - _47 = move _48 as *const dyn std::marker::Send (PointerCoercion(Unsize)); -+ _48 = _12; -+ _47 = _12; ++ _48 = copy _12; ++ _47 = copy _12; StorageDead(_48); - _45 = Ge(move _46, move _47); -+ _45 = Ge(_4, _12); ++ _45 = Ge(copy _4, copy _12); StorageDead(_47); StorageDead(_46); _44 = opaque::(move _45) -> [return: bb8, unwind continue]; diff --git a/tests/mir-opt/gvn.wrap_unwrap.GVN.panic-abort.diff b/tests/mir-opt/gvn.wrap_unwrap.GVN.panic-abort.diff index a5c29c191ad..0433152bb4f 100644 --- a/tests/mir-opt/gvn.wrap_unwrap.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.wrap_unwrap.GVN.panic-abort.diff @@ -16,9 +16,9 @@ bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; - _2 = Option::::Some(move _3); -+ _2 = Option::::Some(_1); ++ _2 = Option::::Some(copy _1); StorageDead(_3); - _4 = discriminant(_2); - switchInt(move _4) -> [0: bb2, 1: bb3, otherwise: bb1]; @@ -37,10 +37,10 @@ bb3: { StorageLive(_5); -- _5 = ((_2 as Some).0: T); -- _0 = _5; -+ _5 = _1; -+ _0 = _1; +- _5 = copy ((_2 as Some).0: T); +- _0 = copy _5; ++ _5 = copy _1; ++ _0 = copy _1; StorageDead(_5); StorageDead(_2); return; diff --git a/tests/mir-opt/gvn.wrap_unwrap.GVN.panic-unwind.diff b/tests/mir-opt/gvn.wrap_unwrap.GVN.panic-unwind.diff index 6f2e5248271..5722c865c2f 100644 --- a/tests/mir-opt/gvn.wrap_unwrap.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.wrap_unwrap.GVN.panic-unwind.diff @@ -16,9 +16,9 @@ bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; - _2 = Option::::Some(move _3); -+ _2 = Option::::Some(_1); ++ _2 = Option::::Some(copy _1); StorageDead(_3); - _4 = discriminant(_2); - switchInt(move _4) -> [0: bb2, 1: bb3, otherwise: bb1]; @@ -37,10 +37,10 @@ bb3: { StorageLive(_5); -- _5 = ((_2 as Some).0: T); -- _0 = _5; -+ _5 = _1; -+ _0 = _1; +- _5 = copy ((_2 as Some).0: T); +- _0 = copy _5; ++ _5 = copy _1; ++ _0 = copy _1; StorageDead(_5); StorageDead(_2); return; diff --git a/tests/mir-opt/gvn_copy_moves.fn0.GVN.diff b/tests/mir-opt/gvn_copy_moves.fn0.GVN.diff index b12de636f58..c364da7a3cc 100644 --- a/tests/mir-opt/gvn_copy_moves.fn0.GVN.diff +++ b/tests/mir-opt/gvn_copy_moves.fn0.GVN.diff @@ -14,10 +14,10 @@ _2 = [const 42_u128; 6]; - _2[_1] = const 1_u128; + _2[1 of 2] = const 1_u128; - _3 = (_2,); - _4 = _3; -- _5 = fn1(move (_3.0: [u128; 6]), _4) -> [return: bb1, unwind unreachable]; -+ _5 = fn1((_3.0: [u128; 6]), _3) -> [return: bb1, unwind unreachable]; + _3 = (copy _2,); + _4 = copy _3; +- _5 = fn1(move (_3.0: [u128; 6]), copy _4) -> [return: bb1, unwind unreachable]; ++ _5 = fn1(copy (_3.0: [u128; 6]), copy _3) -> [return: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/gvn_copy_moves.rs b/tests/mir-opt/gvn_copy_moves.rs index 1812de16d69..b1fe2caf3a1 100644 --- a/tests/mir-opt/gvn_copy_moves.rs +++ b/tests/mir-opt/gvn_copy_moves.rs @@ -18,9 +18,9 @@ fn fn0() { // CHECK-NEXT: _1 = const 1_usize; // CHECK-NEXT: _2 = [const 42_u128; 6]; // CHECK-NEXT: _2[1 of 2] = const 1_u128; - // CHECK-NEXT: _3 = (_2,); - // CHECK-NEXT: _4 = _3; - // CHECK-NEXT: _5 = fn1((_3.0: [u128; 6]), _3) + // CHECK-NEXT: _3 = (copy _2,); + // CHECK-NEXT: _4 = copy _3; + // CHECK-NEXT: _5 = fn1(copy (_3.0: [u128; 6]), copy _3) a = 1_usize; b = [42; 6]; b[a] = 1; diff --git a/tests/mir-opt/gvn_ptr_eq_with_constant.main.GVN.diff b/tests/mir-opt/gvn_ptr_eq_with_constant.main.GVN.diff index 3af78d9b6ce..1e378d30a3e 100644 --- a/tests/mir-opt/gvn_ptr_eq_with_constant.main.GVN.diff +++ b/tests/mir-opt/gvn_ptr_eq_with_constant.main.GVN.diff @@ -25,20 +25,20 @@ StorageLive(_2); StorageLive(_3); - _3 = AlignOf(u8); -- _2 = _3 as *mut u8 (Transmute); +- _2 = copy _3 as *mut u8 (Transmute); + _3 = const 1_usize; + _2 = const {0x1 as *mut u8}; StorageDead(_3); StorageLive(_4); StorageLive(_5); -- _5 = _2; -- _4 = _2 as *const u8 (PtrToPtr); +- _5 = copy _2; +- _4 = copy _2 as *const u8 (PtrToPtr); + _5 = const {0x1 as *mut u8}; + _4 = const {0x1 as *const u8}; StorageDead(_5); StorageLive(_6); - _6 = const Foo::::SENTINEL as *const u8 (PtrToPtr); -- _1 = Eq(_4, _6); +- _1 = Eq(copy _4, copy _6); + _6 = const {0x1 as *const u8}; + _1 = const true; StorageDead(_6); diff --git a/tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff index 626367766d7..37b7b0d2c9d 100644 --- a/tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff @@ -17,14 +17,14 @@ StorageLive(_3); _5 = const f::promoted[0]; _3 = &(*_5); -- _2 = ((*_3).1: E); -+ _2 = ((*_5).1: E); +- _2 = copy ((*_3).1: E); ++ _2 = copy ((*_5).1: E); StorageLive(_1); -- _1 = ((_2 as A).1: u32); +- _1 = copy ((_2 as A).1: u32); + _1 = const 0_u32; StorageDead(_3); StorageDead(_2); -- _0 = _1; +- _0 = copy _1; + _0 = const 0_u32; StorageDead(_1); return; diff --git a/tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff index 626367766d7..37b7b0d2c9d 100644 --- a/tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff @@ -17,14 +17,14 @@ StorageLive(_3); _5 = const f::promoted[0]; _3 = &(*_5); -- _2 = ((*_3).1: E); -+ _2 = ((*_5).1: E); +- _2 = copy ((*_3).1: E); ++ _2 = copy ((*_5).1: E); StorageLive(_1); -- _1 = ((_2 as A).1: u32); +- _1 = copy ((_2 as A).1: u32); + _1 = const 0_u32; StorageDead(_3); StorageDead(_2); -- _0 = _1; +- _0 = copy _1; + _0 = const 0_u32; StorageDead(_1); return; diff --git a/tests/mir-opt/if_condition_int.dont_opt_bool.SimplifyComparisonIntegral.diff b/tests/mir-opt/if_condition_int.dont_opt_bool.SimplifyComparisonIntegral.diff index 083515aebc6..2350faa05d3 100644 --- a/tests/mir-opt/if_condition_int.dont_opt_bool.SimplifyComparisonIntegral.diff +++ b/tests/mir-opt/if_condition_int.dont_opt_bool.SimplifyComparisonIntegral.diff @@ -8,7 +8,7 @@ bb0: { StorageLive(_2); - _2 = _1; + _2 = copy _1; switchInt(move _2) -> [0: bb2, otherwise: bb1]; } diff --git a/tests/mir-opt/if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff b/tests/mir-opt/if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff index 15319586062..94570017730 100644 --- a/tests/mir-opt/if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff +++ b/tests/mir-opt/if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff @@ -10,7 +10,7 @@ bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; _2 = Eq(move _3, const -42f32); switchInt(move _2) -> [0: bb2, otherwise: bb1]; } diff --git a/tests/mir-opt/if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff b/tests/mir-opt/if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff index 218d7fd59b7..d19b4148405 100644 --- a/tests/mir-opt/if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff +++ b/tests/mir-opt/if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff @@ -17,11 +17,11 @@ bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; - _2 = Eq(move _3, const 17_i8); - StorageDead(_3); -- switchInt(_2) -> [0: bb2, otherwise: bb1]; -+ _2 = Eq(_3, const 17_i8); +- switchInt(copy _2) -> [0: bb2, otherwise: bb1]; ++ _2 = Eq(copy _3, const 17_i8); + nop; + switchInt(move _3) -> [17: bb1, otherwise: bb2]; } @@ -30,7 +30,7 @@ + StorageDead(_3); StorageLive(_6); StorageLive(_7); - _7 = _2; + _7 = copy _2; _6 = move _7 as i32 (IntToInt); StorageDead(_7); _0 = Add(const 100_i32, move _6); @@ -42,7 +42,7 @@ + StorageDead(_3); StorageLive(_4); StorageLive(_5); - _5 = _2; + _5 = copy _2; _4 = move _5 as i32 (IntToInt); StorageDead(_5); _0 = Add(const 10_i32, move _4); diff --git a/tests/mir-opt/if_condition_int.opt_char.SimplifyComparisonIntegral.diff b/tests/mir-opt/if_condition_int.opt_char.SimplifyComparisonIntegral.diff index fedbd6cdd24..e47b7e52259 100644 --- a/tests/mir-opt/if_condition_int.opt_char.SimplifyComparisonIntegral.diff +++ b/tests/mir-opt/if_condition_int.opt_char.SimplifyComparisonIntegral.diff @@ -10,7 +10,7 @@ bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; - _2 = Eq(move _3, const 'x'); - switchInt(move _2) -> [0: bb2, otherwise: bb1]; + nop; diff --git a/tests/mir-opt/if_condition_int.opt_i8.SimplifyComparisonIntegral.diff b/tests/mir-opt/if_condition_int.opt_i8.SimplifyComparisonIntegral.diff index 9c38d8fe065..b6cdc6af8bf 100644 --- a/tests/mir-opt/if_condition_int.opt_i8.SimplifyComparisonIntegral.diff +++ b/tests/mir-opt/if_condition_int.opt_i8.SimplifyComparisonIntegral.diff @@ -10,7 +10,7 @@ bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; - _2 = Eq(move _3, const 42_i8); - switchInt(move _2) -> [0: bb2, otherwise: bb1]; + nop; diff --git a/tests/mir-opt/if_condition_int.opt_multiple_ifs.SimplifyComparisonIntegral.diff b/tests/mir-opt/if_condition_int.opt_multiple_ifs.SimplifyComparisonIntegral.diff index 8c85ce78565..31745ac732a 100644 --- a/tests/mir-opt/if_condition_int.opt_multiple_ifs.SimplifyComparisonIntegral.diff +++ b/tests/mir-opt/if_condition_int.opt_multiple_ifs.SimplifyComparisonIntegral.diff @@ -12,7 +12,7 @@ bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; - _2 = Eq(move _3, const 42_u32); - switchInt(move _2) -> [0: bb2, otherwise: bb1]; + nop; @@ -29,7 +29,7 @@ StorageDead(_3); StorageLive(_4); StorageLive(_5); - _5 = _1; + _5 = copy _1; - _4 = Ne(move _5, const 21_u32); - switchInt(move _4) -> [0: bb4, otherwise: bb3]; + nop; diff --git a/tests/mir-opt/if_condition_int.opt_negative.SimplifyComparisonIntegral.diff b/tests/mir-opt/if_condition_int.opt_negative.SimplifyComparisonIntegral.diff index 876ed61e9fa..d747985f6e1 100644 --- a/tests/mir-opt/if_condition_int.opt_negative.SimplifyComparisonIntegral.diff +++ b/tests/mir-opt/if_condition_int.opt_negative.SimplifyComparisonIntegral.diff @@ -10,7 +10,7 @@ bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; - _2 = Eq(move _3, const -42_i32); - switchInt(move _2) -> [0: bb2, otherwise: bb1]; + nop; diff --git a/tests/mir-opt/if_condition_int.opt_u32.SimplifyComparisonIntegral.diff b/tests/mir-opt/if_condition_int.opt_u32.SimplifyComparisonIntegral.diff index ed3eb47dd3d..1d6809a9438 100644 --- a/tests/mir-opt/if_condition_int.opt_u32.SimplifyComparisonIntegral.diff +++ b/tests/mir-opt/if_condition_int.opt_u32.SimplifyComparisonIntegral.diff @@ -10,7 +10,7 @@ bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; - _2 = Eq(move _3, const 42_u32); - switchInt(move _2) -> [0: bb2, otherwise: bb1]; + nop; diff --git a/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-abort.diff b/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-abort.diff index 4e495c37fbc..2d64d49ce5c 100644 --- a/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-abort.diff @@ -21,17 +21,17 @@ bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; _2 = ::cache::(move _3) -> [return: bb1, unwind unreachable]; } bb1: { StorageDead(_3); StorageLive(_4); - _4 = _2; + _4 = copy _2; - _0 = try_execute_query::<::C>(move _4) -> [return: bb2, unwind unreachable]; + StorageLive(_5); -+ _5 = _4 as &dyn Cache::V> (PointerCoercion(Unsize)); ++ _5 = copy _4 as &dyn Cache::V> (PointerCoercion(Unsize)); + _0 = ::V> as Cache>::store_nocache(move _5) -> [return: bb2, unwind unreachable]; } diff --git a/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-unwind.diff b/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-unwind.diff index 7fdb7618212..c5e9654e19c 100644 --- a/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-unwind.diff @@ -21,17 +21,17 @@ bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; _2 = ::cache::(move _3) -> [return: bb1, unwind continue]; } bb1: { StorageDead(_3); StorageLive(_4); - _4 = _2; + _4 = copy _2; - _0 = try_execute_query::<::C>(move _4) -> [return: bb2, unwind continue]; + StorageLive(_5); -+ _5 = _4 as &dyn Cache::V> (PointerCoercion(Unsize)); ++ _5 = copy _4 as &dyn Cache::V> (PointerCoercion(Unsize)); + _0 = ::V> as Cache>::store_nocache(move _5) -> [return: bb2, unwind continue]; } diff --git a/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.panic-abort.diff b/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.panic-abort.diff index 8df4408690b..13bc54424d1 100644 --- a/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.panic-abort.diff @@ -8,7 +8,7 @@ bb0: { StorageLive(_2); - _2 = _1; + _2 = copy _1; _0 = as Cache>::store_nocache(move _2) -> [return: bb1, unwind unreachable]; } diff --git a/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.panic-unwind.diff b/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.panic-unwind.diff index 43a0621f766..35d4db37802 100644 --- a/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.panic-unwind.diff @@ -8,7 +8,7 @@ bb0: { StorageLive(_2); - _2 = _1; + _2 = copy _1; _0 = as Cache>::store_nocache(move _2) -> [return: bb1, unwind continue]; } diff --git a/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-abort.diff b/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-abort.diff index e72c312f549..f02ca623317 100644 --- a/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-abort.diff @@ -13,7 +13,7 @@ bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; _2 = move _3 as &dyn Cache::V> (PointerCoercion(Unsize)); StorageDead(_3); - _0 = mk_cycle::<::V>(move _2) -> [return: bb1, unwind unreachable]; diff --git a/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-unwind.diff b/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-unwind.diff index 46728f9e2e6..31080dff4de 100644 --- a/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-unwind.diff @@ -13,7 +13,7 @@ bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; _2 = move _3 as &dyn Cache::V> (PointerCoercion(Unsize)); StorageDead(_3); - _0 = mk_cycle::<::V>(move _2) -> [return: bb1, unwind continue]; diff --git a/tests/mir-opt/inline/inline_any_operand.bar.Inline.after.mir b/tests/mir-opt/inline/inline_any_operand.bar.Inline.after.mir index 2d0b71e0a64..0ee5968419a 100644 --- a/tests/mir-opt/inline/inline_any_operand.bar.Inline.after.mir +++ b/tests/mir-opt/inline/inline_any_operand.bar.Inline.after.mir @@ -18,12 +18,12 @@ fn bar() -> bool { StorageLive(_1); _1 = foo; StorageLive(_2); - _2 = _1; + _2 = copy _1; StorageLive(_3); _3 = const 1_i32; StorageLive(_4); _4 = const -1_i32; - _0 = Eq(_3, _4); + _0 = Eq(copy _3, copy _4); StorageDead(_4); StorageDead(_3); StorageDead(_2); diff --git a/tests/mir-opt/inline/inline_closure.foo.Inline.after.mir b/tests/mir-opt/inline/inline_closure.foo.Inline.after.mir index 8a60f4b1bdc..5bc227c87df 100644 --- a/tests/mir-opt/inline/inline_closure.foo.Inline.after.mir +++ b/tests/mir-opt/inline/inline_closure.foo.Inline.after.mir @@ -26,15 +26,15 @@ fn foo(_1: T, _2: i32) -> i32 { _4 = &_3; StorageLive(_5); StorageLive(_6); - _6 = _2; + _6 = copy _2; StorageLive(_7); - _7 = _2; + _7 = copy _2; _5 = (move _6, move _7); StorageLive(_8); _8 = move (_5.0: i32); StorageLive(_9); _9 = move (_5.1: i32); - _0 = _8; + _0 = copy _8; StorageDead(_9); StorageDead(_8); StorageDead(_7); diff --git a/tests/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir b/tests/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir index f524b054b61..7930111cf22 100644 --- a/tests/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir +++ b/tests/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir @@ -26,15 +26,15 @@ fn foo(_1: T, _2: &i32) -> i32 { _4 = &_3; StorageLive(_5); StorageLive(_6); - _6 = _2; + _6 = copy _2; StorageLive(_7); - _7 = _2; + _7 = copy _2; _5 = (move _6, move _7); StorageLive(_8); _8 = move (_5.0: &i32); StorageLive(_9); _9 = move (_5.1: &i32); - _0 = (*_8); + _0 = copy (*_8); StorageDead(_9); StorageDead(_8); StorageDead(_7); diff --git a/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir b/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir index 2f9d28ea093..17e6e39a86b 100644 --- a/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir +++ b/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir @@ -34,18 +34,18 @@ fn foo(_1: T, _2: i32) -> (i32, T) { _6 = &_3; StorageLive(_7); StorageLive(_8); - _8 = _2; + _8 = copy _2; _7 = (move _8,); StorageLive(_9); _9 = move (_7.0: i32); StorageLive(_10); StorageLive(_12); StorageLive(_11); - _10 = ((*_6).0: &i32); - _11 = (*_10); + _10 = copy ((*_6).0: &i32); + _11 = copy (*_10); StorageLive(_13); - _12 = ((*_6).1: &T); - _13 = (*_12); + _12 = copy ((*_6).1: &T); + _13 = copy (*_12); _0 = (move _11, move _13); StorageDead(_13); StorageDead(_11); diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff index 07031a298bc..94017f028cc 100644 --- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff @@ -34,13 +34,13 @@ - _4 = g() -> [return: bb1, unwind unreachable]; + _4 = {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8 (#0)}; + _3 = &mut _4; -+ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}> { __pointer: _3 }; ++ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}> { __pointer: copy _3 }; + StorageDead(_3); + StorageLive(_5); + _5 = const false; + StorageLive(_6); + StorageLive(_7); -+ _6 = (_2.0: &mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}); ++ _6 = copy (_2.0: &mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}); + _7 = discriminant((*_6)); + switchInt(move _7) -> [0: bb3, 1: bb7, 3: bb8, otherwise: bb9]; } @@ -68,7 +68,7 @@ - StorageDead(_2); - drop(_4) -> [return: bb4, unwind unreachable]; + StorageLive(_8); -+ switchInt(_5) -> [0: bb4, otherwise: bb5]; ++ switchInt(copy _5) -> [0: bb4, otherwise: bb5]; } bb4: { @@ -99,7 +99,7 @@ + bb8: { + StorageLive(_8); + StorageDead(_8); -+ _1 = CoroutineState::::Complete(_5); ++ _1 = CoroutineState::::Complete(copy _5); + discriminant((*_6)) = 1; + goto -> bb2; + } diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff index ab6c62b0baf..858f9ace9b4 100644 --- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff @@ -34,13 +34,13 @@ - _4 = g() -> [return: bb1, unwind continue]; + _4 = {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8 (#0)}; + _3 = &mut _4; -+ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}> { __pointer: _3 }; ++ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}> { __pointer: copy _3 }; + StorageDead(_3); + StorageLive(_5); + _5 = const false; + StorageLive(_6); + StorageLive(_7); -+ _6 = (_2.0: &mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}); ++ _6 = copy (_2.0: &mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}); + _7 = discriminant((*_6)); + switchInt(move _7) -> [0: bb5, 1: bb9, 3: bb10, otherwise: bb11]; } @@ -84,7 +84,7 @@ - drop(_4) -> [return: bb6, unwind terminate(cleanup)]; + bb5: { + StorageLive(_8); -+ switchInt(_5) -> [0: bb6, otherwise: bb7]; ++ switchInt(copy _5) -> [0: bb6, otherwise: bb7]; } - bb6 (cleanup): { @@ -113,7 +113,7 @@ + bb10: { + StorageLive(_8); + StorageDead(_8); -+ _1 = CoroutineState::::Complete(_5); ++ _1 = CoroutineState::::Complete(copy _5); + discriminant((*_6)) = 1; + goto -> bb4; + } diff --git a/tests/mir-opt/inline/inline_diverging.g.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_diverging.g.Inline.panic-abort.diff index d675695eb10..bda85586515 100644 --- a/tests/mir-opt/inline/inline_diverging.g.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_diverging.g.Inline.panic-abort.diff @@ -16,7 +16,7 @@ bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; _2 = Gt(move _3, const 0_i32); switchInt(move _2) -> [0: bb2, otherwise: bb1]; } @@ -24,7 +24,7 @@ bb1: { StorageDead(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; _0 = move _4 as u32 (IntToInt); StorageDead(_4); StorageDead(_2); diff --git a/tests/mir-opt/inline/inline_diverging.g.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_diverging.g.Inline.panic-unwind.diff index 1142616115f..ecd72d2b37f 100644 --- a/tests/mir-opt/inline/inline_diverging.g.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_diverging.g.Inline.panic-unwind.diff @@ -16,7 +16,7 @@ bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; _2 = Gt(move _3, const 0_i32); switchInt(move _2) -> [0: bb2, otherwise: bb1]; } @@ -24,7 +24,7 @@ bb1: { StorageDead(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; _0 = move _4 as u32 (IntToInt); StorageDead(_4); StorageDead(_2); diff --git a/tests/mir-opt/inline/inline_diverging.h.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_diverging.h.Inline.panic-abort.diff index 2bbb830fc77..338dca85e5c 100644 --- a/tests/mir-opt/inline/inline_diverging.h.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_diverging.h.Inline.panic-abort.diff @@ -40,7 +40,7 @@ + + bb2: { + StorageDead(_5); -+ _1 = (_4, _6); ++ _1 = (copy _4, copy _6); + drop(_2) -> [return: bb3, unwind unreachable]; + } + diff --git a/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff index bc4f2d24df0..a77cb913bfd 100644 --- a/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff @@ -43,7 +43,7 @@ + StorageDead(_5); + StorageLive(_7); + _7 = move _4; -+ _1 = (move _7, _6); ++ _1 = (move _7, copy _6); + StorageDead(_7); + StorageDead(_4); + drop(_2) -> [return: bb3, unwind continue]; diff --git a/tests/mir-opt/inline/inline_more_in_non_inline.marked_inline_direct.Inline.after.panic-abort.mir b/tests/mir-opt/inline/inline_more_in_non_inline.marked_inline_direct.Inline.after.panic-abort.mir index 522f772c6f4..9b28aeb271d 100644 --- a/tests/mir-opt/inline/inline_more_in_non_inline.marked_inline_direct.Inline.after.panic-abort.mir +++ b/tests/mir-opt/inline/inline_more_in_non_inline.marked_inline_direct.Inline.after.panic-abort.mir @@ -9,7 +9,7 @@ fn marked_inline_direct(_1: i32) -> () { bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; _2 = call_twice(move _3) -> [return: bb1, unwind unreachable]; } diff --git a/tests/mir-opt/inline/inline_more_in_non_inline.marked_inline_direct.Inline.after.panic-unwind.mir b/tests/mir-opt/inline/inline_more_in_non_inline.marked_inline_direct.Inline.after.panic-unwind.mir index 722b02eeba8..929c89940dc 100644 --- a/tests/mir-opt/inline/inline_more_in_non_inline.marked_inline_direct.Inline.after.panic-unwind.mir +++ b/tests/mir-opt/inline/inline_more_in_non_inline.marked_inline_direct.Inline.after.panic-unwind.mir @@ -9,7 +9,7 @@ fn marked_inline_direct(_1: i32) -> () { bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; _2 = call_twice(move _3) -> [return: bb1, unwind continue]; } diff --git a/tests/mir-opt/inline/inline_more_in_non_inline.marked_inline_indirect.Inline.after.panic-abort.mir b/tests/mir-opt/inline/inline_more_in_non_inline.marked_inline_indirect.Inline.after.panic-abort.mir index 63b91cbce2d..374ed294d8b 100644 --- a/tests/mir-opt/inline/inline_more_in_non_inline.marked_inline_indirect.Inline.after.panic-abort.mir +++ b/tests/mir-opt/inline/inline_more_in_non_inline.marked_inline_indirect.Inline.after.panic-abort.mir @@ -12,7 +12,7 @@ fn marked_inline_indirect(_1: i32) -> () { bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; StorageLive(_4); _4 = call_twice(move _3) -> [return: bb1, unwind unreachable]; } diff --git a/tests/mir-opt/inline/inline_more_in_non_inline.marked_inline_indirect.Inline.after.panic-unwind.mir b/tests/mir-opt/inline/inline_more_in_non_inline.marked_inline_indirect.Inline.after.panic-unwind.mir index 7c84e98dd51..97bed8020ba 100644 --- a/tests/mir-opt/inline/inline_more_in_non_inline.marked_inline_indirect.Inline.after.panic-unwind.mir +++ b/tests/mir-opt/inline/inline_more_in_non_inline.marked_inline_indirect.Inline.after.panic-unwind.mir @@ -12,7 +12,7 @@ fn marked_inline_indirect(_1: i32) -> () { bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; StorageLive(_4); _4 = call_twice(move _3) -> [return: bb1, unwind continue]; } diff --git a/tests/mir-opt/inline/inline_more_in_non_inline.monomorphic_not_inline.Inline.after.panic-abort.mir b/tests/mir-opt/inline/inline_more_in_non_inline.monomorphic_not_inline.Inline.after.panic-abort.mir index 989014b8b47..cffe0e96f5c 100644 --- a/tests/mir-opt/inline/inline_more_in_non_inline.monomorphic_not_inline.Inline.after.panic-abort.mir +++ b/tests/mir-opt/inline/inline_more_in_non_inline.monomorphic_not_inline.Inline.after.panic-abort.mir @@ -13,10 +13,10 @@ fn monomorphic_not_inline(_1: i32) -> () { bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; StorageLive(_4); StorageLive(_5); - _4 = other_thing(_3) -> [return: bb2, unwind unreachable]; + _4 = other_thing(copy _3) -> [return: bb2, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/inline/inline_more_in_non_inline.monomorphic_not_inline.Inline.after.panic-unwind.mir b/tests/mir-opt/inline/inline_more_in_non_inline.monomorphic_not_inline.Inline.after.panic-unwind.mir index bd200719bbb..7f3a093012b 100644 --- a/tests/mir-opt/inline/inline_more_in_non_inline.monomorphic_not_inline.Inline.after.panic-unwind.mir +++ b/tests/mir-opt/inline/inline_more_in_non_inline.monomorphic_not_inline.Inline.after.panic-unwind.mir @@ -13,10 +13,10 @@ fn monomorphic_not_inline(_1: i32) -> () { bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; StorageLive(_4); StorageLive(_5); - _4 = other_thing(_3) -> [return: bb2, unwind continue]; + _4 = other_thing(copy _3) -> [return: bb2, unwind continue]; } bb1: { diff --git a/tests/mir-opt/inline/inline_retag.bar.Inline.after.mir b/tests/mir-opt/inline/inline_retag.bar.Inline.after.mir index ec3c79e2a37..9a256ea1949 100644 --- a/tests/mir-opt/inline/inline_retag.bar.Inline.after.mir +++ b/tests/mir-opt/inline/inline_retag.bar.Inline.after.mir @@ -26,25 +26,25 @@ fn bar() -> bool { StorageLive(_1); _1 = foo; StorageLive(_2); - _2 = _1; + _2 = copy _1; StorageLive(_3); StorageLive(_4); _10 = const bar::promoted[1]; Retag(_10); - _4 = _10; - _3 = _4; + _4 = copy _10; + _3 = copy _4; StorageLive(_6); StorageLive(_7); _9 = const bar::promoted[0]; Retag(_9); - _7 = _9; - _6 = _7; + _7 = copy _9; + _6 = copy _7; Retag(_3); Retag(_6); StorageLive(_11); - _11 = (*_3); + _11 = copy (*_3); StorageLive(_12); - _12 = (*_6); + _12 = copy (*_6); _0 = Eq(move _11, move _12); StorageDead(_12); StorageDead(_11); diff --git a/tests/mir-opt/inline/inline_shims.clone.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_shims.clone.Inline.panic-abort.diff index 8117e58fa51..26b4dc357f3 100644 --- a/tests/mir-opt/inline/inline_shims.clone.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_shims.clone.Inline.panic-abort.diff @@ -15,7 +15,7 @@ - } - - bb1: { -+ _0 = (*_2); ++ _0 = copy (*_2); StorageDead(_2); return; } diff --git a/tests/mir-opt/inline/inline_shims.clone.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_shims.clone.Inline.panic-unwind.diff index 00e92a0f5e5..faa12d5c736 100644 --- a/tests/mir-opt/inline/inline_shims.clone.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_shims.clone.Inline.panic-unwind.diff @@ -15,7 +15,7 @@ - } - - bb1: { -+ _0 = (*_2); ++ _0 = copy (*_2); StorageDead(_2); return; } diff --git a/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff index 2a36ccaab11..581244074b3 100644 --- a/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff @@ -20,7 +20,7 @@ bb0: { StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; - _3 = std::ptr::drop_in_place::>(move _4) -> [return: bb1, unwind unreachable]; + StorageLive(_6); + StorageLive(_7); @@ -34,7 +34,7 @@ StorageDead(_4); StorageDead(_3); StorageLive(_5); - _5 = _2; + _5 = copy _2; - _0 = std::ptr::drop_in_place::>(move _5) -> [return: bb2, unwind unreachable]; + StorageLive(_8); + StorageLive(_9); diff --git a/tests/mir-opt/inline/inline_shims.drop.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_shims.drop.Inline.panic-unwind.diff index e11561076e6..d89ca003d77 100644 --- a/tests/mir-opt/inline/inline_shims.drop.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_shims.drop.Inline.panic-unwind.diff @@ -16,7 +16,7 @@ bb0: { StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; _3 = std::ptr::drop_in_place::>(move _4) -> [return: bb1, unwind continue]; } @@ -24,7 +24,7 @@ StorageDead(_4); StorageDead(_3); StorageLive(_5); - _5 = _2; + _5 = copy _2; - _0 = std::ptr::drop_in_place::>(move _5) -> [return: bb2, unwind continue]; + StorageLive(_6); + StorageLive(_7); diff --git a/tests/mir-opt/inline/inline_trait_method.test.Inline.after.panic-abort.mir b/tests/mir-opt/inline/inline_trait_method.test.Inline.after.panic-abort.mir index d7b4302b06d..8355cd0070d 100644 --- a/tests/mir-opt/inline/inline_trait_method.test.Inline.after.panic-abort.mir +++ b/tests/mir-opt/inline/inline_trait_method.test.Inline.after.panic-abort.mir @@ -7,7 +7,7 @@ fn test(_1: &dyn X) -> u32 { bb0: { StorageLive(_2); - _2 = _1; + _2 = copy _1; _0 = ::y(move _2) -> [return: bb1, unwind unreachable]; } diff --git a/tests/mir-opt/inline/inline_trait_method.test.Inline.after.panic-unwind.mir b/tests/mir-opt/inline/inline_trait_method.test.Inline.after.panic-unwind.mir index 0d6f3e61f71..ebfbfeb0b13 100644 --- a/tests/mir-opt/inline/inline_trait_method.test.Inline.after.panic-unwind.mir +++ b/tests/mir-opt/inline/inline_trait_method.test.Inline.after.panic-unwind.mir @@ -7,7 +7,7 @@ fn test(_1: &dyn X) -> u32 { bb0: { StorageLive(_2); - _2 = _1; + _2 = copy _1; _0 = ::y(move _2) -> [return: bb1, unwind continue]; } diff --git a/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-abort.mir b/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-abort.mir index af79c7ce196..1105dba06ac 100644 --- a/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-abort.mir +++ b/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-abort.mir @@ -12,7 +12,7 @@ fn test2(_1: &dyn X) -> bool { bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; _2 = move _3; StorageDead(_3); _0 = ::y(move _2) -> [return: bb1, unwind unreachable]; diff --git a/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-unwind.mir b/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-unwind.mir index bf5a56b8e62..faa6ef47b18 100644 --- a/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-unwind.mir +++ b/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-unwind.mir @@ -12,7 +12,7 @@ fn test2(_1: &dyn X) -> bool { bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; _2 = move _3; StorageDead(_3); _0 = ::y(move _2) -> [return: bb1, unwind continue]; diff --git a/tests/mir-opt/inline/issue_106141.outer.Inline.panic-abort.diff b/tests/mir-opt/inline/issue_106141.outer.Inline.panic-abort.diff index 2ab79cc2a50..e87a565f0fc 100644 --- a/tests/mir-opt/inline/issue_106141.outer.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/issue_106141.outer.Inline.panic-abort.diff @@ -25,12 +25,12 @@ bb1: { + StorageLive(_3); -+ _2 = Lt(_0, const 1_usize); -+ assert(move _2, "index out of bounds: the length is {} but the index is {}", const 1_usize, _0) -> [success: bb2, unwind unreachable]; ++ _2 = Lt(copy _0, const 1_usize); ++ assert(move _2, "index out of bounds: the length is {} but the index is {}", const 1_usize, copy _0) -> [success: bb2, unwind unreachable]; + } + + bb2: { -+ _3 = (*_1)[_0]; ++ _3 = copy (*_1)[_0]; + switchInt(move _3) -> [0: bb3, otherwise: bb4]; + } + diff --git a/tests/mir-opt/inline/issue_106141.outer.Inline.panic-unwind.diff b/tests/mir-opt/inline/issue_106141.outer.Inline.panic-unwind.diff index 4d96a862885..834851b75ad 100644 --- a/tests/mir-opt/inline/issue_106141.outer.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/issue_106141.outer.Inline.panic-unwind.diff @@ -25,12 +25,12 @@ bb1: { + StorageLive(_3); -+ _2 = Lt(_0, const 1_usize); -+ assert(move _2, "index out of bounds: the length is {} but the index is {}", const 1_usize, _0) -> [success: bb2, unwind continue]; ++ _2 = Lt(copy _0, const 1_usize); ++ assert(move _2, "index out of bounds: the length is {} but the index is {}", const 1_usize, copy _0) -> [success: bb2, unwind continue]; + } + + bb2: { -+ _3 = (*_1)[_0]; ++ _3 = copy (*_1)[_0]; + switchInt(move _3) -> [0: bb3, otherwise: bb4]; + } + diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir index 8c457037ec9..a48a9a0bb0c 100644 --- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir +++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir @@ -14,11 +14,11 @@ fn a(_1: &mut [T]) -> &mut [T] { StorageLive(_2); StorageLive(_3); StorageLive(_4); - _4 = _1; - _3 = _4; - _2 = _3; + _4 = copy _1; + _3 = copy _4; + _2 = copy _3; StorageDead(_4); - _0 = _2; + _0 = copy _2; StorageDead(_3); StorageDead(_2); return; diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir index e27d9fe38c7..02aadfc1de0 100644 --- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir +++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir @@ -16,17 +16,17 @@ fn b(_1: &mut Box) -> &mut T { StorageLive(_2); StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; StorageLive(_5); StorageLive(_6); - _5 = (*_4); - _6 = (((_5.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const T); + _5 = copy (*_4); + _6 = copy (((_5.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const T); _3 = &mut (*_6); StorageDead(_6); StorageDead(_5); - _2 = _3; + _2 = copy _3; StorageDead(_4); - _0 = _2; + _0 = copy _2; StorageDead(_3); StorageDead(_2); return; diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.c.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.c.Inline.after.mir index da0464c64d6..2d88f9e5524 100644 --- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.c.Inline.after.mir +++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.c.Inline.after.mir @@ -12,9 +12,9 @@ fn c(_1: &[T]) -> &[T] { bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; - _2 = _3; - _0 = _2; + _3 = copy _1; + _2 = copy _3; + _0 = copy _2; StorageDead(_3); StorageDead(_2); return; diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir index 25eaedfc842..1ea347510fd 100644 --- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir +++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir @@ -14,15 +14,15 @@ fn d(_1: &Box) -> &T { bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; StorageLive(_4); StorageLive(_5); - _4 = (*_3); - _5 = (((_4.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const T); + _4 = copy (*_3); + _5 = copy (((_4.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const T); _2 = &(*_5); StorageDead(_5); StorageDead(_4); - _0 = _2; + _0 = copy _2; StorageDead(_3); StorageDead(_2); return; diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff index 0d9d58316ea..f36157a762c 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff @@ -18,9 +18,9 @@ bb0: { StorageLive(_3); - _3 = _1; + _3 = copy _1; StorageLive(_4); - _4 = _2; + _4 = copy _2; - _0 = core::num::::unchecked_shl(move _3, move _4) -> [return: bb1, unwind unreachable]; + StorageLive(_6); + StorageLive(_5); @@ -29,12 +29,12 @@ } bb1: { -+ _6 = core::num::::unchecked_shl::precondition_check(_4) -> [return: bb2, unwind unreachable]; ++ _6 = core::num::::unchecked_shl::precondition_check(copy _4) -> [return: bb2, unwind unreachable]; + } + + bb2: { + StorageDead(_5); -+ _0 = ShlUnchecked(_3, _4); ++ _0 = ShlUnchecked(copy _3, copy _4); + StorageDead(_6); StorageDead(_4); StorageDead(_3); diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff index 82f7eceaa18..be1b066c6c1 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff @@ -18,9 +18,9 @@ bb0: { StorageLive(_3); - _3 = _1; + _3 = copy _1; StorageLive(_4); - _4 = _2; + _4 = copy _2; - _0 = core::num::::unchecked_shl(move _3, move _4) -> [return: bb1, unwind continue]; + StorageLive(_6); + StorageLive(_5); @@ -29,12 +29,12 @@ } bb1: { -+ _6 = core::num::::unchecked_shl::precondition_check(_4) -> [return: bb2, unwind unreachable]; ++ _6 = core::num::::unchecked_shl::precondition_check(copy _4) -> [return: bb2, unwind unreachable]; + } + + bb2: { + StorageDead(_5); -+ _0 = ShlUnchecked(_3, _4); ++ _0 = ShlUnchecked(copy _3, copy _4); + StorageDead(_6); StorageDead(_4); StorageDead(_3); diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-abort.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-abort.mir index dc27685ee79..611273ab08d 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-abort.mir @@ -12,7 +12,7 @@ fn unchecked_shl_unsigned_smaller(_1: u16, _2: u32) -> u16 { } bb0: { - _0 = ShlUnchecked(_1, _2); + _0 = ShlUnchecked(copy _1, copy _2); return; } } diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-unwind.mir index dc27685ee79..611273ab08d 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-unwind.mir @@ -12,7 +12,7 @@ fn unchecked_shl_unsigned_smaller(_1: u16, _2: u32) -> u16 { } bb0: { - _0 = ShlUnchecked(_1, _2); + _0 = ShlUnchecked(copy _1, copy _2); return; } } diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-abort.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-abort.diff index 6894b246699..360687f3c4e 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-abort.diff @@ -18,9 +18,9 @@ bb0: { StorageLive(_3); - _3 = _1; + _3 = copy _1; StorageLive(_4); - _4 = _2; + _4 = copy _2; - _0 = core::num::::unchecked_shr(move _3, move _4) -> [return: bb1, unwind unreachable]; + StorageLive(_6); + StorageLive(_5); @@ -29,12 +29,12 @@ } bb1: { -+ _6 = core::num::::unchecked_shr::precondition_check(_4) -> [return: bb2, unwind unreachable]; ++ _6 = core::num::::unchecked_shr::precondition_check(copy _4) -> [return: bb2, unwind unreachable]; + } + + bb2: { + StorageDead(_5); -+ _0 = ShrUnchecked(_3, _4); ++ _0 = ShrUnchecked(copy _3, copy _4); + StorageDead(_6); StorageDead(_4); StorageDead(_3); diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-unwind.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-unwind.diff index 070f4a1c5c8..986df55df03 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-unwind.diff @@ -18,9 +18,9 @@ bb0: { StorageLive(_3); - _3 = _1; + _3 = copy _1; StorageLive(_4); - _4 = _2; + _4 = copy _2; - _0 = core::num::::unchecked_shr(move _3, move _4) -> [return: bb1, unwind continue]; + StorageLive(_6); + StorageLive(_5); @@ -29,12 +29,12 @@ } bb1: { -+ _6 = core::num::::unchecked_shr::precondition_check(_4) -> [return: bb2, unwind unreachable]; ++ _6 = core::num::::unchecked_shr::precondition_check(copy _4) -> [return: bb2, unwind unreachable]; + } + + bb2: { + StorageDead(_5); -+ _0 = ShrUnchecked(_3, _4); ++ _0 = ShrUnchecked(copy _3, copy _4); + StorageDead(_6); StorageDead(_4); StorageDead(_3); diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.panic-abort.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.panic-abort.mir index 54f093b87d1..f4ddd0bca04 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.panic-abort.mir @@ -12,7 +12,7 @@ fn unchecked_shr_signed_bigger(_1: i64, _2: u32) -> i64 { } bb0: { - _0 = ShrUnchecked(_1, _2); + _0 = ShrUnchecked(copy _1, copy _2); return; } } diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.panic-unwind.mir index 54f093b87d1..f4ddd0bca04 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.panic-unwind.mir @@ -12,7 +12,7 @@ fn unchecked_shr_signed_bigger(_1: i64, _2: u32) -> i64 { } bb0: { - _0 = ShrUnchecked(_1, _2); + _0 = ShrUnchecked(copy _1, copy _2); return; } } diff --git a/tests/mir-opt/inline/unsized_argument.caller.Inline.diff b/tests/mir-opt/inline/unsized_argument.caller.Inline.diff index 37083973fd1..70671e2089a 100644 --- a/tests/mir-opt/inline/unsized_argument.caller.Inline.diff +++ b/tests/mir-opt/inline/unsized_argument.caller.Inline.diff @@ -12,7 +12,7 @@ StorageLive(_2); StorageLive(_3); _3 = move _1; - _4 = (((_3.0: std::ptr::Unique<[i32]>).0: std::ptr::NonNull<[i32]>).0: *const [i32]); + _4 = copy (((_3.0: std::ptr::Unique<[i32]>).0: std::ptr::NonNull<[i32]>).0: *const [i32]); _2 = callee(move (*_4)) -> [return: bb1, unwind: bb3]; } diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff index c1f7879cf0e..28878736ed7 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff @@ -36,7 +36,7 @@ + bb2: { + StorageLive(_4); + _4 = UbChecks(); -+ assume(_4); ++ assume(copy _4); + _5 = unreachable_unchecked::precondition_check() -> [return: bb1, unwind unreachable]; + } + diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff index 5271e538daf..27b6bb6a5bb 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff @@ -40,7 +40,7 @@ + bb2: { + StorageLive(_4); + _4 = UbChecks(); -+ assume(_4); ++ assume(copy _4); + _5 = unreachable_unchecked::precondition_check() -> [return: bb1, unwind unreachable]; + } + diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir index dcab8a679a8..66ab5e1b962 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir @@ -22,7 +22,7 @@ fn unwrap_unchecked(_1: Option) -> T { } bb1: { - _0 = ((_1 as Some).0: T); + _0 = copy ((_1 as Some).0: T); StorageDead(_2); return; } diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir index dcab8a679a8..66ab5e1b962 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir @@ -22,7 +22,7 @@ fn unwrap_unchecked(_1: Option) -> T { } bb1: { - _0 = ((_1 as Some).0: T); + _0 = copy ((_1 as Some).0: T); StorageDead(_2); return; } diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff index f8715789cec..1e33e222b27 100644 --- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff +++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff @@ -85,7 +85,7 @@ - } - - bb2: { -+ _4 = Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}> { __pointer: _5 }; ++ _4 = Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}> { __pointer: copy _5 }; StorageDead(_5); StorageLive(_6); StorageLive(_7); @@ -160,7 +160,7 @@ + StorageLive(_14); + _14 = (); + StorageLive(_41); -+ _41 = Option::<()>::Some(_14); ++ _41 = Option::<()>::Some(copy _14); + _13 = std::future::Ready::<()>(move _41); + StorageDead(_41); + StorageDead(_14); @@ -193,7 +193,7 @@ + StorageLive(_22); + StorageLive(_23); + StorageLive(_24); -+ _24 = _31; ++ _24 = copy _31; + _23 = move _24; + _22 = &mut (*_23); + StorageDead(_24); @@ -231,8 +231,8 @@ + + bb10: { + StorageLive(_26); -+ _26 = ((_18 as Ready).0: ()); -+ _30 = _26; ++ _26 = copy ((_18 as Ready).0: ()); ++ _30 = copy _26; + StorageDead(_26); + StorageDead(_23); + StorageDead(_21); diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff index 494f5591e32..b1840beb3ef 100644 --- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff @@ -87,7 +87,7 @@ - } - - bb2: { -+ _4 = Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}> { __pointer: _5 }; ++ _4 = Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}> { __pointer: copy _5 }; StorageDead(_5); StorageLive(_6); StorageLive(_7); @@ -177,7 +177,7 @@ + StorageLive(_14); + _14 = (); + StorageLive(_43); -+ _43 = Option::<()>::Some(_14); ++ _43 = Option::<()>::Some(copy _14); + _13 = std::future::Ready::<()>(move _43); + StorageDead(_43); + StorageDead(_14); @@ -212,7 +212,7 @@ + StorageLive(_22); + StorageLive(_23); + StorageLive(_24); -+ _24 = _31; ++ _24 = copy _31; + _23 = move _24; + _22 = &mut (*_23); + StorageDead(_24); @@ -250,8 +250,8 @@ + + bb12: { + StorageLive(_26); -+ _26 = ((_18 as Ready).0: ()); -+ _30 = _26; ++ _26 = copy ((_18 as Ready).0: ()); ++ _30 = copy _26; + StorageDead(_26); + StorageDead(_23); + StorageDead(_21); diff --git a/tests/mir-opt/instsimplify/bool_compare.eq_false.InstSimplify-after-simplifycfg.diff b/tests/mir-opt/instsimplify/bool_compare.eq_false.InstSimplify-after-simplifycfg.diff index fea5f4f02ce..4762123184b 100644 --- a/tests/mir-opt/instsimplify/bool_compare.eq_false.InstSimplify-after-simplifycfg.diff +++ b/tests/mir-opt/instsimplify/bool_compare.eq_false.InstSimplify-after-simplifycfg.diff @@ -10,7 +10,7 @@ bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; - _2 = Eq(move _3, const false); + _2 = Not(move _3); switchInt(move _2) -> [0: bb2, otherwise: bb1]; diff --git a/tests/mir-opt/instsimplify/bool_compare.eq_true.InstSimplify-after-simplifycfg.diff b/tests/mir-opt/instsimplify/bool_compare.eq_true.InstSimplify-after-simplifycfg.diff index 9a509ccfa67..6fae0acf439 100644 --- a/tests/mir-opt/instsimplify/bool_compare.eq_true.InstSimplify-after-simplifycfg.diff +++ b/tests/mir-opt/instsimplify/bool_compare.eq_true.InstSimplify-after-simplifycfg.diff @@ -10,7 +10,7 @@ bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; - _2 = Eq(move _3, const true); + _2 = move _3; switchInt(move _2) -> [0: bb2, otherwise: bb1]; diff --git a/tests/mir-opt/instsimplify/bool_compare.false_eq.InstSimplify-after-simplifycfg.diff b/tests/mir-opt/instsimplify/bool_compare.false_eq.InstSimplify-after-simplifycfg.diff index e4ec4c80579..7975a808d4f 100644 --- a/tests/mir-opt/instsimplify/bool_compare.false_eq.InstSimplify-after-simplifycfg.diff +++ b/tests/mir-opt/instsimplify/bool_compare.false_eq.InstSimplify-after-simplifycfg.diff @@ -10,7 +10,7 @@ bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; - _2 = Eq(const false, move _3); + _2 = Not(move _3); switchInt(move _2) -> [0: bb2, otherwise: bb1]; diff --git a/tests/mir-opt/instsimplify/bool_compare.false_ne.InstSimplify-after-simplifycfg.diff b/tests/mir-opt/instsimplify/bool_compare.false_ne.InstSimplify-after-simplifycfg.diff index 3aea55f4db4..80d0cd62007 100644 --- a/tests/mir-opt/instsimplify/bool_compare.false_ne.InstSimplify-after-simplifycfg.diff +++ b/tests/mir-opt/instsimplify/bool_compare.false_ne.InstSimplify-after-simplifycfg.diff @@ -10,7 +10,7 @@ bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; - _2 = Ne(const false, move _3); + _2 = move _3; switchInt(move _2) -> [0: bb2, otherwise: bb1]; diff --git a/tests/mir-opt/instsimplify/bool_compare.ne_false.InstSimplify-after-simplifycfg.diff b/tests/mir-opt/instsimplify/bool_compare.ne_false.InstSimplify-after-simplifycfg.diff index b6e891088a1..c0f8b5261c2 100644 --- a/tests/mir-opt/instsimplify/bool_compare.ne_false.InstSimplify-after-simplifycfg.diff +++ b/tests/mir-opt/instsimplify/bool_compare.ne_false.InstSimplify-after-simplifycfg.diff @@ -10,7 +10,7 @@ bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; - _2 = Ne(move _3, const false); + _2 = move _3; switchInt(move _2) -> [0: bb2, otherwise: bb1]; diff --git a/tests/mir-opt/instsimplify/bool_compare.ne_true.InstSimplify-after-simplifycfg.diff b/tests/mir-opt/instsimplify/bool_compare.ne_true.InstSimplify-after-simplifycfg.diff index 974738bb3a9..4627b314408 100644 --- a/tests/mir-opt/instsimplify/bool_compare.ne_true.InstSimplify-after-simplifycfg.diff +++ b/tests/mir-opt/instsimplify/bool_compare.ne_true.InstSimplify-after-simplifycfg.diff @@ -10,7 +10,7 @@ bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; - _2 = Ne(move _3, const true); + _2 = Not(move _3); switchInt(move _2) -> [0: bb2, otherwise: bb1]; diff --git a/tests/mir-opt/instsimplify/bool_compare.true_eq.InstSimplify-after-simplifycfg.diff b/tests/mir-opt/instsimplify/bool_compare.true_eq.InstSimplify-after-simplifycfg.diff index 240835bf7f2..91ca1ba553e 100644 --- a/tests/mir-opt/instsimplify/bool_compare.true_eq.InstSimplify-after-simplifycfg.diff +++ b/tests/mir-opt/instsimplify/bool_compare.true_eq.InstSimplify-after-simplifycfg.diff @@ -10,7 +10,7 @@ bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; - _2 = Eq(const true, move _3); + _2 = move _3; switchInt(move _2) -> [0: bb2, otherwise: bb1]; diff --git a/tests/mir-opt/instsimplify/bool_compare.true_ne.InstSimplify-after-simplifycfg.diff b/tests/mir-opt/instsimplify/bool_compare.true_ne.InstSimplify-after-simplifycfg.diff index 1e2b2c27f57..744c61b987d 100644 --- a/tests/mir-opt/instsimplify/bool_compare.true_ne.InstSimplify-after-simplifycfg.diff +++ b/tests/mir-opt/instsimplify/bool_compare.true_ne.InstSimplify-after-simplifycfg.diff @@ -10,7 +10,7 @@ bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; - _2 = Ne(const true, move _3); + _2 = Not(move _3); switchInt(move _2) -> [0: bb2, otherwise: bb1]; diff --git a/tests/mir-opt/instsimplify/casts.redundant.InstSimplify-after-simplifycfg.diff b/tests/mir-opt/instsimplify/casts.redundant.InstSimplify-after-simplifycfg.diff index 7001589d9e3..afa25ecdbfb 100644 --- a/tests/mir-opt/instsimplify/casts.redundant.InstSimplify-after-simplifycfg.diff +++ b/tests/mir-opt/instsimplify/casts.redundant.InstSimplify-after-simplifycfg.diff @@ -15,16 +15,16 @@ StorageLive(_2); StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; StorageLive(_5); - _5 = _4; + _5 = copy _4; - _3 = move _5 as *const &u8 (PtrToPtr); + _3 = move _5; StorageDead(_5); StorageDead(_4); - _2 = move _3 as *const &u8 (PtrToPtr); + _2 = move _3; - _0 = _2; + _0 = copy _2; StorageDead(_3); StorageDead(_2); return; diff --git a/tests/mir-opt/instsimplify/casts.roundtrip.InstSimplify-after-simplifycfg.diff b/tests/mir-opt/instsimplify/casts.roundtrip.InstSimplify-after-simplifycfg.diff index e1045db9730..12e2913a8ca 100644 --- a/tests/mir-opt/instsimplify/casts.roundtrip.InstSimplify-after-simplifycfg.diff +++ b/tests/mir-opt/instsimplify/casts.roundtrip.InstSimplify-after-simplifycfg.diff @@ -12,7 +12,7 @@ StorageLive(_2); StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; _3 = move _4 as *mut u8 (PtrToPtr); _2 = move _3 as *const u8 (PtrToPtr); StorageDead(_4); diff --git a/tests/mir-opt/instsimplify/casts.rs b/tests/mir-opt/instsimplify/casts.rs index 24dbb67b42d..27308ee52bc 100644 --- a/tests/mir-opt/instsimplify/casts.rs +++ b/tests/mir-opt/instsimplify/casts.rs @@ -19,7 +19,7 @@ pub fn redundant<'a, 'b: 'a>(x: *const &'a u8) -> *const &'a u8 { // EMIT_MIR casts.roundtrip.InstSimplify-after-simplifycfg.diff pub fn roundtrip(x: *const u8) -> *const u8 { // CHECK-LABEL: fn roundtrip( - // CHECK: _4 = _1; + // CHECK: _4 = copy _1; // CHECK: _3 = move _4 as *mut u8 (PtrToPtr); // CHECK: _2 = move _3 as *const u8 (PtrToPtr); x as *mut u8 as *const u8 @@ -28,7 +28,7 @@ pub fn roundtrip(x: *const u8) -> *const u8 { // EMIT_MIR casts.roundtrip.InstSimplify-after-simplifycfg.diff pub fn cast_thin_via_aggregate(x: *const u8) -> *const () { // CHECK-LABEL: fn cast_thin_via_aggregate( - // CHECK: _2 = _1; + // CHECK: _2 = copy _1; // CHECK: _0 = move _2 as *const () (PtrToPtr); std::intrinsics::aggregate_raw_ptr(x, ()) } diff --git a/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-abort.diff b/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-abort.diff index a7de09ca386..f39df7ffca0 100644 --- a/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-abort.diff +++ b/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-abort.diff @@ -31,38 +31,38 @@ _3 = const 0_usize; - _4 = Len(_1); + _4 = const 2_usize; - _5 = Lt(_3, _4); - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind unreachable]; + _5 = Lt(copy _3, copy _4); + assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind unreachable]; } bb1: { - _2 = _1[_3]; + _2 = copy _1[_3]; StorageDead(_3); StorageLive(_6); StorageLive(_7); _7 = const 1_usize; - _8 = Len(_1); + _8 = const 2_usize; - _9 = Lt(_7, _8); - assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, _7) -> [success: bb2, unwind unreachable]; + _9 = Lt(copy _7, copy _8); + assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, copy _7) -> [success: bb2, unwind unreachable]; } bb2: { - _6 = _1[_7]; + _6 = copy _1[_7]; StorageDead(_7); StorageLive(_10); StorageLive(_11); - _11 = _2; + _11 = copy _2; StorageLive(_12); - _12 = _2; + _12 = copy _2; _10 = Mul(move _11, move _12); StorageDead(_12); StorageDead(_11); StorageLive(_13); StorageLive(_14); - _14 = _6; + _14 = copy _6; StorageLive(_15); - _15 = _6; + _15 = copy _6; _13 = Mul(move _14, move _15); StorageDead(_15); StorageDead(_14); diff --git a/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-unwind.diff b/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-unwind.diff index c15f7e47fe3..0e7d5653c68 100644 --- a/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-unwind.diff +++ b/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-unwind.diff @@ -31,38 +31,38 @@ _3 = const 0_usize; - _4 = Len(_1); + _4 = const 2_usize; - _5 = Lt(_3, _4); - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind continue]; + _5 = Lt(copy _3, copy _4); + assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind continue]; } bb1: { - _2 = _1[_3]; + _2 = copy _1[_3]; StorageDead(_3); StorageLive(_6); StorageLive(_7); _7 = const 1_usize; - _8 = Len(_1); + _8 = const 2_usize; - _9 = Lt(_7, _8); - assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, _7) -> [success: bb2, unwind continue]; + _9 = Lt(copy _7, copy _8); + assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, copy _7) -> [success: bb2, unwind continue]; } bb2: { - _6 = _1[_7]; + _6 = copy _1[_7]; StorageDead(_7); StorageLive(_10); StorageLive(_11); - _11 = _2; + _11 = copy _2; StorageLive(_12); - _12 = _2; + _12 = copy _2; _10 = Mul(move _11, move _12); StorageDead(_12); StorageDead(_11); StorageLive(_13); StorageLive(_14); - _14 = _6; + _14 = copy _6; StorageLive(_15); - _15 = _6; + _15 = copy _6; _13 = Mul(move _14, move _15); StorageDead(_15); StorageDead(_14); diff --git a/tests/mir-opt/instsimplify/combine_clone_of_primitives.{impl#0}-clone.InstSimplify-after-simplifycfg.panic-abort.diff b/tests/mir-opt/instsimplify/combine_clone_of_primitives.{impl#0}-clone.InstSimplify-after-simplifycfg.panic-abort.diff index c6f858d89eb..d0b50c597c4 100644 --- a/tests/mir-opt/instsimplify/combine_clone_of_primitives.{impl#0}-clone.InstSimplify-after-simplifycfg.panic-abort.diff +++ b/tests/mir-opt/instsimplify/combine_clone_of_primitives.{impl#0}-clone.InstSimplify-after-simplifycfg.panic-abort.diff @@ -20,7 +20,7 @@ StorageLive(_4); _4 = &((*_1).0: T); - _3 = &(*_4); -+ _3 = _4; ++ _3 = copy _4; _2 = ::clone(move _3) -> [return: bb1, unwind unreachable]; } @@ -32,8 +32,8 @@ _7 = &((*_1).1: u64); - _6 = &(*_7); - _5 = ::clone(move _6) -> [return: bb2, unwind unreachable]; -+ _6 = _7; -+ _5 = (*_6); ++ _6 = copy _7; ++ _5 = copy (*_6); + goto -> bb2; } @@ -45,8 +45,8 @@ _10 = &((*_1).2: [f32; 3]); - _9 = &(*_10); - _8 = <[f32; 3] as Clone>::clone(move _9) -> [return: bb3, unwind unreachable]; -+ _9 = _10; -+ _8 = (*_9); ++ _9 = copy _10; ++ _8 = copy (*_9); + goto -> bb3; } diff --git a/tests/mir-opt/instsimplify/combine_clone_of_primitives.{impl#0}-clone.InstSimplify-after-simplifycfg.panic-unwind.diff b/tests/mir-opt/instsimplify/combine_clone_of_primitives.{impl#0}-clone.InstSimplify-after-simplifycfg.panic-unwind.diff index 691ab1f0e7f..b8f4f348530 100644 --- a/tests/mir-opt/instsimplify/combine_clone_of_primitives.{impl#0}-clone.InstSimplify-after-simplifycfg.panic-unwind.diff +++ b/tests/mir-opt/instsimplify/combine_clone_of_primitives.{impl#0}-clone.InstSimplify-after-simplifycfg.panic-unwind.diff @@ -20,7 +20,7 @@ StorageLive(_4); _4 = &((*_1).0: T); - _3 = &(*_4); -+ _3 = _4; ++ _3 = copy _4; _2 = ::clone(move _3) -> [return: bb1, unwind continue]; } @@ -32,8 +32,8 @@ _7 = &((*_1).1: u64); - _6 = &(*_7); - _5 = ::clone(move _6) -> [return: bb2, unwind: bb4]; -+ _6 = _7; -+ _5 = (*_6); ++ _6 = copy _7; ++ _5 = copy (*_6); + goto -> bb2; } @@ -45,8 +45,8 @@ _10 = &((*_1).2: [f32; 3]); - _9 = &(*_10); - _8 = <[f32; 3] as Clone>::clone(move _9) -> [return: bb3, unwind: bb4]; -+ _9 = _10; -+ _8 = (*_9); ++ _9 = copy _10; ++ _8 = copy (*_9); + goto -> bb3; } diff --git a/tests/mir-opt/instsimplify/duplicate_switch_targets.assert_zero.InstSimplify-after-simplifycfg.diff b/tests/mir-opt/instsimplify/duplicate_switch_targets.assert_zero.InstSimplify-after-simplifycfg.diff index 7596aa20308..5d74f0f75db 100644 --- a/tests/mir-opt/instsimplify/duplicate_switch_targets.assert_zero.InstSimplify-after-simplifycfg.diff +++ b/tests/mir-opt/instsimplify/duplicate_switch_targets.assert_zero.InstSimplify-after-simplifycfg.diff @@ -5,8 +5,8 @@ let mut _0: u8; bb0: { -- switchInt(_1) -> [0: bb2, 1: bb1, otherwise: bb1]; -+ switchInt(_1) -> [0: bb2, otherwise: bb1]; +- switchInt(copy _1) -> [0: bb2, 1: bb1, otherwise: bb1]; ++ switchInt(copy _1) -> [0: bb2, otherwise: bb1]; } bb1: { @@ -14,7 +14,7 @@ } bb2: { - _0 = _1; + _0 = copy _1; return; } } diff --git a/tests/mir-opt/instsimplify/ref_of_deref.pointers.InstSimplify-after-simplifycfg.diff b/tests/mir-opt/instsimplify/ref_of_deref.pointers.InstSimplify-after-simplifycfg.diff index ca26f0240f9..b2f720be9e1 100644 --- a/tests/mir-opt/instsimplify/ref_of_deref.pointers.InstSimplify-after-simplifycfg.diff +++ b/tests/mir-opt/instsimplify/ref_of_deref.pointers.InstSimplify-after-simplifycfg.diff @@ -39,12 +39,12 @@ _5 = &mut (*_2); StorageLive(_6); - _6 = &raw const (*_1); -+ _6 = _1; ++ _6 = copy _1; StorageLive(_7); _7 = &raw const (*_2); StorageLive(_8); - _8 = &raw mut (*_2); -+ _8 = _2; ++ _8 = copy _2; _0 = const (); StorageDead(_8); StorageDead(_7); diff --git a/tests/mir-opt/instsimplify/ref_of_deref.references.InstSimplify-after-simplifycfg.diff b/tests/mir-opt/instsimplify/ref_of_deref.references.InstSimplify-after-simplifycfg.diff index 928ee3acaa0..4ea9da46c55 100644 --- a/tests/mir-opt/instsimplify/ref_of_deref.references.InstSimplify-after-simplifycfg.diff +++ b/tests/mir-opt/instsimplify/ref_of_deref.references.InstSimplify-after-simplifycfg.diff @@ -33,12 +33,12 @@ bb0: { StorageLive(_3); - _3 = &(*_1); -+ _3 = _1; ++ _3 = copy _1; StorageLive(_4); _4 = &(*_2); StorageLive(_5); - _5 = &mut (*_2); -+ _5 = _2; ++ _5 = copy _2; StorageLive(_6); _6 = &raw const (*_1); StorageLive(_7); diff --git a/tests/mir-opt/instsimplify/ref_of_deref.rs b/tests/mir-opt/instsimplify/ref_of_deref.rs index dc0f5f8198b..5372d906bda 100644 --- a/tests/mir-opt/instsimplify/ref_of_deref.rs +++ b/tests/mir-opt/instsimplify/ref_of_deref.rs @@ -1,6 +1,5 @@ //@ test-mir-pass: InstSimplify-after-simplifycfg #![crate_type = "lib"] -#![feature(raw_ref_op)] // For each of these, only 2 of the 6 should simplify, // as the others have the wrong types. @@ -8,11 +7,11 @@ // EMIT_MIR ref_of_deref.references.InstSimplify-after-simplifycfg.diff // CHECK-LABEL: references pub fn references(const_ref: &i32, mut_ref: &mut [i32]) { - // CHECK: _3 = _1; + // CHECK: _3 = copy _1; let _a = &*const_ref; // CHECK: _4 = &(*_2); let _b = &*mut_ref; - // CHECK: _5 = _2; + // CHECK: _5 = copy _2; let _c = &mut *mut_ref; // CHECK: _6 = &raw const (*_1); let _d = &raw const *const_ref; @@ -31,10 +30,10 @@ pub unsafe fn pointers(const_ptr: *const [i32], mut_ptr: *mut i32) { let _b = &*mut_ptr; // CHECK: _5 = &mut (*_2); let _c = &mut *mut_ptr; - // CHECK: _6 = _1; + // CHECK: _6 = copy _1; let _d = &raw const *const_ptr; // CHECK: _7 = &raw const (*_2); let _e = &raw const *mut_ptr; - // CHECK: _8 = _2; + // CHECK: _8 = copy _2; let _f = &raw mut *mut_ptr; } diff --git a/tests/mir-opt/instsimplify/ub_check.rs b/tests/mir-opt/instsimplify/ub_check.rs index ee72511c132..b513f60dc7b 100644 --- a/tests/mir-opt/instsimplify/ub_check.rs +++ b/tests/mir-opt/instsimplify/ub_check.rs @@ -6,7 +6,7 @@ pub fn unwrap_unchecked(x: Option) -> i32 { // CHECK-LABEL: fn unwrap_unchecked( // CHECK-NOT: UbChecks() // CHECK: [[assume:_.*]] = const false; - // CHECK-NEXT: assume([[assume]]); + // CHECK-NEXT: assume(copy [[assume]]); // CHECK-NEXT: unreachable_unchecked::precondition_check unsafe { x.unwrap_unchecked() } } diff --git a/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify-after-simplifycfg.diff b/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify-after-simplifycfg.diff index 7ef77e76d12..5fee9a6733d 100644 --- a/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify-after-simplifycfg.diff +++ b/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify-after-simplifycfg.diff @@ -21,7 +21,7 @@ bb0: { StorageLive(_2); - _2 = _1; + _2 = copy _1; StorageLive(_3); StorageLive(_5); _3 = discriminant(_2); @@ -36,7 +36,7 @@ StorageLive(_4); - _4 = UbChecks(); + _4 = const false; - assume(_4); + assume(copy _4); _5 = unreachable_unchecked::precondition_check() -> [return: bb1, unwind unreachable]; } diff --git a/tests/mir-opt/issue_101973.inner.GVN.panic-abort.diff b/tests/mir-opt/issue_101973.inner.GVN.panic-abort.diff index 311de9e1c93..ac88fe67bb8 100644 --- a/tests/mir-opt/issue_101973.inner.GVN.panic-abort.diff +++ b/tests/mir-opt/issue_101973.inner.GVN.panic-abort.diff @@ -29,22 +29,22 @@ StorageLive(_3); StorageLive(_4); StorageLive(_5); - _5 = _1; + _5 = copy _1; nop; - StorageLive(_14); -- _14 = BitAnd(_5, const 255_u32); +- _14 = BitAnd(copy _5, const 255_u32); - _4 = BitOr(const 0_u32, move _14); - StorageDead(_14); + nop; -+ _14 = BitAnd(_1, const 255_u32); -+ _4 = _14; ++ _14 = BitAnd(copy _1, const 255_u32); ++ _4 = copy _14; + nop; StorageDead(_5); StorageLive(_6); StorageLive(_7); StorageLive(_8); StorageLive(_9); - _9 = _1; + _9 = copy _1; - _10 = const 8_i32 as u32 (IntToInt); - _11 = Lt(move _10, const 32_u32); - assert(move _11, "attempt to shift right by `{}`, which would overflow", const 8_i32) -> [success: bb1, unwind unreachable]; @@ -55,7 +55,7 @@ bb1: { - _8 = Shr(move _9, const 8_i32); -+ _8 = Shr(_1, const 8_i32); ++ _8 = Shr(copy _1, const 8_i32); StorageDead(_9); _7 = BitAnd(move _8, const 15_u32); StorageDead(_8); @@ -71,7 +71,7 @@ _6 = Shl(move _7, const 1_i32); StorageDead(_7); - _3 = rotate_right::(move _4, move _6) -> [return: bb3, unwind unreachable]; -+ _3 = rotate_right::(_14, move _6) -> [return: bb3, unwind unreachable]; ++ _3 = rotate_right::(copy _14, move _6) -> [return: bb3, unwind unreachable]; } bb3: { diff --git a/tests/mir-opt/issue_101973.inner.GVN.panic-unwind.diff b/tests/mir-opt/issue_101973.inner.GVN.panic-unwind.diff index c5fd042161d..96c3cae2d33 100644 --- a/tests/mir-opt/issue_101973.inner.GVN.panic-unwind.diff +++ b/tests/mir-opt/issue_101973.inner.GVN.panic-unwind.diff @@ -29,22 +29,22 @@ StorageLive(_3); StorageLive(_4); StorageLive(_5); - _5 = _1; + _5 = copy _1; nop; - StorageLive(_14); -- _14 = BitAnd(_5, const 255_u32); +- _14 = BitAnd(copy _5, const 255_u32); - _4 = BitOr(const 0_u32, move _14); - StorageDead(_14); + nop; -+ _14 = BitAnd(_1, const 255_u32); -+ _4 = _14; ++ _14 = BitAnd(copy _1, const 255_u32); ++ _4 = copy _14; + nop; StorageDead(_5); StorageLive(_6); StorageLive(_7); StorageLive(_8); StorageLive(_9); - _9 = _1; + _9 = copy _1; - _10 = const 8_i32 as u32 (IntToInt); - _11 = Lt(move _10, const 32_u32); - assert(move _11, "attempt to shift right by `{}`, which would overflow", const 8_i32) -> [success: bb1, unwind continue]; @@ -55,7 +55,7 @@ bb1: { - _8 = Shr(move _9, const 8_i32); -+ _8 = Shr(_1, const 8_i32); ++ _8 = Shr(copy _1, const 8_i32); StorageDead(_9); _7 = BitAnd(move _8, const 15_u32); StorageDead(_8); @@ -71,7 +71,7 @@ _6 = Shl(move _7, const 1_i32); StorageDead(_7); - _3 = rotate_right::(move _4, move _6) -> [return: bb3, unwind unreachable]; -+ _3 = rotate_right::(_14, move _6) -> [return: bb3, unwind unreachable]; ++ _3 = rotate_right::(copy _14, move _6) -> [return: bb3, unwind unreachable]; } bb3: { diff --git a/tests/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir b/tests/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir index 632b5580656..66dbbc0c044 100644 --- a/tests/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir @@ -25,7 +25,7 @@ fn main() -> () { bb2: { StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; switchInt(move _4) -> [0: bb4, otherwise: bb3]; } diff --git a/tests/mir-opt/issue_41110.main.ElaborateDrops.panic-abort.diff b/tests/mir-opt/issue_41110.main.ElaborateDrops.panic-abort.diff index 4469270a9b2..cf952230128 100644 --- a/tests/mir-opt/issue_41110.main.ElaborateDrops.panic-abort.diff +++ b/tests/mir-opt/issue_41110.main.ElaborateDrops.panic-abort.diff @@ -63,7 +63,7 @@ + } + + bb8 (cleanup): { -+ switchInt(_5) -> [0: bb6, otherwise: bb7]; ++ switchInt(copy _5) -> [0: bb6, otherwise: bb7]; } } diff --git a/tests/mir-opt/issue_41110.main.ElaborateDrops.panic-unwind.diff b/tests/mir-opt/issue_41110.main.ElaborateDrops.panic-unwind.diff index 4469270a9b2..cf952230128 100644 --- a/tests/mir-opt/issue_41110.main.ElaborateDrops.panic-unwind.diff +++ b/tests/mir-opt/issue_41110.main.ElaborateDrops.panic-unwind.diff @@ -63,7 +63,7 @@ + } + + bb8 (cleanup): { -+ switchInt(_5) -> [0: bb6, otherwise: bb7]; ++ switchInt(copy _5) -> [0: bb6, otherwise: bb7]; } } diff --git a/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-abort.diff b/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-abort.diff index 78184f6aeeb..15fd95a63ff 100644 --- a/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-abort.diff +++ b/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-abort.diff @@ -93,7 +93,7 @@ + } + + bb12 (cleanup): { -+ switchInt(_6) -> [0: bb10, otherwise: bb11]; ++ switchInt(copy _6) -> [0: bb10, otherwise: bb11]; } } diff --git a/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-unwind.diff b/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-unwind.diff index 688887c3c1f..4a0067981cb 100644 --- a/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-unwind.diff +++ b/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-unwind.diff @@ -93,7 +93,7 @@ + } + + bb12 (cleanup): { -+ switchInt(_6) -> [0: bb10, otherwise: bb11]; ++ switchInt(copy _6) -> [0: bb10, otherwise: bb11]; } } diff --git a/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-abort.diff b/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-abort.diff index 55d2629a551..e2726464ef3 100644 --- a/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-abort.diff +++ b/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-abort.diff @@ -115,7 +115,7 @@ + } + + bb15 (cleanup): { -+ switchInt(_7) -> [0: bb12, otherwise: bb14]; ++ switchInt(copy _7) -> [0: bb12, otherwise: bb14]; + } + + bb16: { @@ -132,7 +132,7 @@ + } + + bb19: { -+ switchInt(_7) -> [0: bb13, otherwise: bb18]; ++ switchInt(copy _7) -> [0: bb13, otherwise: bb18]; + } + + bb20 (cleanup): { @@ -141,7 +141,7 @@ + } + + bb21 (cleanup): { -+ switchInt(_7) -> [0: bb12, otherwise: bb20]; ++ switchInt(copy _7) -> [0: bb12, otherwise: bb20]; } } diff --git a/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-unwind.diff b/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-unwind.diff index c731b5646f6..7efa3330e66 100644 --- a/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-unwind.diff +++ b/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-unwind.diff @@ -115,7 +115,7 @@ + } + + bb15 (cleanup): { -+ switchInt(_7) -> [0: bb12, otherwise: bb14]; ++ switchInt(copy _7) -> [0: bb12, otherwise: bb14]; + } + + bb16: { @@ -132,7 +132,7 @@ + } + + bb19: { -+ switchInt(_7) -> [0: bb13, otherwise: bb18]; ++ switchInt(copy _7) -> [0: bb13, otherwise: bb18]; + } + + bb20 (cleanup): { @@ -141,7 +141,7 @@ + } + + bb21 (cleanup): { -+ switchInt(_7) -> [0: bb12, otherwise: bb20]; ++ switchInt(copy _7) -> [0: bb12, otherwise: bb20]; } } diff --git a/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-abort.mir b/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-abort.mir index 3104baa5fdb..736a8bbca49 100644 --- a/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-abort.mir +++ b/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-abort.mir @@ -54,8 +54,8 @@ fn test() -> Option> { bb4: { StorageLive(_12); - _12 = ((_6 as Continue).0: u32); - (*_5) = _12; + _12 = copy ((_6 as Continue).0: u32); + (*_5) = copy _12; StorageDead(_12); _1 = move _5; drop(_5) -> [return: bb7, unwind: bb11]; @@ -63,9 +63,9 @@ fn test() -> Option> { bb5: { StorageLive(_9); - _9 = ((_6 as Break).0: std::option::Option); + _9 = copy ((_6 as Break).0: std::option::Option); StorageLive(_11); - _11 = _9; + _11 = copy _9; _0 = > as FromResidual>>::from_residual(move _11) -> [return: bb6, unwind: bb12]; } diff --git a/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-unwind.mir b/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-unwind.mir index da33c830115..1acb1ae20b6 100644 --- a/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-unwind.mir +++ b/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-unwind.mir @@ -54,8 +54,8 @@ fn test() -> Option> { bb4: { StorageLive(_12); - _12 = ((_6 as Continue).0: u32); - (*_5) = _12; + _12 = copy ((_6 as Continue).0: u32); + (*_5) = copy _12; StorageDead(_12); _1 = move _5; drop(_5) -> [return: bb7, unwind: bb11]; @@ -63,9 +63,9 @@ fn test() -> Option> { bb5: { StorageLive(_9); - _9 = ((_6 as Break).0: std::option::Option); + _9 = copy ((_6 as Break).0: std::option::Option); StorageLive(_11); - _11 = _9; + _11 = copy _9; _0 = > as FromResidual>>::from_residual(move _11) -> [return: bb6, unwind: bb12]; } diff --git a/tests/mir-opt/issue_72181.bar.built.after.mir b/tests/mir-opt/issue_72181.bar.built.after.mir index b6cc7d22195..569c4a00628 100644 --- a/tests/mir-opt/issue_72181.bar.built.after.mir +++ b/tests/mir-opt/issue_72181.bar.built.after.mir @@ -9,8 +9,8 @@ fn bar(_1: [(Never, u32); 1]) -> u32 { bb0: { StorageLive(_2); - _2 = (_1[0 of 1].1: u32); - _0 = _2; + _2 = copy (_1[0 of 1].1: u32); + _0 = copy _2; StorageDead(_2); return; } diff --git a/tests/mir-opt/issue_72181.foo.built.after.mir b/tests/mir-opt/issue_72181.foo.built.after.mir index f78942cc56f..314cf8b367f 100644 --- a/tests/mir-opt/issue_72181.foo.built.after.mir +++ b/tests/mir-opt/issue_72181.foo.built.after.mir @@ -11,12 +11,12 @@ fn foo(_1: [(Never, u32); 1]) -> u32 { StorageLive(_2); _2 = const 0_usize; _3 = Len(_1); - _4 = Lt(_2, _3); - assert(move _4, "index out of bounds: the length is {} but the index is {}", move _3, _2) -> [success: bb1, unwind: bb2]; + _4 = Lt(copy _2, copy _3); + assert(move _4, "index out of bounds: the length is {} but the index is {}", move _3, copy _2) -> [success: bb1, unwind: bb2]; } bb1: { - _0 = (_1[_2].1: u32); + _0 = copy (_1[_2].1: u32); StorageDead(_2); return; } diff --git a/tests/mir-opt/issue_72181.main.built.after.mir b/tests/mir-opt/issue_72181.main.built.after.mir index 89d351d5172..aade84a6dd2 100644 --- a/tests/mir-opt/issue_72181.main.built.after.mir +++ b/tests/mir-opt/issue_72181.main.built.after.mir @@ -39,8 +39,8 @@ fn main() -> () { StorageLive(_6); _6 = const 0_usize; _7 = Len(_2); - _8 = Lt(_6, _7); - assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb3, unwind: bb5]; + _8 = Lt(copy _6, copy _7); + assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb3, unwind: bb5]; } bb2: { @@ -49,7 +49,7 @@ fn main() -> () { } bb3: { - _5 = (_2[_6].0: u64); + _5 = copy (_2[_6].0: u64); PlaceMention(_5); StorageDead(_6); StorageDead(_5); diff --git a/tests/mir-opt/issue_72181_1.main.built.after.mir b/tests/mir-opt/issue_72181_1.main.built.after.mir index e8ad5cd8d16..293aa37944d 100644 --- a/tests/mir-opt/issue_72181_1.main.built.after.mir +++ b/tests/mir-opt/issue_72181_1.main.built.after.mir @@ -19,7 +19,7 @@ fn main() -> () { StorageLive(_2); StorageLive(_3); _3 = (); - _2 = transmute::<(), Void>(move _3) -> bb4; + _2 = std::intrinsics::transmute::<(), Void>(move _3) -> bb4; } bb1: { diff --git a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff index 861ee1d3d3d..f03691ad673 100644 --- a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff +++ b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff @@ -24,9 +24,9 @@ bb0: { StorageLive(_4); - _4 = [_1, _1, _1]; + _4 = [copy _1, copy _1, copy _1]; _3 = &_4; - _2 = _3 as &[T] (PointerCoercion(Unsize)); + _2 = copy _3 as &[T] (PointerCoercion(Unsize)); nop; nop; goto -> bb2; diff --git a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff index f27be953384..633e5c740a1 100644 --- a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff +++ b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff @@ -24,9 +24,9 @@ bb0: { StorageLive(_4); - _4 = [_1, _1, _1]; + _4 = [copy _1, copy _1, copy _1]; _3 = &_4; - _2 = _3 as &[T] (PointerCoercion(Unsize)); + _2 = copy _3 as &[T] (PointerCoercion(Unsize)); nop; nop; goto -> bb2; diff --git a/tests/mir-opt/issue_78192.f.InstSimplify-after-simplifycfg.diff b/tests/mir-opt/issue_78192.f.InstSimplify-after-simplifycfg.diff index 53957bb3cb1..aae0570973d 100644 --- a/tests/mir-opt/issue_78192.f.InstSimplify-after-simplifycfg.diff +++ b/tests/mir-opt/issue_78192.f.InstSimplify-after-simplifycfg.diff @@ -17,9 +17,9 @@ StorageLive(_4); _4 = &raw const (*_1); _3 = &_4; - _2 = _3; + _2 = copy _3; StorageDead(_3); - _0 = (*_2); + _0 = copy (*_2); StorageDead(_4); StorageDead(_2); return; diff --git a/tests/mir-opt/issue_91633.foo.built.after.mir b/tests/mir-opt/issue_91633.foo.built.after.mir index a66769f0d11..50fdf08375a 100644 --- a/tests/mir-opt/issue_91633.foo.built.after.mir +++ b/tests/mir-opt/issue_91633.foo.built.after.mir @@ -18,8 +18,8 @@ fn foo(_1: Box<[T]>) -> T { StorageLive(_4); _4 = const 0_usize; _5 = Len((*_1)); - _6 = Lt(_4, _5); - assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind: bb5]; + _6 = Lt(copy _4, copy _5); + assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, copy _4) -> [success: bb1, unwind: bb5]; } bb1: { diff --git a/tests/mir-opt/issue_91633.fun.built.after.mir b/tests/mir-opt/issue_91633.fun.built.after.mir index 7175c9e8006..5b41b376719 100644 --- a/tests/mir-opt/issue_91633.fun.built.after.mir +++ b/tests/mir-opt/issue_91633.fun.built.after.mir @@ -16,8 +16,8 @@ fn fun(_1: &[T]) -> &T { StorageLive(_3); _3 = const 0_usize; _4 = Len((*_1)); - _5 = Lt(_3, _4); - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind: bb2]; + _5 = Lt(copy _3, copy _4); + assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind: bb2]; } bb1: { diff --git a/tests/mir-opt/issue_99325.main.built.after.32bit.mir b/tests/mir-opt/issue_99325.main.built.after.32bit.mir index 72e7f4794f9..161c73529f5 100644 --- a/tests/mir-opt/issue_99325.main.built.after.32bit.mir +++ b/tests/mir-opt/issue_99325.main.built.after.32bit.mir @@ -83,9 +83,9 @@ fn main() -> () { StorageDead(_3); PlaceMention(_2); StorageLive(_8); - _8 = (_2.0: &&[u8]); + _8 = copy (_2.0: &&[u8]); StorageLive(_9); - _9 = (_2.1: &&[u8; 4]); + _9 = copy (_2.1: &&[u8; 4]); StorageLive(_10); StorageLive(_11); _11 = &(*_8); @@ -187,9 +187,9 @@ fn main() -> () { StorageDead(_24); PlaceMention(_23); StorageLive(_28); - _28 = (_23.0: &&[u8]); + _28 = copy (_23.0: &&[u8]); StorageLive(_29); - _29 = (_23.1: &&[u8; 4]); + _29 = copy (_23.1: &&[u8; 4]); StorageLive(_30); StorageLive(_31); _31 = &(*_28); diff --git a/tests/mir-opt/issue_99325.main.built.after.64bit.mir b/tests/mir-opt/issue_99325.main.built.after.64bit.mir index 72e7f4794f9..161c73529f5 100644 --- a/tests/mir-opt/issue_99325.main.built.after.64bit.mir +++ b/tests/mir-opt/issue_99325.main.built.after.64bit.mir @@ -83,9 +83,9 @@ fn main() -> () { StorageDead(_3); PlaceMention(_2); StorageLive(_8); - _8 = (_2.0: &&[u8]); + _8 = copy (_2.0: &&[u8]); StorageLive(_9); - _9 = (_2.1: &&[u8; 4]); + _9 = copy (_2.1: &&[u8; 4]); StorageLive(_10); StorageLive(_11); _11 = &(*_8); @@ -187,9 +187,9 @@ fn main() -> () { StorageDead(_24); PlaceMention(_23); StorageLive(_28); - _28 = (_23.0: &&[u8]); + _28 = copy (_23.0: &&[u8]); StorageLive(_29); - _29 = (_23.1: &&[u8; 4]); + _29 = copy (_23.1: &&[u8; 4]); StorageLive(_30); StorageLive(_31); _31 = &(*_28); diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir index 8da56d59aaa..573c0a12bc1 100644 --- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir @@ -19,7 +19,7 @@ fn num_to_digit(_1: char) -> u32 { bb0: { StorageLive(_2); - _2 = char::methods::::to_digit(_1, const 8_u32) -> [return: bb1, unwind unreachable]; + _2 = char::methods::::to_digit(copy _1, const 8_u32) -> [return: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir index 61bc09d901c..049803041d4 100644 --- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir @@ -19,7 +19,7 @@ fn num_to_digit(_1: char) -> u32 { bb0: { StorageLive(_2); - _2 = char::methods::::to_digit(_1, const 8_u32) -> [return: bb1, unwind continue]; + _2 = char::methods::::to_digit(copy _1, const 8_u32) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff b/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff index 25ed1b4d0c7..1ab9be96652 100644 --- a/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff +++ b/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff @@ -19,26 +19,26 @@ bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; _2 = move _3 as [u32; 4] (Transmute); StorageDead(_3); - switchInt(_2[0 of 4]) -> [0: bb1, otherwise: bb4]; + switchInt(copy _2[0 of 4]) -> [0: bb1, otherwise: bb4]; } bb1: { - switchInt(_2[1 of 4]) -> [0: bb2, otherwise: bb4]; + switchInt(copy _2[1 of 4]) -> [0: bb2, otherwise: bb4]; } bb2: { - switchInt(_2[2 of 4]) -> [0: bb3, 4294901760: bb3, otherwise: bb4]; + switchInt(copy _2[2 of 4]) -> [0: bb3, 4294901760: bb3, otherwise: bb4]; } bb3: { StorageLive(_4); - _4 = _2[3 of 4]; + _4 = copy _2[3 of 4]; StorageLive(_5); StorageLive(_6); - _6 = _4; + _6 = copy _4; _5 = move _6 as [u8; 4] (Transmute); StorageDead(_6); _0 = Option::<[u8; 4]>::Some(move _5); diff --git a/tests/mir-opt/jump_threading.aggregate.JumpThreading.panic-abort.diff b/tests/mir-opt/jump_threading.aggregate.JumpThreading.panic-abort.diff index e955e669014..a7551c3fb5b 100644 --- a/tests/mir-opt/jump_threading.aggregate.JumpThreading.panic-abort.diff +++ b/tests/mir-opt/jump_threading.aggregate.JumpThreading.panic-abort.diff @@ -18,13 +18,13 @@ StorageLive(_4); _4 = const aggregate::FOO; StorageLive(_2); - _2 = (_4.0: u8); + _2 = copy (_4.0: u8); StorageLive(_3); - _3 = (_4.1: u8); + _3 = copy (_4.1: u8); StorageDead(_4); StorageLive(_5); StorageLive(_6); - _6 = _2; + _6 = copy _2; _5 = Eq(move _6, const 7_u8); - switchInt(move _5) -> [0: bb2, otherwise: bb1]; + goto -> bb2; @@ -32,13 +32,13 @@ bb1: { StorageDead(_6); - _0 = _3; + _0 = copy _3; goto -> bb3; } bb2: { StorageDead(_6); - _0 = _2; + _0 = copy _2; goto -> bb3; } diff --git a/tests/mir-opt/jump_threading.aggregate.JumpThreading.panic-unwind.diff b/tests/mir-opt/jump_threading.aggregate.JumpThreading.panic-unwind.diff index e955e669014..a7551c3fb5b 100644 --- a/tests/mir-opt/jump_threading.aggregate.JumpThreading.panic-unwind.diff +++ b/tests/mir-opt/jump_threading.aggregate.JumpThreading.panic-unwind.diff @@ -18,13 +18,13 @@ StorageLive(_4); _4 = const aggregate::FOO; StorageLive(_2); - _2 = (_4.0: u8); + _2 = copy (_4.0: u8); StorageLive(_3); - _3 = (_4.1: u8); + _3 = copy (_4.1: u8); StorageDead(_4); StorageLive(_5); StorageLive(_6); - _6 = _2; + _6 = copy _2; _5 = Eq(move _6, const 7_u8); - switchInt(move _5) -> [0: bb2, otherwise: bb1]; + goto -> bb2; @@ -32,13 +32,13 @@ bb1: { StorageDead(_6); - _0 = _3; + _0 = copy _3; goto -> bb3; } bb2: { StorageDead(_6); - _0 = _2; + _0 = copy _2; goto -> bb3; } diff --git a/tests/mir-opt/jump_threading.aggregate_copy.JumpThreading.panic-abort.diff b/tests/mir-opt/jump_threading.aggregate_copy.JumpThreading.panic-abort.diff index 0c8e04a1e74..4d639d89f0d 100644 --- a/tests/mir-opt/jump_threading.aggregate_copy.JumpThreading.panic-abort.diff +++ b/tests/mir-opt/jump_threading.aggregate_copy.JumpThreading.panic-abort.diff @@ -22,12 +22,12 @@ StorageLive(_1); _1 = const aggregate_copy::Foo; StorageLive(_2); - _2 = _1; + _2 = copy _1; StorageLive(_3); - _3 = (_2.1: u32); + _3 = copy (_2.1: u32); StorageLive(_4); StorageLive(_5); - _5 = _3; + _5 = copy _3; _4 = Eq(move _5, const 2_u32); - switchInt(move _4) -> [0: bb2, otherwise: bb1]; + goto -> bb2; @@ -35,7 +35,7 @@ bb1: { StorageDead(_5); - _0 = (_2.0: u32); + _0 = copy (_2.0: u32); goto -> bb3; } diff --git a/tests/mir-opt/jump_threading.aggregate_copy.JumpThreading.panic-unwind.diff b/tests/mir-opt/jump_threading.aggregate_copy.JumpThreading.panic-unwind.diff index 0c8e04a1e74..4d639d89f0d 100644 --- a/tests/mir-opt/jump_threading.aggregate_copy.JumpThreading.panic-unwind.diff +++ b/tests/mir-opt/jump_threading.aggregate_copy.JumpThreading.panic-unwind.diff @@ -22,12 +22,12 @@ StorageLive(_1); _1 = const aggregate_copy::Foo; StorageLive(_2); - _2 = _1; + _2 = copy _1; StorageLive(_3); - _3 = (_2.1: u32); + _3 = copy (_2.1: u32); StorageLive(_4); StorageLive(_5); - _5 = _3; + _5 = copy _3; _4 = Eq(move _5, const 2_u32); - switchInt(move _4) -> [0: bb2, otherwise: bb1]; + goto -> bb2; @@ -35,7 +35,7 @@ bb1: { StorageDead(_5); - _0 = (_2.0: u32); + _0 = copy (_2.0: u32); goto -> bb3; } diff --git a/tests/mir-opt/jump_threading.assume.JumpThreading.panic-abort.diff b/tests/mir-opt/jump_threading.assume.JumpThreading.panic-abort.diff index f1f0106fdbc..519cb0f0ab1 100644 --- a/tests/mir-opt/jump_threading.assume.JumpThreading.panic-abort.diff +++ b/tests/mir-opt/jump_threading.assume.JumpThreading.panic-abort.diff @@ -5,11 +5,11 @@ let mut _0: u8; bb0: { - switchInt(_1) -> [7: bb1, otherwise: bb2]; + switchInt(copy _1) -> [7: bb1, otherwise: bb2]; } bb1: { - assume(_2); + assume(copy _2); - goto -> bb3; + goto -> bb6; } @@ -19,7 +19,7 @@ } bb3: { - switchInt(_2) -> [0: bb4, otherwise: bb5]; + switchInt(copy _2) -> [0: bb4, otherwise: bb5]; } bb4: { diff --git a/tests/mir-opt/jump_threading.assume.JumpThreading.panic-unwind.diff b/tests/mir-opt/jump_threading.assume.JumpThreading.panic-unwind.diff index f1f0106fdbc..519cb0f0ab1 100644 --- a/tests/mir-opt/jump_threading.assume.JumpThreading.panic-unwind.diff +++ b/tests/mir-opt/jump_threading.assume.JumpThreading.panic-unwind.diff @@ -5,11 +5,11 @@ let mut _0: u8; bb0: { - switchInt(_1) -> [7: bb1, otherwise: bb2]; + switchInt(copy _1) -> [7: bb1, otherwise: bb2]; } bb1: { - assume(_2); + assume(copy _2); - goto -> bb3; + goto -> bb6; } @@ -19,7 +19,7 @@ } bb3: { - switchInt(_2) -> [0: bb4, otherwise: bb5]; + switchInt(copy _2) -> [0: bb4, otherwise: bb5]; } bb4: { diff --git a/tests/mir-opt/jump_threading.custom_discr.JumpThreading.panic-abort.diff b/tests/mir-opt/jump_threading.custom_discr.JumpThreading.panic-abort.diff index 462cc207785..a86371794eb 100644 --- a/tests/mir-opt/jump_threading.custom_discr.JumpThreading.panic-abort.diff +++ b/tests/mir-opt/jump_threading.custom_discr.JumpThreading.panic-abort.diff @@ -11,7 +11,7 @@ bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; switchInt(move _3) -> [0: bb2, otherwise: bb1]; } diff --git a/tests/mir-opt/jump_threading.custom_discr.JumpThreading.panic-unwind.diff b/tests/mir-opt/jump_threading.custom_discr.JumpThreading.panic-unwind.diff index 462cc207785..a86371794eb 100644 --- a/tests/mir-opt/jump_threading.custom_discr.JumpThreading.panic-unwind.diff +++ b/tests/mir-opt/jump_threading.custom_discr.JumpThreading.panic-unwind.diff @@ -11,7 +11,7 @@ bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; switchInt(move _3) -> [0: bb2, otherwise: bb1]; } diff --git a/tests/mir-opt/jump_threading.disappearing_bb.JumpThreading.panic-abort.diff b/tests/mir-opt/jump_threading.disappearing_bb.JumpThreading.panic-abort.diff index f290da84e5d..d17f2752f58 100644 --- a/tests/mir-opt/jump_threading.disappearing_bb.JumpThreading.panic-abort.diff +++ b/tests/mir-opt/jump_threading.disappearing_bb.JumpThreading.panic-abort.diff @@ -9,7 +9,7 @@ bb0: { _2 = const true; _3 = const true; - switchInt(_1) -> [0: bb3, 1: bb3, 2: bb1, otherwise: bb2]; + switchInt(copy _1) -> [0: bb3, 1: bb3, 2: bb1, otherwise: bb2]; } bb1: { @@ -28,11 +28,11 @@ } bb4: { - switchInt(_3) -> [0: bb5, otherwise: bb7]; + switchInt(copy _3) -> [0: bb5, otherwise: bb7]; } bb5: { - switchInt(_2) -> [0: bb6, otherwise: bb8]; + switchInt(copy _2) -> [0: bb6, otherwise: bb8]; } bb6: { diff --git a/tests/mir-opt/jump_threading.disappearing_bb.JumpThreading.panic-unwind.diff b/tests/mir-opt/jump_threading.disappearing_bb.JumpThreading.panic-unwind.diff index f290da84e5d..d17f2752f58 100644 --- a/tests/mir-opt/jump_threading.disappearing_bb.JumpThreading.panic-unwind.diff +++ b/tests/mir-opt/jump_threading.disappearing_bb.JumpThreading.panic-unwind.diff @@ -9,7 +9,7 @@ bb0: { _2 = const true; _3 = const true; - switchInt(_1) -> [0: bb3, 1: bb3, 2: bb1, otherwise: bb2]; + switchInt(copy _1) -> [0: bb3, 1: bb3, 2: bb1, otherwise: bb2]; } bb1: { @@ -28,11 +28,11 @@ } bb4: { - switchInt(_3) -> [0: bb5, otherwise: bb7]; + switchInt(copy _3) -> [0: bb5, otherwise: bb7]; } bb5: { - switchInt(_2) -> [0: bb6, otherwise: bb8]; + switchInt(copy _2) -> [0: bb6, otherwise: bb8]; } bb6: { diff --git a/tests/mir-opt/jump_threading.duplicate_chain.JumpThreading.panic-abort.diff b/tests/mir-opt/jump_threading.duplicate_chain.JumpThreading.panic-abort.diff index adcedfb3667..083a6e7487a 100644 --- a/tests/mir-opt/jump_threading.duplicate_chain.JumpThreading.panic-abort.diff +++ b/tests/mir-opt/jump_threading.duplicate_chain.JumpThreading.panic-abort.diff @@ -8,7 +8,7 @@ let mut _4: i32; bb0: { - switchInt(_1) -> [1: bb1, otherwise: bb2]; + switchInt(copy _1) -> [1: bb1, otherwise: bb2]; } bb1: { @@ -28,7 +28,7 @@ bb4: { _4 = const 15_i32; -- switchInt(_2) -> [5: bb5, otherwise: bb6]; +- switchInt(copy _2) -> [5: bb5, otherwise: bb6]; + goto -> bb5; } diff --git a/tests/mir-opt/jump_threading.duplicate_chain.JumpThreading.panic-unwind.diff b/tests/mir-opt/jump_threading.duplicate_chain.JumpThreading.panic-unwind.diff index adcedfb3667..083a6e7487a 100644 --- a/tests/mir-opt/jump_threading.duplicate_chain.JumpThreading.panic-unwind.diff +++ b/tests/mir-opt/jump_threading.duplicate_chain.JumpThreading.panic-unwind.diff @@ -8,7 +8,7 @@ let mut _4: i32; bb0: { - switchInt(_1) -> [1: bb1, otherwise: bb2]; + switchInt(copy _1) -> [1: bb1, otherwise: bb2]; } bb1: { @@ -28,7 +28,7 @@ bb4: { _4 = const 15_i32; -- switchInt(_2) -> [5: bb5, otherwise: bb6]; +- switchInt(copy _2) -> [5: bb5, otherwise: bb6]; + goto -> bb5; } diff --git a/tests/mir-opt/jump_threading.floats.JumpThreading.panic-abort.diff b/tests/mir-opt/jump_threading.floats.JumpThreading.panic-abort.diff index 6ca37e96d29..1192f7c23e1 100644 --- a/tests/mir-opt/jump_threading.floats.JumpThreading.panic-abort.diff +++ b/tests/mir-opt/jump_threading.floats.JumpThreading.panic-abort.diff @@ -33,7 +33,7 @@ StorageDead(_2); StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; _3 = Eq(move _4, const 0f64); switchInt(move _3) -> [0: bb5, otherwise: bb4]; } diff --git a/tests/mir-opt/jump_threading.floats.JumpThreading.panic-unwind.diff b/tests/mir-opt/jump_threading.floats.JumpThreading.panic-unwind.diff index 6ca37e96d29..1192f7c23e1 100644 --- a/tests/mir-opt/jump_threading.floats.JumpThreading.panic-unwind.diff +++ b/tests/mir-opt/jump_threading.floats.JumpThreading.panic-unwind.diff @@ -33,7 +33,7 @@ StorageDead(_2); StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; _3 = Eq(move _4, const 0f64); switchInt(move _3) -> [0: bb5, otherwise: bb4]; } diff --git a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff index 65379ae8b89..79599f85611 100644 --- a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff +++ b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff @@ -45,7 +45,7 @@ StorageLive(_2); StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; StorageLive(_10); StorageLive(_11); StorageLive(_12); @@ -59,8 +59,8 @@ bb2: { StorageLive(_9); - _9 = ((_3 as Continue).0: i32); - _2 = _9; + _9 = copy ((_3 as Continue).0: i32); + _2 = copy _9; StorageDead(_9); _0 = Result::::Ok(move _2); StorageDead(_2); @@ -70,9 +70,9 @@ bb3: { StorageLive(_6); - _6 = ((_3 as Break).0: std::result::Result); + _6 = copy ((_3 as Break).0: std::result::Result); StorageLive(_8); - _8 = _6; + _8 = copy _6; StorageLive(_14); _14 = move ((_8 as Err).0: i32); StorageLive(_15); @@ -104,7 +104,7 @@ bb6: { _12 = move ((_4 as Err).0: i32); StorageLive(_13); - _13 = Result::::Err(_12); + _13 = Result::::Err(copy _12); _3 = ControlFlow::, i32>::Break(move _13); StorageDead(_13); - goto -> bb5; @@ -113,7 +113,7 @@ bb7: { _11 = move ((_4 as Ok).0: i32); - _3 = ControlFlow::, i32>::Continue(_11); + _3 = ControlFlow::, i32>::Continue(copy _11); goto -> bb5; + } + diff --git a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff index 65379ae8b89..79599f85611 100644 --- a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff +++ b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff @@ -45,7 +45,7 @@ StorageLive(_2); StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; StorageLive(_10); StorageLive(_11); StorageLive(_12); @@ -59,8 +59,8 @@ bb2: { StorageLive(_9); - _9 = ((_3 as Continue).0: i32); - _2 = _9; + _9 = copy ((_3 as Continue).0: i32); + _2 = copy _9; StorageDead(_9); _0 = Result::::Ok(move _2); StorageDead(_2); @@ -70,9 +70,9 @@ bb3: { StorageLive(_6); - _6 = ((_3 as Break).0: std::result::Result); + _6 = copy ((_3 as Break).0: std::result::Result); StorageLive(_8); - _8 = _6; + _8 = copy _6; StorageLive(_14); _14 = move ((_8 as Err).0: i32); StorageLive(_15); @@ -104,7 +104,7 @@ bb6: { _12 = move ((_4 as Err).0: i32); StorageLive(_13); - _13 = Result::::Err(_12); + _13 = Result::::Err(copy _12); _3 = ControlFlow::, i32>::Break(move _13); StorageDead(_13); - goto -> bb5; @@ -113,7 +113,7 @@ bb7: { _11 = move ((_4 as Ok).0: i32); - _3 = ControlFlow::, i32>::Continue(_11); + _3 = ControlFlow::, i32>::Continue(copy _11); goto -> bb5; + } + diff --git a/tests/mir-opt/jump_threading.multiple_match.JumpThreading.panic-abort.diff b/tests/mir-opt/jump_threading.multiple_match.JumpThreading.panic-abort.diff index 2ca03e439a0..09c0ad6d485 100644 --- a/tests/mir-opt/jump_threading.multiple_match.JumpThreading.panic-abort.diff +++ b/tests/mir-opt/jump_threading.multiple_match.JumpThreading.panic-abort.diff @@ -7,18 +7,18 @@ let mut _3: u8; bb0: { - switchInt(_1) -> [3: bb1, otherwise: bb2]; + switchInt(copy _1) -> [3: bb1, otherwise: bb2]; } bb1: { - _2 = _1; -- switchInt(_2) -> [3: bb3, otherwise: bb4]; + _2 = copy _1; +- switchInt(copy _2) -> [3: bb3, otherwise: bb4]; + goto -> bb3; } bb2: { - _3 = _1; -- switchInt(_3) -> [3: bb5, otherwise: bb6]; + _3 = copy _1; +- switchInt(copy _3) -> [3: bb5, otherwise: bb6]; + goto -> bb6; } @@ -38,7 +38,7 @@ } bb6: { - switchInt(_3) -> [1: bb7, otherwise: bb8]; + switchInt(copy _3) -> [1: bb7, otherwise: bb8]; } bb7: { diff --git a/tests/mir-opt/jump_threading.multiple_match.JumpThreading.panic-unwind.diff b/tests/mir-opt/jump_threading.multiple_match.JumpThreading.panic-unwind.diff index 2ca03e439a0..09c0ad6d485 100644 --- a/tests/mir-opt/jump_threading.multiple_match.JumpThreading.panic-unwind.diff +++ b/tests/mir-opt/jump_threading.multiple_match.JumpThreading.panic-unwind.diff @@ -7,18 +7,18 @@ let mut _3: u8; bb0: { - switchInt(_1) -> [3: bb1, otherwise: bb2]; + switchInt(copy _1) -> [3: bb1, otherwise: bb2]; } bb1: { - _2 = _1; -- switchInt(_2) -> [3: bb3, otherwise: bb4]; + _2 = copy _1; +- switchInt(copy _2) -> [3: bb3, otherwise: bb4]; + goto -> bb3; } bb2: { - _3 = _1; -- switchInt(_3) -> [3: bb5, otherwise: bb6]; + _3 = copy _1; +- switchInt(copy _3) -> [3: bb5, otherwise: bb6]; + goto -> bb6; } @@ -38,7 +38,7 @@ } bb6: { - switchInt(_3) -> [1: bb7, otherwise: bb8]; + switchInt(copy _3) -> [1: bb7, otherwise: bb8]; } bb7: { diff --git a/tests/mir-opt/jump_threading.mutable_ref.JumpThreading.panic-abort.diff b/tests/mir-opt/jump_threading.mutable_ref.JumpThreading.panic-abort.diff index e9d4352014f..bb47f57b542 100644 --- a/tests/mir-opt/jump_threading.mutable_ref.JumpThreading.panic-abort.diff +++ b/tests/mir-opt/jump_threading.mutable_ref.JumpThreading.panic-abort.diff @@ -27,7 +27,7 @@ StorageDead(_3); StorageLive(_4); StorageLive(_5); - _5 = _1; + _5 = copy _1; _4 = Eq(move _5, const 7_i32); switchInt(move _4) -> [0: bb2, otherwise: bb1]; } diff --git a/tests/mir-opt/jump_threading.mutable_ref.JumpThreading.panic-unwind.diff b/tests/mir-opt/jump_threading.mutable_ref.JumpThreading.panic-unwind.diff index e9d4352014f..bb47f57b542 100644 --- a/tests/mir-opt/jump_threading.mutable_ref.JumpThreading.panic-unwind.diff +++ b/tests/mir-opt/jump_threading.mutable_ref.JumpThreading.panic-unwind.diff @@ -27,7 +27,7 @@ StorageDead(_3); StorageLive(_4); StorageLive(_5); - _5 = _1; + _5 = copy _1; _4 = Eq(move _5, const 7_i32); switchInt(move _4) -> [0: bb2, otherwise: bb1]; } diff --git a/tests/mir-opt/jump_threading.mutate_discriminant.JumpThreading.panic-abort.diff b/tests/mir-opt/jump_threading.mutate_discriminant.JumpThreading.panic-abort.diff index 8821b47c345..7014146cb86 100644 --- a/tests/mir-opt/jump_threading.mutate_discriminant.JumpThreading.panic-abort.diff +++ b/tests/mir-opt/jump_threading.mutate_discriminant.JumpThreading.panic-abort.diff @@ -10,7 +10,7 @@ discriminant(_1) = 1; (((_1 as variant#1).0: NonZeroUsize).0: usize) = const 0_usize; _2 = discriminant(_1); - switchInt(_2) -> [0: bb1, otherwise: bb2]; + switchInt(copy _2) -> [0: bb1, otherwise: bb2]; } bb1: { diff --git a/tests/mir-opt/jump_threading.mutate_discriminant.JumpThreading.panic-unwind.diff b/tests/mir-opt/jump_threading.mutate_discriminant.JumpThreading.panic-unwind.diff index 8821b47c345..7014146cb86 100644 --- a/tests/mir-opt/jump_threading.mutate_discriminant.JumpThreading.panic-unwind.diff +++ b/tests/mir-opt/jump_threading.mutate_discriminant.JumpThreading.panic-unwind.diff @@ -10,7 +10,7 @@ discriminant(_1) = 1; (((_1 as variant#1).0: NonZeroUsize).0: usize) = const 0_usize; _2 = discriminant(_1); - switchInt(_2) -> [0: bb1, otherwise: bb2]; + switchInt(copy _2) -> [0: bb1, otherwise: bb2]; } bb1: { diff --git a/tests/mir-opt/jump_threading.renumbered_bb.JumpThreading.panic-abort.diff b/tests/mir-opt/jump_threading.renumbered_bb.JumpThreading.panic-abort.diff index 2d943a4bee2..9a8bdc8f4d9 100644 --- a/tests/mir-opt/jump_threading.renumbered_bb.JumpThreading.panic-abort.diff +++ b/tests/mir-opt/jump_threading.renumbered_bb.JumpThreading.panic-abort.diff @@ -8,7 +8,7 @@ bb0: { _3 = const false; - switchInt(_1) -> [1: bb1, otherwise: bb2]; + switchInt(copy _1) -> [1: bb1, otherwise: bb2]; } bb1: { @@ -18,17 +18,17 @@ } bb2: { - _2 = _1; - _3 = _1; + _2 = copy _1; + _3 = copy _1; goto -> bb3; } bb3: { - switchInt(_2) -> [0: bb4, otherwise: bb5]; + switchInt(copy _2) -> [0: bb4, otherwise: bb5]; } bb4: { - switchInt(_3) -> [0: bb6, otherwise: bb7]; + switchInt(copy _3) -> [0: bb6, otherwise: bb7]; } bb5: { diff --git a/tests/mir-opt/jump_threading.renumbered_bb.JumpThreading.panic-unwind.diff b/tests/mir-opt/jump_threading.renumbered_bb.JumpThreading.panic-unwind.diff index 2d943a4bee2..9a8bdc8f4d9 100644 --- a/tests/mir-opt/jump_threading.renumbered_bb.JumpThreading.panic-unwind.diff +++ b/tests/mir-opt/jump_threading.renumbered_bb.JumpThreading.panic-unwind.diff @@ -8,7 +8,7 @@ bb0: { _3 = const false; - switchInt(_1) -> [1: bb1, otherwise: bb2]; + switchInt(copy _1) -> [1: bb1, otherwise: bb2]; } bb1: { @@ -18,17 +18,17 @@ } bb2: { - _2 = _1; - _3 = _1; + _2 = copy _1; + _3 = copy _1; goto -> bb3; } bb3: { - switchInt(_2) -> [0: bb4, otherwise: bb5]; + switchInt(copy _2) -> [0: bb4, otherwise: bb5]; } bb4: { - switchInt(_3) -> [0: bb6, otherwise: bb7]; + switchInt(copy _3) -> [0: bb6, otherwise: bb7]; } bb5: { diff --git a/tests/mir-opt/jump_threading.rs b/tests/mir-opt/jump_threading.rs index 6486a321e69..9487a4e7e5f 100644 --- a/tests/mir-opt/jump_threading.rs +++ b/tests/mir-opt/jump_threading.rs @@ -24,11 +24,11 @@ fn too_complex(x: Result) -> Option { // CHECK: bb4: { // CHECK: goto -> bb6; // CHECK: bb5: { - // CHECK: {{_.*}} = (([[controlflow]] as Break).0: usize); + // CHECK: {{_.*}} = copy (([[controlflow]] as Break).0: usize); // CHECK: _0 = Option::::None; // CHECK: goto -> bb7; // CHECK: bb6: { - // CHECK: {{_.*}} = (([[controlflow]] as Continue).0: i32); + // CHECK: {{_.*}} = copy (([[controlflow]] as Continue).0: i32); // CHECK: _0 = Option::::Some( // CHECK: goto -> bb7; // CHECK: bb7: { @@ -49,16 +49,16 @@ fn too_complex(x: Result) -> Option { fn identity(x: Result) -> Result { // CHECK-LABEL: fn identity( // CHECK: bb0: { - // CHECK: [[x:_.*]] = _1; + // CHECK: [[x:_.*]] = copy _1; // CHECK: switchInt(move {{_.*}}) -> [0: bb7, 1: bb6, otherwise: bb1]; // CHECK: bb1: { // CHECK: unreachable; // CHECK: bb2: { - // CHECK: {{_.*}} = (([[controlflow:_.*]] as Continue).0: i32); + // CHECK: {{_.*}} = copy (([[controlflow:_.*]] as Continue).0: i32); // CHECK: _0 = Result::::Ok( // CHECK: goto -> bb4; // CHECK: bb3: { - // CHECK: {{_.*}} = (([[controlflow]] as Break).0: std::result::Result); + // CHECK: {{_.*}} = copy (([[controlflow]] as Break).0: std::result::Result); // CHECK: _0 = Result::::Err( // CHECK: goto -> bb4; // CHECK: bb4: { @@ -160,13 +160,13 @@ fn multiple_match(x: u8) -> u8 { mir! { { // CHECK: bb0: { - // CHECK: switchInt([[x:_.*]]) -> [3: bb1, otherwise: bb2]; + // CHECK: switchInt(copy [[x:_.*]]) -> [3: bb1, otherwise: bb2]; match x { 3 => bb1, _ => bb2 } } bb1 = { // We know `x == 3`, so we can take `bb3`. // CHECK: bb1: { - // CHECK: {{_.*}} = [[x]]; + // CHECK: {{_.*}} = copy [[x]]; // CHECK: goto -> bb3; let y = x; match y { 3 => bb3, _ => bb4 } @@ -174,7 +174,7 @@ fn multiple_match(x: u8) -> u8 { bb2 = { // We know `x != 3`, so we can take `bb6`. // CHECK: bb2: { - // CHECK: [[z:_.*]] = [[x]]; + // CHECK: [[z:_.*]] = copy [[x]]; // CHECK: goto -> bb6; let z = x; match z { 3 => bb5, _ => bb6 } @@ -203,7 +203,7 @@ fn multiple_match(x: u8) -> u8 { bb6 = { // We know `z != 3`, so we CANNOT take `bb7`. // CHECK: bb6: { - // CHECK: switchInt([[z]]) -> [1: bb7, otherwise: bb8]; + // CHECK: switchInt(copy [[z]]) -> [1: bb7, otherwise: bb8]; match z { 1 => bb7, _ => bb8 } } bb7 = { @@ -467,12 +467,12 @@ fn assume(a: u8, b: bool) -> u8 { mir! { { // CHECK: bb0: { - // CHECK-NEXT: switchInt(_1) -> [7: bb1, otherwise: bb2] + // CHECK-NEXT: switchInt(copy _1) -> [7: bb1, otherwise: bb2] match a { 7 => bb1, _ => bb2 } } bb1 = { // CHECK: bb1: { - // CHECK-NEXT: assume(_2); + // CHECK-NEXT: assume(copy _2); // CHECK-NEXT: goto -> bb6; Assume(b); Goto(bb3) @@ -484,7 +484,7 @@ fn assume(a: u8, b: bool) -> u8 { } bb3 = { // CHECK: bb3: { - // CHECK-NEXT: switchInt(_2) -> [0: bb4, otherwise: bb5]; + // CHECK-NEXT: switchInt(copy _2) -> [0: bb4, otherwise: bb5]; match b { false => bb4, _ => bb5 } } bb4 = { diff --git a/tests/mir-opt/jump_threading.too_complex.JumpThreading.panic-abort.diff b/tests/mir-opt/jump_threading.too_complex.JumpThreading.panic-abort.diff index 365d9d6b32b..7de35929892 100644 --- a/tests/mir-opt/jump_threading.too_complex.JumpThreading.panic-abort.diff +++ b/tests/mir-opt/jump_threading.too_complex.JumpThreading.panic-abort.diff @@ -39,9 +39,9 @@ bb2: { StorageLive(_6); - _6 = ((_1 as Err).0: usize); + _6 = copy ((_1 as Err).0: usize); StorageLive(_7); - _7 = _6; + _7 = copy _6; _2 = ControlFlow::::Break(move _7); StorageDead(_7); StorageDead(_6); @@ -51,9 +51,9 @@ bb3: { StorageLive(_4); - _4 = ((_1 as Ok).0: i32); + _4 = copy ((_1 as Ok).0: i32); StorageLive(_5); - _5 = _4; + _5 = copy _4; _2 = ControlFlow::::Continue(move _5); StorageDead(_5); StorageDead(_4); @@ -68,7 +68,7 @@ bb5: { StorageLive(_11); - _11 = ((_2 as Break).0: usize); + _11 = copy ((_2 as Break).0: usize); _0 = Option::::None; StorageDead(_11); goto -> bb7; @@ -76,9 +76,9 @@ bb6: { StorageLive(_9); - _9 = ((_2 as Continue).0: i32); + _9 = copy ((_2 as Continue).0: i32); StorageLive(_10); - _10 = _9; + _10 = copy _9; _0 = Option::::Some(move _10); StorageDead(_10); StorageDead(_9); diff --git a/tests/mir-opt/jump_threading.too_complex.JumpThreading.panic-unwind.diff b/tests/mir-opt/jump_threading.too_complex.JumpThreading.panic-unwind.diff index 365d9d6b32b..7de35929892 100644 --- a/tests/mir-opt/jump_threading.too_complex.JumpThreading.panic-unwind.diff +++ b/tests/mir-opt/jump_threading.too_complex.JumpThreading.panic-unwind.diff @@ -39,9 +39,9 @@ bb2: { StorageLive(_6); - _6 = ((_1 as Err).0: usize); + _6 = copy ((_1 as Err).0: usize); StorageLive(_7); - _7 = _6; + _7 = copy _6; _2 = ControlFlow::::Break(move _7); StorageDead(_7); StorageDead(_6); @@ -51,9 +51,9 @@ bb3: { StorageLive(_4); - _4 = ((_1 as Ok).0: i32); + _4 = copy ((_1 as Ok).0: i32); StorageLive(_5); - _5 = _4; + _5 = copy _4; _2 = ControlFlow::::Continue(move _5); StorageDead(_5); StorageDead(_4); @@ -68,7 +68,7 @@ bb5: { StorageLive(_11); - _11 = ((_2 as Break).0: usize); + _11 = copy ((_2 as Break).0: usize); _0 = Option::::None; StorageDead(_11); goto -> bb7; @@ -76,9 +76,9 @@ bb6: { StorageLive(_9); - _9 = ((_2 as Continue).0: i32); + _9 = copy ((_2 as Continue).0: i32); StorageLive(_10); - _10 = _9; + _10 = copy _9; _0 = Option::::Some(move _10); StorageDead(_10); StorageDead(_9); diff --git a/tests/mir-opt/lower_array_len.array_bound.GVN.panic-abort.diff b/tests/mir-opt/lower_array_len.array_bound.GVN.panic-abort.diff index 7aca2cb0007..8223cbbb412 100644 --- a/tests/mir-opt/lower_array_len.array_bound.GVN.panic-abort.diff +++ b/tests/mir-opt/lower_array_len.array_bound.GVN.panic-abort.diff @@ -18,7 +18,7 @@ - StorageLive(_3); + nop; StorageLive(_4); - _4 = _1; + _4 = copy _1; - StorageLive(_5); + nop; StorageLive(_6); @@ -35,8 +35,8 @@ StorageDead(_6); - _3 = Lt(move _4, move _5); - switchInt(move _3) -> [0: bb4, otherwise: bb2]; -+ _3 = Lt(_1, const N); -+ switchInt(_3) -> [0: bb4, otherwise: bb2]; ++ _3 = Lt(copy _1, const N); ++ switchInt(copy _3) -> [0: bb4, otherwise: bb2]; } bb2: { @@ -44,18 +44,18 @@ + nop; StorageDead(_4); StorageLive(_8); - _8 = _1; + _8 = copy _1; - _9 = Len((*_2)); -- _10 = Lt(_8, _9); -- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> [success: bb3, unwind unreachable]; +- _10 = Lt(copy _8, copy _9); +- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, copy _8) -> [success: bb3, unwind unreachable]; + _9 = const N; -+ _10 = _3; -+ assert(_3, "index out of bounds: the length is {} but the index is {}", const N, _1) -> [success: bb3, unwind unreachable]; ++ _10 = copy _3; ++ assert(copy _3, "index out of bounds: the length is {} but the index is {}", const N, copy _1) -> [success: bb3, unwind unreachable]; } bb3: { -- _0 = (*_2)[_8]; -+ _0 = (*_2)[_1]; +- _0 = copy (*_2)[_8]; ++ _0 = copy (*_2)[_1]; StorageDead(_8); goto -> bb5; } diff --git a/tests/mir-opt/lower_array_len.array_bound.GVN.panic-unwind.diff b/tests/mir-opt/lower_array_len.array_bound.GVN.panic-unwind.diff index ed39c11319a..d8f33accbc0 100644 --- a/tests/mir-opt/lower_array_len.array_bound.GVN.panic-unwind.diff +++ b/tests/mir-opt/lower_array_len.array_bound.GVN.panic-unwind.diff @@ -18,7 +18,7 @@ - StorageLive(_3); + nop; StorageLive(_4); - _4 = _1; + _4 = copy _1; - StorageLive(_5); + nop; StorageLive(_6); @@ -35,8 +35,8 @@ StorageDead(_6); - _3 = Lt(move _4, move _5); - switchInt(move _3) -> [0: bb4, otherwise: bb2]; -+ _3 = Lt(_1, const N); -+ switchInt(_3) -> [0: bb4, otherwise: bb2]; ++ _3 = Lt(copy _1, const N); ++ switchInt(copy _3) -> [0: bb4, otherwise: bb2]; } bb2: { @@ -44,18 +44,18 @@ + nop; StorageDead(_4); StorageLive(_8); - _8 = _1; + _8 = copy _1; - _9 = Len((*_2)); -- _10 = Lt(_8, _9); -- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> [success: bb3, unwind continue]; +- _10 = Lt(copy _8, copy _9); +- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, copy _8) -> [success: bb3, unwind continue]; + _9 = const N; -+ _10 = _3; -+ assert(_3, "index out of bounds: the length is {} but the index is {}", const N, _1) -> [success: bb3, unwind continue]; ++ _10 = copy _3; ++ assert(copy _3, "index out of bounds: the length is {} but the index is {}", const N, copy _1) -> [success: bb3, unwind continue]; } bb3: { -- _0 = (*_2)[_8]; -+ _0 = (*_2)[_1]; +- _0 = copy (*_2)[_8]; ++ _0 = copy (*_2)[_1]; StorageDead(_8); goto -> bb5; } diff --git a/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-abort.diff b/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-abort.diff index 734d28e9546..1cb9963c00e 100644 --- a/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-abort.diff +++ b/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-abort.diff @@ -21,7 +21,7 @@ - StorageLive(_3); + nop; StorageLive(_4); - _4 = _1; + _4 = copy _1; - StorageLive(_5); + nop; StorageLive(_6); @@ -38,8 +38,8 @@ StorageDead(_6); - _3 = Lt(move _4, move _5); - switchInt(move _3) -> [0: bb4, otherwise: bb2]; -+ _3 = Lt(_1, const N); -+ switchInt(_3) -> [0: bb4, otherwise: bb2]; ++ _3 = Lt(copy _1, const N); ++ switchInt(copy _3) -> [0: bb4, otherwise: bb2]; } bb2: { @@ -47,18 +47,18 @@ + nop; StorageDead(_4); StorageLive(_8); - _8 = _1; + _8 = copy _1; - _9 = Len((*_2)); -- _10 = Lt(_8, _9); -- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> [success: bb3, unwind unreachable]; +- _10 = Lt(copy _8, copy _9); +- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, copy _8) -> [success: bb3, unwind unreachable]; + _9 = const N; -+ _10 = _3; -+ assert(_3, "index out of bounds: the length is {} but the index is {}", const N, _1) -> [success: bb3, unwind unreachable]; ++ _10 = copy _3; ++ assert(copy _3, "index out of bounds: the length is {} but the index is {}", const N, copy _1) -> [success: bb3, unwind unreachable]; } bb3: { -- _0 = (*_2)[_8]; -+ _0 = (*_2)[_1]; +- _0 = copy (*_2)[_8]; ++ _0 = copy (*_2)[_1]; StorageDead(_8); goto -> bb6; } @@ -70,8 +70,8 @@ StorageLive(_11); _11 = const 0_usize; - _12 = Len((*_2)); -- _13 = Lt(_11, _12); -- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, _11) -> [success: bb5, unwind unreachable]; +- _13 = Lt(copy _11, copy _12); +- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb5, unwind unreachable]; + _12 = const N; + _13 = Lt(const 0_usize, const N); + assert(move _13, "index out of bounds: the length is {} but the index is {}", const N, const 0_usize) -> [success: bb5, unwind unreachable]; diff --git a/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-unwind.diff b/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-unwind.diff index ec569ab5042..fa4e11ed201 100644 --- a/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-unwind.diff +++ b/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-unwind.diff @@ -21,7 +21,7 @@ - StorageLive(_3); + nop; StorageLive(_4); - _4 = _1; + _4 = copy _1; - StorageLive(_5); + nop; StorageLive(_6); @@ -38,8 +38,8 @@ StorageDead(_6); - _3 = Lt(move _4, move _5); - switchInt(move _3) -> [0: bb4, otherwise: bb2]; -+ _3 = Lt(_1, const N); -+ switchInt(_3) -> [0: bb4, otherwise: bb2]; ++ _3 = Lt(copy _1, const N); ++ switchInt(copy _3) -> [0: bb4, otherwise: bb2]; } bb2: { @@ -47,18 +47,18 @@ + nop; StorageDead(_4); StorageLive(_8); - _8 = _1; + _8 = copy _1; - _9 = Len((*_2)); -- _10 = Lt(_8, _9); -- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> [success: bb3, unwind continue]; +- _10 = Lt(copy _8, copy _9); +- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, copy _8) -> [success: bb3, unwind continue]; + _9 = const N; -+ _10 = _3; -+ assert(_3, "index out of bounds: the length is {} but the index is {}", const N, _1) -> [success: bb3, unwind continue]; ++ _10 = copy _3; ++ assert(copy _3, "index out of bounds: the length is {} but the index is {}", const N, copy _1) -> [success: bb3, unwind continue]; } bb3: { -- _0 = (*_2)[_8]; -+ _0 = (*_2)[_1]; +- _0 = copy (*_2)[_8]; ++ _0 = copy (*_2)[_1]; StorageDead(_8); goto -> bb6; } @@ -70,8 +70,8 @@ StorageLive(_11); _11 = const 0_usize; - _12 = Len((*_2)); -- _13 = Lt(_11, _12); -- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, _11) -> [success: bb5, unwind continue]; +- _13 = Lt(copy _11, copy _12); +- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb5, unwind continue]; + _12 = const N; + _13 = Lt(const 0_usize, const N); + assert(move _13, "index out of bounds: the length is {} but the index is {}", const N, const 0_usize) -> [success: bb5, unwind continue]; diff --git a/tests/mir-opt/lower_array_len.rs b/tests/mir-opt/lower_array_len.rs index f7ed376726c..6553343cbf0 100644 --- a/tests/mir-opt/lower_array_len.rs +++ b/tests/mir-opt/lower_array_len.rs @@ -6,7 +6,7 @@ pub fn array_bound(index: usize, slice: &[u8; N]) -> u8 { // CHECK-LABEL: fn array_bound( // CHECK-NOT: Lt - // CHECK: Lt(_1, const N); + // CHECK: Lt(copy _1, const N); // CHECK-NOT: Lt if index < slice.len() { slice[index] } else { 42 } } @@ -15,7 +15,7 @@ pub fn array_bound(index: usize, slice: &[u8; N]) -> u8 { pub fn array_bound_mut(index: usize, slice: &mut [u8; N]) -> u8 { // CHECK-LABEL: fn array_bound_mut( // CHECK-NOT: Lt - // CHECK: Lt(_1, const N); + // CHECK: Lt(copy _1, const N); // CHECK-NOT: Lt // CHECK: Lt(const 0_usize, const N) // CHECK-NOT: Lt diff --git a/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.panic-abort.diff index 96b66af66a2..7f325245bce 100644 --- a/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.panic-abort.diff @@ -33,7 +33,7 @@ StorageLive(_7); _7 = &_1; _6 = &raw const (*_7); - _5 = _6; + _5 = copy _6; _4 = move _5 as *const i32 (PtrToPtr); StorageDead(_5); StorageLive(_8); @@ -42,7 +42,7 @@ StorageLive(_11); _11 = &mut _2; _10 = &raw mut (*_11); - _9 = _10; + _9 = copy _10; _8 = move _9 as *mut i32 (PtrToPtr); StorageDead(_9); - _3 = copy_nonoverlapping::(move _4, move _8, const 0_usize) -> [return: bb1, unwind unreachable]; diff --git a/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.panic-unwind.diff index 96b66af66a2..7f325245bce 100644 --- a/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.panic-unwind.diff @@ -33,7 +33,7 @@ StorageLive(_7); _7 = &_1; _6 = &raw const (*_7); - _5 = _6; + _5 = copy _6; _4 = move _5 as *const i32 (PtrToPtr); StorageDead(_5); StorageLive(_8); @@ -42,7 +42,7 @@ StorageLive(_11); _11 = &mut _2; _10 = &raw mut (*_11); - _9 = _10; + _9 = copy _10; _8 = move _9 as *mut i32 (PtrToPtr); StorageDead(_9); - _3 = copy_nonoverlapping::(move _4, move _8, const 0_usize) -> [return: bb1, unwind unreachable]; diff --git a/tests/mir-opt/lower_intrinsics.get_metadata.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.get_metadata.LowerIntrinsics.panic-abort.diff index d256058c05e..f2cfce1b6e3 100644 --- a/tests/mir-opt/lower_intrinsics.get_metadata.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.get_metadata.LowerIntrinsics.panic-abort.diff @@ -25,7 +25,7 @@ bb0: { StorageLive(_4); StorageLive(_5); - _5 = _1; + _5 = copy _1; - _4 = ptr_metadata::(move _5) -> [return: bb1, unwind unreachable]; + _4 = PtrMetadata(move _5); + goto -> bb1; @@ -35,7 +35,7 @@ StorageDead(_5); StorageLive(_6); StorageLive(_7); - _7 = _2; + _7 = copy _2; - _6 = ptr_metadata::<[u8], usize>(move _7) -> [return: bb2, unwind unreachable]; + _6 = PtrMetadata(move _7); + goto -> bb2; @@ -45,7 +45,7 @@ StorageDead(_7); StorageLive(_8); StorageLive(_9); - _9 = _3; + _9 = copy _3; - _8 = ptr_metadata::>(move _9) -> [return: bb3, unwind unreachable]; + _8 = PtrMetadata(move _9); + goto -> bb3; diff --git a/tests/mir-opt/lower_intrinsics.get_metadata.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.get_metadata.LowerIntrinsics.panic-unwind.diff index d256058c05e..f2cfce1b6e3 100644 --- a/tests/mir-opt/lower_intrinsics.get_metadata.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.get_metadata.LowerIntrinsics.panic-unwind.diff @@ -25,7 +25,7 @@ bb0: { StorageLive(_4); StorageLive(_5); - _5 = _1; + _5 = copy _1; - _4 = ptr_metadata::(move _5) -> [return: bb1, unwind unreachable]; + _4 = PtrMetadata(move _5); + goto -> bb1; @@ -35,7 +35,7 @@ StorageDead(_5); StorageLive(_6); StorageLive(_7); - _7 = _2; + _7 = copy _2; - _6 = ptr_metadata::<[u8], usize>(move _7) -> [return: bb2, unwind unreachable]; + _6 = PtrMetadata(move _7); + goto -> bb2; @@ -45,7 +45,7 @@ StorageDead(_7); StorageLive(_8); StorageLive(_9); - _9 = _3; + _9 = copy _3; - _8 = ptr_metadata::>(move _9) -> [return: bb3, unwind unreachable]; + _8 = PtrMetadata(move _9); + goto -> bb3; diff --git a/tests/mir-opt/lower_intrinsics.make_pointers.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.make_pointers.LowerIntrinsics.panic-abort.diff index 02934d4c01e..b282509c068 100644 --- a/tests/mir-opt/lower_intrinsics.make_pointers.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.make_pointers.LowerIntrinsics.panic-abort.diff @@ -34,7 +34,7 @@ bb0: { StorageLive(_4); StorageLive(_5); - _5 = _1; + _5 = copy _1; StorageLive(_6); _6 = (); - _4 = aggregate_raw_ptr::<*const i32, *const u8, ()>(move _5, move _6) -> [return: bb1, unwind unreachable]; @@ -47,7 +47,7 @@ StorageDead(_5); StorageLive(_7); StorageLive(_8); - _8 = _2; + _8 = copy _2; StorageLive(_9); _9 = (); - _7 = aggregate_raw_ptr::<*mut u8, *mut (), ()>(move _8, move _9) -> [return: bb2, unwind unreachable]; @@ -60,9 +60,9 @@ StorageDead(_8); StorageLive(_10); StorageLive(_11); - _11 = _1; + _11 = copy _1; StorageLive(_12); - _12 = _3; + _12 = copy _3; - _10 = aggregate_raw_ptr::<*const [u16], *const u8, usize>(move _11, move _12) -> [return: bb3, unwind unreachable]; + _10 = *const [u16] from (move _11, move _12); + goto -> bb3; @@ -73,9 +73,9 @@ StorageDead(_11); StorageLive(_13); StorageLive(_14); - _14 = _2; + _14 = copy _2; StorageLive(_15); - _15 = _3; + _15 = copy _3; - _13 = aggregate_raw_ptr::<*mut [u64], *mut (), usize>(move _14, move _15) -> [return: bb4, unwind unreachable]; + _13 = *mut [u64] from (move _14, move _15); + goto -> bb4; diff --git a/tests/mir-opt/lower_intrinsics.make_pointers.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.make_pointers.LowerIntrinsics.panic-unwind.diff index 02934d4c01e..b282509c068 100644 --- a/tests/mir-opt/lower_intrinsics.make_pointers.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.make_pointers.LowerIntrinsics.panic-unwind.diff @@ -34,7 +34,7 @@ bb0: { StorageLive(_4); StorageLive(_5); - _5 = _1; + _5 = copy _1; StorageLive(_6); _6 = (); - _4 = aggregate_raw_ptr::<*const i32, *const u8, ()>(move _5, move _6) -> [return: bb1, unwind unreachable]; @@ -47,7 +47,7 @@ StorageDead(_5); StorageLive(_7); StorageLive(_8); - _8 = _2; + _8 = copy _2; StorageLive(_9); _9 = (); - _7 = aggregate_raw_ptr::<*mut u8, *mut (), ()>(move _8, move _9) -> [return: bb2, unwind unreachable]; @@ -60,9 +60,9 @@ StorageDead(_8); StorageLive(_10); StorageLive(_11); - _11 = _1; + _11 = copy _1; StorageLive(_12); - _12 = _3; + _12 = copy _3; - _10 = aggregate_raw_ptr::<*const [u16], *const u8, usize>(move _11, move _12) -> [return: bb3, unwind unreachable]; + _10 = *const [u16] from (move _11, move _12); + goto -> bb3; @@ -73,9 +73,9 @@ StorageDead(_11); StorageLive(_13); StorageLive(_14); - _14 = _2; + _14 = copy _2; StorageLive(_15); - _15 = _3; + _15 = copy _3; - _13 = aggregate_raw_ptr::<*mut [u64], *mut (), usize>(move _14, move _15) -> [return: bb4, unwind unreachable]; + _13 = *mut [u64] from (move _14, move _15); + goto -> bb4; diff --git a/tests/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.panic-abort.diff index 069a82b9521..5aa98698476 100644 --- a/tests/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.panic-abort.diff @@ -13,7 +13,7 @@ StorageLive(_1); _1 = std::intrinsics::size_of::; StorageLive(_2); - _2 = _1; + _2 = copy _1; - _0 = move _2() -> [return: bb1, unwind unreachable]; + _0 = SizeOf(T); + goto -> bb1; diff --git a/tests/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.panic-unwind.diff index 069a82b9521..5aa98698476 100644 --- a/tests/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.panic-unwind.diff @@ -13,7 +13,7 @@ StorageLive(_1); _1 = std::intrinsics::size_of::; StorageLive(_2); - _2 = _1; + _2 = copy _1; - _0 = move _2() -> [return: bb1, unwind unreachable]; + _0 = SizeOf(T); + goto -> bb1; diff --git a/tests/mir-opt/lower_intrinsics.ptr_offset.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.ptr_offset.LowerIntrinsics.panic-abort.diff index 4f7ad0b6094..62cce84f695 100644 --- a/tests/mir-opt/lower_intrinsics.ptr_offset.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.ptr_offset.LowerIntrinsics.panic-abort.diff @@ -10,9 +10,9 @@ bb0: { StorageLive(_3); - _3 = _1; + _3 = copy _1; StorageLive(_4); - _4 = _2; + _4 = copy _2; - _0 = offset::<*const i32, isize>(move _3, move _4) -> [return: bb1, unwind unreachable]; + _0 = Offset(move _3, move _4); + goto -> bb1; diff --git a/tests/mir-opt/lower_intrinsics.ptr_offset.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.ptr_offset.LowerIntrinsics.panic-unwind.diff index 4f7ad0b6094..62cce84f695 100644 --- a/tests/mir-opt/lower_intrinsics.ptr_offset.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.ptr_offset.LowerIntrinsics.panic-unwind.diff @@ -10,9 +10,9 @@ bb0: { StorageLive(_3); - _3 = _1; + _3 = copy _1; StorageLive(_4); - _4 = _2; + _4 = copy _2; - _0 = offset::<*const i32, isize>(move _3, move _4) -> [return: bb1, unwind unreachable]; + _0 = Offset(move _3, move _4); + goto -> bb1; diff --git a/tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.panic-abort.diff index 781104be290..95717d03b61 100644 --- a/tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.panic-abort.diff @@ -10,7 +10,7 @@ StorageLive(_2); _2 = &raw const (*_1); - _0 = read_via_copy::(move _2) -> [return: bb1, unwind unreachable]; -+ _0 = (*_2); ++ _0 = copy (*_2); + goto -> bb1; } diff --git a/tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.panic-unwind.diff index 781104be290..95717d03b61 100644 --- a/tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.panic-unwind.diff @@ -10,7 +10,7 @@ StorageLive(_2); _2 = &raw const (*_1); - _0 = read_via_copy::(move _2) -> [return: bb1, unwind unreachable]; -+ _0 = (*_2); ++ _0 = copy (*_2); + goto -> bb1; } diff --git a/tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.panic-abort.diff index 56c357b3776..8828549249e 100644 --- a/tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.panic-abort.diff @@ -10,7 +10,7 @@ StorageLive(_2); _2 = &raw const (*_1); - _0 = read_via_copy::(move _2) -> unwind unreachable; -+ _0 = (*_2); ++ _0 = copy (*_2); + unreachable; } } diff --git a/tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.panic-unwind.diff index 56c357b3776..8828549249e 100644 --- a/tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.panic-unwind.diff @@ -10,7 +10,7 @@ StorageLive(_2); _2 = &raw const (*_1); - _0 = read_via_copy::(move _2) -> unwind unreachable; -+ _0 = (*_2); ++ _0 = copy (*_2); + unreachable; } } diff --git a/tests/mir-opt/lower_intrinsics.rs b/tests/mir-opt/lower_intrinsics.rs index 2569f4f4de5..4859d935461 100644 --- a/tests/mir-opt/lower_intrinsics.rs +++ b/tests/mir-opt/lower_intrinsics.rs @@ -197,7 +197,7 @@ pub fn with_overflow(a: i32, b: i32) { pub fn read_via_copy_primitive(r: &i32) -> i32 { // CHECK-LABEL: fn read_via_copy_primitive( // CHECK: [[tmp:_.*]] = &raw const (*_1); - // CHECK: _0 = (*[[tmp]]); + // CHECK: _0 = copy (*[[tmp]]); // CHECK: return; unsafe { core::intrinsics::read_via_copy(r) } @@ -207,7 +207,7 @@ pub fn read_via_copy_primitive(r: &i32) -> i32 { pub fn read_via_copy_uninhabited(r: &Never) -> Never { // CHECK-LABEL: fn read_via_copy_uninhabited( // CHECK: [[tmp:_.*]] = &raw const (*_1); - // CHECK: _0 = (*[[tmp]]); + // CHECK: _0 = copy (*[[tmp]]); // CHECK: unreachable; unsafe { core::intrinsics::read_via_copy(r) } diff --git a/tests/mir-opt/lower_intrinsics.three_way_compare_char.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.three_way_compare_char.LowerIntrinsics.panic-abort.diff index 816d6209715..f29bc5dfc6e 100644 --- a/tests/mir-opt/lower_intrinsics.three_way_compare_char.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.three_way_compare_char.LowerIntrinsics.panic-abort.diff @@ -15,9 +15,9 @@ bb0: { StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; StorageLive(_5); - _5 = _2; + _5 = copy _2; - _3 = three_way_compare::(move _4, move _5) -> [return: bb1, unwind unreachable]; + _3 = Cmp(move _4, move _5); + goto -> bb1; diff --git a/tests/mir-opt/lower_intrinsics.three_way_compare_char.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.three_way_compare_char.LowerIntrinsics.panic-unwind.diff index 80b4bd7a2be..596ad70b3bf 100644 --- a/tests/mir-opt/lower_intrinsics.three_way_compare_char.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.three_way_compare_char.LowerIntrinsics.panic-unwind.diff @@ -15,9 +15,9 @@ bb0: { StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; StorageLive(_5); - _5 = _2; + _5 = copy _2; - _3 = three_way_compare::(move _4, move _5) -> [return: bb1, unwind continue]; + _3 = Cmp(move _4, move _5); + goto -> bb1; diff --git a/tests/mir-opt/lower_intrinsics.three_way_compare_signed.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.three_way_compare_signed.LowerIntrinsics.panic-abort.diff index 05c20aaa09a..654cb2503df 100644 --- a/tests/mir-opt/lower_intrinsics.three_way_compare_signed.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.three_way_compare_signed.LowerIntrinsics.panic-abort.diff @@ -12,9 +12,9 @@ bb0: { StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; StorageLive(_5); - _5 = _2; + _5 = copy _2; - _3 = three_way_compare::(move _4, move _5) -> [return: bb1, unwind unreachable]; + _3 = Cmp(move _4, move _5); + goto -> bb1; diff --git a/tests/mir-opt/lower_intrinsics.three_way_compare_signed.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.three_way_compare_signed.LowerIntrinsics.panic-unwind.diff index 8a254d02a47..987c2166692 100644 --- a/tests/mir-opt/lower_intrinsics.three_way_compare_signed.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.three_way_compare_signed.LowerIntrinsics.panic-unwind.diff @@ -12,9 +12,9 @@ bb0: { StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; StorageLive(_5); - _5 = _2; + _5 = copy _2; - _3 = three_way_compare::(move _4, move _5) -> [return: bb1, unwind continue]; + _3 = Cmp(move _4, move _5); + goto -> bb1; diff --git a/tests/mir-opt/lower_intrinsics.three_way_compare_unsigned.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.three_way_compare_unsigned.LowerIntrinsics.panic-abort.diff index 437614ec673..82c89b7ce54 100644 --- a/tests/mir-opt/lower_intrinsics.three_way_compare_unsigned.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.three_way_compare_unsigned.LowerIntrinsics.panic-abort.diff @@ -15,9 +15,9 @@ bb0: { StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; StorageLive(_5); - _5 = _2; + _5 = copy _2; - _3 = three_way_compare::(move _4, move _5) -> [return: bb1, unwind unreachable]; + _3 = Cmp(move _4, move _5); + goto -> bb1; diff --git a/tests/mir-opt/lower_intrinsics.three_way_compare_unsigned.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.three_way_compare_unsigned.LowerIntrinsics.panic-unwind.diff index 7d6137979c8..d7ec6dcfa2c 100644 --- a/tests/mir-opt/lower_intrinsics.three_way_compare_unsigned.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.three_way_compare_unsigned.LowerIntrinsics.panic-unwind.diff @@ -15,9 +15,9 @@ bb0: { StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; StorageLive(_5); - _5 = _2; + _5 = copy _2; - _3 = three_way_compare::(move _4, move _5) -> [return: bb1, unwind continue]; + _3 = Cmp(move _4, move _5); + goto -> bb1; diff --git a/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.panic-abort.diff index 6e542c4b5a7..b1104c70e46 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.panic-abort.diff @@ -8,8 +8,8 @@ bb0: { StorageLive(_2); - _2 = _1; -- _0 = transmute::(move _2) -> [return: bb1, unwind unreachable]; + _2 = copy _1; +- _0 = std::intrinsics::transmute::(move _2) -> [return: bb1, unwind unreachable]; + _0 = move _2 as i8 (Transmute); + goto -> bb1; } diff --git a/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.panic-unwind.diff index 6e542c4b5a7..b1104c70e46 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.panic-unwind.diff @@ -8,8 +8,8 @@ bb0: { StorageLive(_2); - _2 = _1; -- _0 = transmute::(move _2) -> [return: bb1, unwind unreachable]; + _2 = copy _1; +- _0 = std::intrinsics::transmute::(move _2) -> [return: bb1, unwind unreachable]; + _0 = move _2 as i8 (Transmute); + goto -> bb1; } diff --git a/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.panic-abort.diff index ab4646370f1..169e48a31dd 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.panic-abort.diff @@ -8,8 +8,8 @@ bb0: { StorageLive(_2); - _2 = _1; -- _0 = transmute::<&T, *const T>(move _2) -> [return: bb1, unwind unreachable]; + _2 = copy _1; +- _0 = std::intrinsics::transmute::<&T, *const T>(move _2) -> [return: bb1, unwind unreachable]; + _0 = move _2 as *const T (Transmute); + goto -> bb1; } diff --git a/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.panic-unwind.diff index ab4646370f1..169e48a31dd 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.panic-unwind.diff @@ -8,8 +8,8 @@ bb0: { StorageLive(_2); - _2 = _1; -- _0 = transmute::<&T, *const T>(move _2) -> [return: bb1, unwind unreachable]; + _2 = copy _1; +- _0 = std::intrinsics::transmute::<&T, *const T>(move _2) -> [return: bb1, unwind unreachable]; + _0 = move _2 as *const T (Transmute); + goto -> bb1; } diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.panic-abort.diff index c4a3358ffa3..7098b4d3168 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.panic-abort.diff @@ -11,13 +11,13 @@ bb0: { StorageLive(_1); -- _1 = transmute::>(const 1_usize) -> [return: bb1, unwind unreachable]; +- _1 = std::intrinsics::transmute::>(const 1_usize) -> [return: bb1, unwind unreachable]; + _1 = const 1_usize as std::boxed::Box (Transmute); + goto -> bb1; } bb1: { - _2 = (((_1.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const Never); + _2 = copy (((_1.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const Never); PlaceMention((*_2)); unreachable; } diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.panic-unwind.diff index c4a3358ffa3..7098b4d3168 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.panic-unwind.diff @@ -11,13 +11,13 @@ bb0: { StorageLive(_1); -- _1 = transmute::>(const 1_usize) -> [return: bb1, unwind unreachable]; +- _1 = std::intrinsics::transmute::>(const 1_usize) -> [return: bb1, unwind unreachable]; + _1 = const 1_usize as std::boxed::Box (Transmute); + goto -> bb1; } bb1: { - _2 = (((_1.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const Never); + _2 = copy (((_1.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const Never); PlaceMention((*_2)); unreachable; } diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.panic-abort.diff index c2c4ec0003c..06225fffd7c 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.panic-abort.diff @@ -10,7 +10,7 @@ bb0: { StorageLive(_1); -- _1 = transmute::(const 1_usize) -> [return: bb1, unwind unreachable]; +- _1 = std::intrinsics::transmute::(const 1_usize) -> [return: bb1, unwind unreachable]; + _1 = const 1_usize as &mut Never (Transmute); + goto -> bb1; } diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.panic-unwind.diff index c2c4ec0003c..06225fffd7c 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.panic-unwind.diff @@ -10,7 +10,7 @@ bb0: { StorageLive(_1); -- _1 = transmute::(const 1_usize) -> [return: bb1, unwind unreachable]; +- _1 = std::intrinsics::transmute::(const 1_usize) -> [return: bb1, unwind unreachable]; + _1 = const 1_usize as &mut Never (Transmute); + goto -> bb1; } diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.panic-abort.diff index 1b516a1f53b..dd6ab3a9c97 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.panic-abort.diff @@ -10,7 +10,7 @@ bb0: { StorageLive(_1); -- _1 = transmute::(const 1_usize) -> [return: bb1, unwind unreachable]; +- _1 = std::intrinsics::transmute::(const 1_usize) -> [return: bb1, unwind unreachable]; + _1 = const 1_usize as &Never (Transmute); + goto -> bb1; } diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.panic-unwind.diff index 1b516a1f53b..dd6ab3a9c97 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.panic-unwind.diff @@ -10,7 +10,7 @@ bb0: { StorageLive(_1); -- _1 = transmute::(const 1_usize) -> [return: bb1, unwind unreachable]; +- _1 = std::intrinsics::transmute::(const 1_usize) -> [return: bb1, unwind unreachable]; + _1 = const 1_usize as &Never (Transmute); + goto -> bb1; } diff --git a/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.panic-abort.diff index 6d3ad348988..6571f3d9db8 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.panic-abort.diff @@ -8,8 +8,8 @@ bb0: { StorageLive(_2); - _2 = _1; -- _0 = transmute::<(), Never>(move _2) -> unwind unreachable; + _2 = copy _1; +- _0 = std::intrinsics::transmute::<(), Never>(move _2) -> unwind unreachable; + _0 = move _2 as Never (Transmute); + unreachable; } diff --git a/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.panic-unwind.diff index 6d3ad348988..6571f3d9db8 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.panic-unwind.diff @@ -8,8 +8,8 @@ bb0: { StorageLive(_2); - _2 = _1; -- _0 = transmute::<(), Never>(move _2) -> unwind unreachable; + _2 = copy _1; +- _0 = std::intrinsics::transmute::<(), Never>(move _2) -> unwind unreachable; + _0 = move _2 as Never (Transmute); + unreachable; } diff --git a/tests/mir-opt/lower_intrinsics.unchecked.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.unchecked.LowerIntrinsics.panic-abort.diff index 3c9694d0370..d0d38462f8d 100644 --- a/tests/mir-opt/lower_intrinsics.unchecked.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.unchecked.LowerIntrinsics.panic-abort.diff @@ -64,9 +64,9 @@ bb0: { StorageLive(_4); StorageLive(_5); - _5 = _1; + _5 = copy _1; StorageLive(_6); - _6 = _2; + _6 = copy _2; - _4 = unchecked_add::(move _5, move _6) -> [return: bb1, unwind unreachable]; + _4 = AddUnchecked(move _5, move _6); + goto -> bb1; @@ -77,9 +77,9 @@ StorageDead(_5); StorageLive(_7); StorageLive(_8); - _8 = _1; + _8 = copy _1; StorageLive(_9); - _9 = _2; + _9 = copy _2; - _7 = unchecked_sub::(move _8, move _9) -> [return: bb2, unwind unreachable]; + _7 = SubUnchecked(move _8, move _9); + goto -> bb2; @@ -90,9 +90,9 @@ StorageDead(_8); StorageLive(_10); StorageLive(_11); - _11 = _1; + _11 = copy _1; StorageLive(_12); - _12 = _2; + _12 = copy _2; - _10 = unchecked_mul::(move _11, move _12) -> [return: bb3, unwind unreachable]; + _10 = MulUnchecked(move _11, move _12); + goto -> bb3; @@ -103,9 +103,9 @@ StorageDead(_11); StorageLive(_13); StorageLive(_14); - _14 = _1; + _14 = copy _1; StorageLive(_15); - _15 = _2; + _15 = copy _2; - _13 = unchecked_div::(move _14, move _15) -> [return: bb4, unwind unreachable]; + _13 = Div(move _14, move _15); + goto -> bb4; @@ -116,9 +116,9 @@ StorageDead(_14); StorageLive(_16); StorageLive(_17); - _17 = _1; + _17 = copy _1; StorageLive(_18); - _18 = _2; + _18 = copy _2; - _16 = unchecked_rem::(move _17, move _18) -> [return: bb5, unwind unreachable]; + _16 = Rem(move _17, move _18); + goto -> bb5; @@ -129,9 +129,9 @@ StorageDead(_17); StorageLive(_19); StorageLive(_20); - _20 = _1; + _20 = copy _1; StorageLive(_21); - _21 = _2; + _21 = copy _2; - _19 = unchecked_shl::(move _20, move _21) -> [return: bb6, unwind unreachable]; + _19 = ShlUnchecked(move _20, move _21); + goto -> bb6; @@ -142,9 +142,9 @@ StorageDead(_20); StorageLive(_22); StorageLive(_23); - _23 = _1; + _23 = copy _1; StorageLive(_24); - _24 = _2; + _24 = copy _2; - _22 = unchecked_shr::(move _23, move _24) -> [return: bb7, unwind unreachable]; + _22 = ShrUnchecked(move _23, move _24); + goto -> bb7; @@ -155,9 +155,9 @@ StorageDead(_23); StorageLive(_25); StorageLive(_26); - _26 = _1; + _26 = copy _1; StorageLive(_27); - _27 = _3; + _27 = copy _3; - _25 = unchecked_shl::(move _26, move _27) -> [return: bb8, unwind unreachable]; + _25 = ShlUnchecked(move _26, move _27); + goto -> bb8; @@ -168,9 +168,9 @@ StorageDead(_26); StorageLive(_28); StorageLive(_29); - _29 = _1; + _29 = copy _1; StorageLive(_30); - _30 = _3; + _30 = copy _3; - _28 = unchecked_shr::(move _29, move _30) -> [return: bb9, unwind unreachable]; + _28 = ShrUnchecked(move _29, move _30); + goto -> bb9; diff --git a/tests/mir-opt/lower_intrinsics.unchecked.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.unchecked.LowerIntrinsics.panic-unwind.diff index 3c9694d0370..d0d38462f8d 100644 --- a/tests/mir-opt/lower_intrinsics.unchecked.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.unchecked.LowerIntrinsics.panic-unwind.diff @@ -64,9 +64,9 @@ bb0: { StorageLive(_4); StorageLive(_5); - _5 = _1; + _5 = copy _1; StorageLive(_6); - _6 = _2; + _6 = copy _2; - _4 = unchecked_add::(move _5, move _6) -> [return: bb1, unwind unreachable]; + _4 = AddUnchecked(move _5, move _6); + goto -> bb1; @@ -77,9 +77,9 @@ StorageDead(_5); StorageLive(_7); StorageLive(_8); - _8 = _1; + _8 = copy _1; StorageLive(_9); - _9 = _2; + _9 = copy _2; - _7 = unchecked_sub::(move _8, move _9) -> [return: bb2, unwind unreachable]; + _7 = SubUnchecked(move _8, move _9); + goto -> bb2; @@ -90,9 +90,9 @@ StorageDead(_8); StorageLive(_10); StorageLive(_11); - _11 = _1; + _11 = copy _1; StorageLive(_12); - _12 = _2; + _12 = copy _2; - _10 = unchecked_mul::(move _11, move _12) -> [return: bb3, unwind unreachable]; + _10 = MulUnchecked(move _11, move _12); + goto -> bb3; @@ -103,9 +103,9 @@ StorageDead(_11); StorageLive(_13); StorageLive(_14); - _14 = _1; + _14 = copy _1; StorageLive(_15); - _15 = _2; + _15 = copy _2; - _13 = unchecked_div::(move _14, move _15) -> [return: bb4, unwind unreachable]; + _13 = Div(move _14, move _15); + goto -> bb4; @@ -116,9 +116,9 @@ StorageDead(_14); StorageLive(_16); StorageLive(_17); - _17 = _1; + _17 = copy _1; StorageLive(_18); - _18 = _2; + _18 = copy _2; - _16 = unchecked_rem::(move _17, move _18) -> [return: bb5, unwind unreachable]; + _16 = Rem(move _17, move _18); + goto -> bb5; @@ -129,9 +129,9 @@ StorageDead(_17); StorageLive(_19); StorageLive(_20); - _20 = _1; + _20 = copy _1; StorageLive(_21); - _21 = _2; + _21 = copy _2; - _19 = unchecked_shl::(move _20, move _21) -> [return: bb6, unwind unreachable]; + _19 = ShlUnchecked(move _20, move _21); + goto -> bb6; @@ -142,9 +142,9 @@ StorageDead(_20); StorageLive(_22); StorageLive(_23); - _23 = _1; + _23 = copy _1; StorageLive(_24); - _24 = _2; + _24 = copy _2; - _22 = unchecked_shr::(move _23, move _24) -> [return: bb7, unwind unreachable]; + _22 = ShrUnchecked(move _23, move _24); + goto -> bb7; @@ -155,9 +155,9 @@ StorageDead(_23); StorageLive(_25); StorageLive(_26); - _26 = _1; + _26 = copy _1; StorageLive(_27); - _27 = _3; + _27 = copy _3; - _25 = unchecked_shl::(move _26, move _27) -> [return: bb8, unwind unreachable]; + _25 = ShlUnchecked(move _26, move _27); + goto -> bb8; @@ -168,9 +168,9 @@ StorageDead(_26); StorageLive(_28); StorageLive(_29); - _29 = _1; + _29 = copy _1; StorageLive(_30); - _30 = _3; + _30 = copy _3; - _28 = unchecked_shr::(move _29, move _30) -> [return: bb9, unwind unreachable]; + _28 = ShrUnchecked(move _29, move _30); + goto -> bb9; diff --git a/tests/mir-opt/lower_intrinsics.with_overflow.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.with_overflow.LowerIntrinsics.panic-abort.diff index efbbeeeac73..a9bb5e7e3a4 100644 --- a/tests/mir-opt/lower_intrinsics.with_overflow.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.with_overflow.LowerIntrinsics.panic-abort.diff @@ -27,9 +27,9 @@ bb0: { StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; StorageLive(_5); - _5 = _2; + _5 = copy _2; - _3 = add_with_overflow::(move _4, move _5) -> [return: bb1, unwind unreachable]; + _3 = AddWithOverflow(move _4, move _5); + goto -> bb1; @@ -40,9 +40,9 @@ StorageDead(_4); StorageLive(_6); StorageLive(_7); - _7 = _1; + _7 = copy _1; StorageLive(_8); - _8 = _2; + _8 = copy _2; - _6 = sub_with_overflow::(move _7, move _8) -> [return: bb2, unwind unreachable]; + _6 = SubWithOverflow(move _7, move _8); + goto -> bb2; @@ -53,9 +53,9 @@ StorageDead(_7); StorageLive(_9); StorageLive(_10); - _10 = _1; + _10 = copy _1; StorageLive(_11); - _11 = _2; + _11 = copy _2; - _9 = mul_with_overflow::(move _10, move _11) -> [return: bb3, unwind unreachable]; + _9 = MulWithOverflow(move _10, move _11); + goto -> bb3; diff --git a/tests/mir-opt/lower_intrinsics.with_overflow.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.with_overflow.LowerIntrinsics.panic-unwind.diff index efbbeeeac73..a9bb5e7e3a4 100644 --- a/tests/mir-opt/lower_intrinsics.with_overflow.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.with_overflow.LowerIntrinsics.panic-unwind.diff @@ -27,9 +27,9 @@ bb0: { StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; StorageLive(_5); - _5 = _2; + _5 = copy _2; - _3 = add_with_overflow::(move _4, move _5) -> [return: bb1, unwind unreachable]; + _3 = AddWithOverflow(move _4, move _5); + goto -> bb1; @@ -40,9 +40,9 @@ StorageDead(_4); StorageLive(_6); StorageLive(_7); - _7 = _1; + _7 = copy _1; StorageLive(_8); - _8 = _2; + _8 = copy _2; - _6 = sub_with_overflow::(move _7, move _8) -> [return: bb2, unwind unreachable]; + _6 = SubWithOverflow(move _7, move _8); + goto -> bb2; @@ -53,9 +53,9 @@ StorageDead(_7); StorageLive(_9); StorageLive(_10); - _10 = _1; + _10 = copy _1; StorageLive(_11); - _11 = _2; + _11 = copy _2; - _9 = mul_with_overflow::(move _10, move _11) -> [return: bb3, unwind unreachable]; + _9 = MulWithOverflow(move _10, move _11); + goto -> bb3; diff --git a/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.panic-abort.diff index 2acb193e054..552b1a9a32b 100644 --- a/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.panic-abort.diff @@ -27,9 +27,9 @@ bb0: { StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; StorageLive(_5); - _5 = _2; + _5 = copy _2; - _3 = std::intrinsics::wrapping_add::(move _4, move _5) -> [return: bb1, unwind unreachable]; + _3 = Add(move _4, move _5); + goto -> bb1; @@ -40,9 +40,9 @@ StorageDead(_4); StorageLive(_6); StorageLive(_7); - _7 = _1; + _7 = copy _1; StorageLive(_8); - _8 = _2; + _8 = copy _2; - _6 = std::intrinsics::wrapping_sub::(move _7, move _8) -> [return: bb2, unwind unreachable]; + _6 = Sub(move _7, move _8); + goto -> bb2; @@ -53,9 +53,9 @@ StorageDead(_7); StorageLive(_9); StorageLive(_10); - _10 = _1; + _10 = copy _1; StorageLive(_11); - _11 = _2; + _11 = copy _2; - _9 = wrapping_mul::(move _10, move _11) -> [return: bb3, unwind unreachable]; + _9 = Mul(move _10, move _11); + goto -> bb3; diff --git a/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.panic-unwind.diff index 2acb193e054..552b1a9a32b 100644 --- a/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.panic-unwind.diff @@ -27,9 +27,9 @@ bb0: { StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; StorageLive(_5); - _5 = _2; + _5 = copy _2; - _3 = std::intrinsics::wrapping_add::(move _4, move _5) -> [return: bb1, unwind unreachable]; + _3 = Add(move _4, move _5); + goto -> bb1; @@ -40,9 +40,9 @@ StorageDead(_4); StorageLive(_6); StorageLive(_7); - _7 = _1; + _7 = copy _1; StorageLive(_8); - _8 = _2; + _8 = copy _2; - _6 = std::intrinsics::wrapping_sub::(move _7, move _8) -> [return: bb2, unwind unreachable]; + _6 = Sub(move _7, move _8); + goto -> bb2; @@ -53,9 +53,9 @@ StorageDead(_7); StorageLive(_9); StorageLive(_10); - _10 = _1; + _10 = copy _1; StorageLive(_11); - _11 = _2; + _11 = copy _2; - _9 = wrapping_mul::(move _10, move _11) -> [return: bb3, unwind unreachable]; + _9 = Mul(move _10, move _11); + goto -> bb3; diff --git a/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.panic-abort.diff b/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.panic-abort.diff index a212ee67881..20001f1248e 100644 --- a/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.panic-abort.diff +++ b/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.panic-abort.diff @@ -16,7 +16,7 @@ bb0: { StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; StorageLive(_5); StorageLive(_6); _6 = &(*_2); @@ -35,14 +35,14 @@ StorageDead(_5); StorageDead(_4); StorageLive(_7); - _7 = _1; + _7 = copy _1; _8 = Len((*_2)); - _9 = Lt(_7, _8); - assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, _7) -> [success: bb3, unwind unreachable]; + _9 = Lt(copy _7, copy _8); + assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, copy _7) -> [success: bb3, unwind unreachable]; } bb3: { - _0 = (*_2)[_7]; + _0 = copy (*_2)[_7]; StorageDead(_7); goto -> bb5; } diff --git a/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.panic-unwind.diff b/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.panic-unwind.diff index 38ec8a5b0c7..ca8f92df5de 100644 --- a/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.panic-unwind.diff +++ b/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.panic-unwind.diff @@ -16,7 +16,7 @@ bb0: { StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; StorageLive(_5); StorageLive(_6); _6 = &(*_2); @@ -35,14 +35,14 @@ StorageDead(_5); StorageDead(_4); StorageLive(_7); - _7 = _1; + _7 = copy _1; _8 = Len((*_2)); - _9 = Lt(_7, _8); - assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, _7) -> [success: bb3, unwind continue]; + _9 = Lt(copy _7, copy _8); + assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, copy _7) -> [success: bb3, unwind continue]; } bb3: { - _0 = (*_2)[_7]; + _0 = copy (*_2)[_7]; StorageDead(_7); goto -> bb5; } diff --git a/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff index 3c4a84bc243..b3eb3e1f8b9 100644 --- a/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff +++ b/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff @@ -32,22 +32,22 @@ bb0: { PlaceMention(_2); -- switchInt((_2.0: bool)) -> [0: bb2, otherwise: bb1]; -+ switchInt((_2.0: bool)) -> [0: bb6, otherwise: bb1]; +- switchInt(copy (_2.0: bool)) -> [0: bb2, otherwise: bb1]; ++ switchInt(copy (_2.0: bool)) -> [0: bb6, otherwise: bb1]; } bb1: { -- switchInt((_2.1: bool)) -> [0: bb4, otherwise: bb3]; -+ switchInt((_2.1: bool)) -> [0: bb5, otherwise: bb2]; +- switchInt(copy (_2.1: bool)) -> [0: bb4, otherwise: bb3]; ++ switchInt(copy (_2.1: bool)) -> [0: bb5, otherwise: bb2]; } bb2: { - falseEdge -> [real: bb9, imaginary: bb1]; -+ switchInt((_2.0: bool)) -> [0: bb3, otherwise: bb4]; ++ switchInt(copy (_2.0: bool)) -> [0: bb3, otherwise: bb4]; } bb3: { -- switchInt((_2.0: bool)) -> [0: bb6, otherwise: bb5]; +- switchInt(copy (_2.0: bool)) -> [0: bb6, otherwise: bb5]; - } - - bb4: { @@ -60,7 +60,7 @@ - - bb6: { StorageLive(_15); - _15 = (_2.1: bool); + _15 = copy (_2.1: bool); StorageLive(_16); _16 = move (_2.2: std::string::String); - goto -> bb20; @@ -70,7 +70,7 @@ - bb7: { + bb4: { StorageLive(_15); - _15 = (_2.1: bool); + _15 = copy (_2.1: bool); StorageLive(_16); _16 = move (_2.2: std::string::String); - goto -> bb20; @@ -87,7 +87,7 @@ - _4 = &fake shallow (_2.1: bool); StorageLive(_12); StorageLive(_13); - _13 = _1; + _13 = copy _1; - switchInt(move _13) -> [0: bb16, otherwise: bb15]; + switchInt(move _13) -> [0: bb13, otherwise: bb12]; } @@ -102,7 +102,7 @@ - _4 = &fake shallow (_2.1: bool); StorageLive(_9); StorageLive(_10); - _10 = _1; + _10 = copy _1; - switchInt(move _10) -> [0: bb12, otherwise: bb11]; + switchInt(move _10) -> [0: bb9, otherwise: bb8]; } @@ -125,7 +125,7 @@ - bb12: { + bb9: { - _9 = (*_6); + _9 = copy (*_6); - switchInt(move _9) -> [0: bb14, otherwise: bb13]; + switchInt(move _9) -> [0: bb11, otherwise: bb10]; } @@ -139,7 +139,7 @@ - FakeRead(ForGuardBinding, _6); - FakeRead(ForGuardBinding, _8); StorageLive(_5); - _5 = (_2.1: bool); + _5 = copy (_2.1: bool); StorageLive(_7); _7 = move (_2.2: std::string::String); - goto -> bb10; @@ -167,7 +167,7 @@ - bb16: { + bb13: { - _12 = (*_6); + _12 = copy (*_6); - switchInt(move _12) -> [0: bb18, otherwise: bb17]; + switchInt(move _12) -> [0: bb15, otherwise: bb14]; } @@ -181,7 +181,7 @@ - FakeRead(ForGuardBinding, _6); - FakeRead(ForGuardBinding, _8); StorageLive(_5); - _5 = (_2.0: bool); + _5 = copy (_2.0: bool); StorageLive(_7); _7 = move (_2.2: std::string::String); - goto -> bb10; diff --git a/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff index 3c4a84bc243..b3eb3e1f8b9 100644 --- a/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff +++ b/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff @@ -32,22 +32,22 @@ bb0: { PlaceMention(_2); -- switchInt((_2.0: bool)) -> [0: bb2, otherwise: bb1]; -+ switchInt((_2.0: bool)) -> [0: bb6, otherwise: bb1]; +- switchInt(copy (_2.0: bool)) -> [0: bb2, otherwise: bb1]; ++ switchInt(copy (_2.0: bool)) -> [0: bb6, otherwise: bb1]; } bb1: { -- switchInt((_2.1: bool)) -> [0: bb4, otherwise: bb3]; -+ switchInt((_2.1: bool)) -> [0: bb5, otherwise: bb2]; +- switchInt(copy (_2.1: bool)) -> [0: bb4, otherwise: bb3]; ++ switchInt(copy (_2.1: bool)) -> [0: bb5, otherwise: bb2]; } bb2: { - falseEdge -> [real: bb9, imaginary: bb1]; -+ switchInt((_2.0: bool)) -> [0: bb3, otherwise: bb4]; ++ switchInt(copy (_2.0: bool)) -> [0: bb3, otherwise: bb4]; } bb3: { -- switchInt((_2.0: bool)) -> [0: bb6, otherwise: bb5]; +- switchInt(copy (_2.0: bool)) -> [0: bb6, otherwise: bb5]; - } - - bb4: { @@ -60,7 +60,7 @@ - - bb6: { StorageLive(_15); - _15 = (_2.1: bool); + _15 = copy (_2.1: bool); StorageLive(_16); _16 = move (_2.2: std::string::String); - goto -> bb20; @@ -70,7 +70,7 @@ - bb7: { + bb4: { StorageLive(_15); - _15 = (_2.1: bool); + _15 = copy (_2.1: bool); StorageLive(_16); _16 = move (_2.2: std::string::String); - goto -> bb20; @@ -87,7 +87,7 @@ - _4 = &fake shallow (_2.1: bool); StorageLive(_12); StorageLive(_13); - _13 = _1; + _13 = copy _1; - switchInt(move _13) -> [0: bb16, otherwise: bb15]; + switchInt(move _13) -> [0: bb13, otherwise: bb12]; } @@ -102,7 +102,7 @@ - _4 = &fake shallow (_2.1: bool); StorageLive(_9); StorageLive(_10); - _10 = _1; + _10 = copy _1; - switchInt(move _10) -> [0: bb12, otherwise: bb11]; + switchInt(move _10) -> [0: bb9, otherwise: bb8]; } @@ -125,7 +125,7 @@ - bb12: { + bb9: { - _9 = (*_6); + _9 = copy (*_6); - switchInt(move _9) -> [0: bb14, otherwise: bb13]; + switchInt(move _9) -> [0: bb11, otherwise: bb10]; } @@ -139,7 +139,7 @@ - FakeRead(ForGuardBinding, _6); - FakeRead(ForGuardBinding, _8); StorageLive(_5); - _5 = (_2.1: bool); + _5 = copy (_2.1: bool); StorageLive(_7); _7 = move (_2.2: std::string::String); - goto -> bb10; @@ -167,7 +167,7 @@ - bb16: { + bb13: { - _12 = (*_6); + _12 = copy (*_6); - switchInt(move _12) -> [0: bb18, otherwise: bb17]; + switchInt(move _12) -> [0: bb15, otherwise: bb14]; } @@ -181,7 +181,7 @@ - FakeRead(ForGuardBinding, _6); - FakeRead(ForGuardBinding, _8); StorageLive(_5); - _5 = (_2.0: bool); + _5 = copy (_2.0: bool); StorageLive(_7); _7 = move (_2.2: std::string::String); - goto -> bb10; diff --git a/tests/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff index 65da13eec50..597d93926f1 100644 --- a/tests/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff @@ -33,16 +33,16 @@ StorageLive(_4); StorageLive(_5); StorageLive(_6); -- switchInt(_1) -> [7: bb2, otherwise: bb1]; +- switchInt(copy _1) -> [7: bb2, otherwise: bb1]; - } - - bb1: { - _2 = const true; - _3 = const false; + StorageLive(_11); -+ _11 = _1; -+ _2 = Ne(_11, const 7_i32); -+ _3 = Eq(_11, const 7_i32); ++ _11 = copy _1; ++ _2 = Ne(copy _11, const 7_i32); ++ _3 = Eq(copy _11, const 7_i32); _4 = const false; _5 = const true; _6 = (); @@ -62,13 +62,13 @@ + StorageDead(_11); StorageDead(_6); StorageLive(_7); - _7 = _2; + _7 = copy _2; StorageLive(_8); - _8 = _3; + _8 = copy _3; StorageLive(_9); - _9 = _4; + _9 = copy _4; StorageLive(_10); - _10 = _5; + _10 = copy _5; _0 = (move _7, move _8, move _9, move _10); StorageDead(_10); StorageDead(_9); diff --git a/tests/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff index 052e2e12664..281f43b355d 100644 --- a/tests/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff @@ -14,7 +14,7 @@ - switchInt(move _3) -> [0: bb2, otherwise: bb1]; + StorageLive(_4); + _4 = move _3; -+ _2 = Eq(_4, const 0_isize); ++ _2 = Eq(copy _4, const 0_isize); + StorageDead(_4); + switchInt(move _2) -> [0: bb2, otherwise: bb1]; } diff --git a/tests/mir-opt/matches_reduce_branches.match_i128_u128.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_i128_u128.MatchBranchSimplification.diff index fc34ce7125e..cc7e863d135 100644 --- a/tests/mir-opt/matches_reduce_branches.match_i128_u128.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_i128_u128.MatchBranchSimplification.diff @@ -39,7 +39,7 @@ - bb6: { + StorageLive(_3); + _3 = move _2; -+ _0 = _3 as u128 (IntToInt); ++ _0 = copy _3 as u128 (IntToInt); + StorageDead(_3); return; } diff --git a/tests/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.diff index 5a71bef9341..e9143ef1636 100644 --- a/tests/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.diff @@ -46,7 +46,7 @@ - bb4: { + StorageLive(_7); + _7 = move _6; -+ _5 = Ne(_7, const false); ++ _5 = Ne(copy _7, const false); + StorageDead(_7); + StorageLive(_8); + _8 = move _5; @@ -66,7 +66,7 @@ - } - - bb7: { -+ _4 = Ne(_8, const false); ++ _4 = Ne(copy _8, const false); + StorageDead(_8); + StorageLive(_9); + _9 = move _4; @@ -86,7 +86,7 @@ - } - - bb10: { -+ _3 = Ne(_9, const false); ++ _3 = Ne(copy _9, const false); + StorageDead(_9); + StorageLive(_10); + _10 = move _3; @@ -104,10 +104,10 @@ - } - - bb12: { -+ _1 = Ne(_10, const false); ++ _1 = Ne(copy _10, const false); + StorageDead(_10); StorageDead(_2); - _0 = _1; + _0 = copy _1; StorageDead(_1); return; } diff --git a/tests/mir-opt/matches_reduce_branches.match_sext_i8_i16.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_sext_i8_i16.MatchBranchSimplification.diff index 7f8c2ab8d37..dbd26adc20f 100644 --- a/tests/mir-opt/matches_reduce_branches.match_sext_i8_i16.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_sext_i8_i16.MatchBranchSimplification.diff @@ -44,7 +44,7 @@ - bb7: { + StorageLive(_3); + _3 = move _2; -+ _0 = _3 as i16 (IntToInt); ++ _0 = copy _3 as i16 (IntToInt); + StorageDead(_3); return; } diff --git a/tests/mir-opt/matches_reduce_branches.match_sext_i8_u16.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_sext_i8_u16.MatchBranchSimplification.diff index 86d0d0ba6cf..f273d538835 100644 --- a/tests/mir-opt/matches_reduce_branches.match_sext_i8_u16.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_sext_i8_u16.MatchBranchSimplification.diff @@ -44,7 +44,7 @@ - bb7: { + StorageLive(_3); + _3 = move _2; -+ _0 = _3 as u16 (IntToInt); ++ _0 = copy _3 as u16 (IntToInt); + StorageDead(_3); return; } diff --git a/tests/mir-opt/matches_reduce_branches.match_trunc_i16_i8.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_trunc_i16_i8.MatchBranchSimplification.diff index d3d27be2070..6170cf13c00 100644 --- a/tests/mir-opt/matches_reduce_branches.match_trunc_i16_i8.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_trunc_i16_i8.MatchBranchSimplification.diff @@ -69,7 +69,7 @@ - bb12: { + StorageLive(_3); + _3 = move _2; -+ _0 = _3 as i8 (IntToInt); ++ _0 = copy _3 as i8 (IntToInt); + StorageDead(_3); return; } diff --git a/tests/mir-opt/matches_reduce_branches.match_trunc_i16_u8.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_trunc_i16_u8.MatchBranchSimplification.diff index 5fe899148eb..c18719ebb55 100644 --- a/tests/mir-opt/matches_reduce_branches.match_trunc_i16_u8.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_trunc_i16_u8.MatchBranchSimplification.diff @@ -69,7 +69,7 @@ - bb12: { + StorageLive(_3); + _3 = move _2; -+ _0 = _3 as u8 (IntToInt); ++ _0 = copy _3 as u8 (IntToInt); + StorageDead(_3); return; } diff --git a/tests/mir-opt/matches_reduce_branches.match_trunc_u16_i8.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_trunc_u16_i8.MatchBranchSimplification.diff index 85f97a13cac..401049026f2 100644 --- a/tests/mir-opt/matches_reduce_branches.match_trunc_u16_i8.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_trunc_u16_i8.MatchBranchSimplification.diff @@ -59,7 +59,7 @@ - bb10: { + StorageLive(_3); + _3 = move _2; -+ _0 = _3 as i8 (IntToInt); ++ _0 = copy _3 as i8 (IntToInt); + StorageDead(_3); return; } diff --git a/tests/mir-opt/matches_reduce_branches.match_trunc_u16_u8.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_trunc_u16_u8.MatchBranchSimplification.diff index 768d838eaa6..d4dafbd886f 100644 --- a/tests/mir-opt/matches_reduce_branches.match_trunc_u16_u8.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_trunc_u16_u8.MatchBranchSimplification.diff @@ -59,7 +59,7 @@ - bb10: { + StorageLive(_3); + _3 = move _2; -+ _0 = _3 as u8 (IntToInt); ++ _0 = copy _3 as u8 (IntToInt); + StorageDead(_3); return; } diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i8.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i8.MatchBranchSimplification.diff index d63eed7c019..5ab6f5eac84 100644 --- a/tests/mir-opt/matches_reduce_branches.match_u8_i8.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_u8_i8.MatchBranchSimplification.diff @@ -39,7 +39,7 @@ - bb6: { + StorageLive(_3); + _3 = move _2; -+ _0 = _3 as i8 (IntToInt); ++ _0 = copy _3 as i8 (IntToInt); + StorageDead(_3); return; } diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i8_2.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i8_2.MatchBranchSimplification.diff index 98dee1835a8..f14b3af9660 100644 --- a/tests/mir-opt/matches_reduce_branches.match_u8_i8_2.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_u8_i8_2.MatchBranchSimplification.diff @@ -35,8 +35,8 @@ - _3 = const -1_i8; + StorageLive(_8); + _8 = move _5; -+ _2 = _8 as i8 (IntToInt); -+ _3 = _8 as i8 (IntToInt); ++ _2 = copy _8 as i8 (IntToInt); ++ _3 = copy _8 as i8 (IntToInt); _4 = (); - goto -> bb6; - } @@ -66,9 +66,9 @@ + StorageDead(_8); StorageDead(_4); StorageLive(_6); - _6 = _2; + _6 = copy _2; StorageLive(_7); - _7 = _3; + _7 = copy _3; _0 = (move _6, move _7); StorageDead(_7); StorageDead(_6); diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i8_2_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i8_2_failed.MatchBranchSimplification.diff index 901dda58617..92e1a7dbc7d 100644 --- a/tests/mir-opt/matches_reduce_branches.match_u8_i8_2_failed.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_u8_i8_2_failed.MatchBranchSimplification.diff @@ -60,9 +60,9 @@ bb6: { StorageDead(_4); StorageLive(_6); - _6 = _2; + _6 = copy _2; StorageLive(_7); - _7 = _3; + _7 = copy _3; _0 = (move _6, move _7); StorageDead(_7); StorageDead(_6); diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i8_failed_len_1.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i8_failed_len_1.MatchBranchSimplification.diff index 9ebf2cf27cb..a1d58424ecd 100644 --- a/tests/mir-opt/matches_reduce_branches.match_u8_i8_failed_len_1.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_u8_i8_failed_len_1.MatchBranchSimplification.diff @@ -7,7 +7,7 @@ bb0: { _2 = discriminant(_1); - switchInt(_2) -> [0: bb1, 127: bb2, 128: bb3, 255: bb4, otherwise: bb5]; + switchInt(copy _2) -> [0: bb1, 127: bb2, 128: bb3, 255: bb4, otherwise: bb5]; } bb1: { diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i8_failed_len_2.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i8_failed_len_2.MatchBranchSimplification.diff index 554856777eb..6c4ade1b6ca 100644 --- a/tests/mir-opt/matches_reduce_branches.match_u8_i8_failed_len_2.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_u8_i8_failed_len_2.MatchBranchSimplification.diff @@ -7,7 +7,7 @@ bb0: { _2 = discriminant(_1); - switchInt(_2) -> [0: bb1, 127: bb2, 128: bb3, 255: bb4, otherwise: bb5]; + switchInt(copy _2) -> [0: bb1, 127: bb2, 128: bb3, 255: bb4, otherwise: bb5]; } bb1: { diff --git a/tests/mir-opt/matches_reduce_branches.match_zext_u8_i16.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_zext_u8_i16.MatchBranchSimplification.diff index e00a604fe25..fdf83d91bbd 100644 --- a/tests/mir-opt/matches_reduce_branches.match_zext_u8_i16.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_zext_u8_i16.MatchBranchSimplification.diff @@ -39,7 +39,7 @@ - bb6: { + StorageLive(_3); + _3 = move _2; -+ _0 = _3 as i16 (IntToInt); ++ _0 = copy _3 as i16 (IntToInt); + StorageDead(_3); return; } diff --git a/tests/mir-opt/matches_reduce_branches.match_zext_u8_u16.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_zext_u8_u16.MatchBranchSimplification.diff index befb9118907..a888d247275 100644 --- a/tests/mir-opt/matches_reduce_branches.match_zext_u8_u16.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_zext_u8_u16.MatchBranchSimplification.diff @@ -39,7 +39,7 @@ - bb6: { + StorageLive(_3); + _3 = move _2; -+ _0 = _3 as u16 (IntToInt); ++ _0 = copy _3 as u16 (IntToInt); + StorageDead(_3); return; } diff --git a/tests/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff b/tests/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff index 11a18f58e3a..99985b28382 100644 --- a/tests/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff @@ -29,7 +29,7 @@ - bb4: { + StorageLive(_3); + _3 = move _2; -+ _0 = _3 as u8 (IntToInt); ++ _0 = copy _3 as u8 (IntToInt); + StorageDead(_3); return; } diff --git a/tests/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff b/tests/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff index 809badc41ba..0fc5032691f 100644 --- a/tests/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff @@ -29,7 +29,7 @@ - bb4: { + StorageLive(_3); + _3 = move _2; -+ _0 = _3 as i8 (IntToInt); ++ _0 = copy _3 as i8 (IntToInt); + StorageDead(_3); return; } diff --git a/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir b/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir index ad456600b0a..d09a422d408 100644 --- a/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir +++ b/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir @@ -50,15 +50,15 @@ fn main() -> () { StorageLive(_3); _3 = const ConstValue(Scalar(0x00000000): usize); _4 = Len(_1); - _5 = Lt(_3, _4); - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind: bb7]; + _5 = Lt(copy _3, copy _4); + assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind: bb7]; } bb1: { _2 = &'?2 _1[_3]; FakeRead(ForLet(None), _2); StorageLive(_6); - _6 = _2; + _6 = copy _2; FakeRead(ForLet(None), _6); StorageLive(_7); _7 = const ConstValue(Scalar(0x01): bool); @@ -68,7 +68,7 @@ fn main() -> () { bb2: { StorageLive(_8); StorageLive(_9); - _9 = (*_6); + _9 = copy (*_6); _8 = ConstValue(ZeroSized: fn(usize) -> bool {use_x})(move _9) -> [return: bb3, unwind: bb7]; } diff --git a/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir b/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir index a15d47cd66f..4abb5b0b93b 100644 --- a/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir +++ b/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir @@ -50,15 +50,15 @@ fn main() -> () { StorageLive(_3); _3 = const ConstValue(Scalar(0x0000000000000000): usize); _4 = Len(_1); - _5 = Lt(_3, _4); - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind: bb7]; + _5 = Lt(copy _3, copy _4); + assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind: bb7]; } bb1: { _2 = &'?2 _1[_3]; FakeRead(ForLet(None), _2); StorageLive(_6); - _6 = _2; + _6 = copy _2; FakeRead(ForLet(None), _6); StorageLive(_7); _7 = const ConstValue(Scalar(0x01): bool); @@ -68,7 +68,7 @@ fn main() -> () { bb2: { StorageLive(_8); StorageLive(_9); - _9 = (*_6); + _9 = copy (*_6); _8 = ConstValue(ZeroSized: fn(usize) -> bool {use_x})(move _9) -> [return: bb3, unwind: bb7]; } diff --git a/tests/mir-opt/nrvo_miscompile_111005.wrong.RenameReturnPlace.diff b/tests/mir-opt/nrvo_miscompile_111005.wrong.RenameReturnPlace.diff index 260b472daa9..d248c76f261 100644 --- a/tests/mir-opt/nrvo_miscompile_111005.wrong.RenameReturnPlace.diff +++ b/tests/mir-opt/nrvo_miscompile_111005.wrong.RenameReturnPlace.diff @@ -6,10 +6,10 @@ let mut _2: char; bb0: { -- _2 = _1; -- _0 = _2; +- _2 = copy _1; +- _0 = copy _2; - _2 = const 'b'; -+ _0 = _1; ++ _0 = copy _1; + _0 = const 'b'; return; } diff --git a/tests/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.panic-abort.diff b/tests/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.panic-abort.diff index f7bc5559ab7..6dce3ec5303 100644 --- a/tests/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.panic-abort.diff +++ b/tests/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.panic-abort.diff @@ -20,7 +20,7 @@ + _0 = [const 0_u8; 1024]; StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; StorageLive(_5); StorageLive(_6); - _6 = &mut _2; @@ -34,7 +34,7 @@ StorageDead(_4); StorageDead(_6); StorageDead(_3); -- _0 = _2; +- _0 = copy _2; - StorageDead(_2); return; } diff --git a/tests/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.panic-unwind.diff b/tests/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.panic-unwind.diff index 3df8e567f1f..54cbe2871f1 100644 --- a/tests/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.panic-unwind.diff +++ b/tests/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.panic-unwind.diff @@ -20,7 +20,7 @@ + _0 = [const 0_u8; 1024]; StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = copy _1; StorageLive(_5); StorageLive(_6); - _6 = &mut _2; @@ -34,7 +34,7 @@ StorageDead(_4); StorageDead(_6); StorageDead(_3); -- _0 = _2; +- _0 = copy _2; - StorageDead(_2); return; } diff --git a/tests/mir-opt/or_pattern.shortcut_second_or.SimplifyCfg-initial.after.mir b/tests/mir-opt/or_pattern.shortcut_second_or.SimplifyCfg-initial.after.mir index 6c76a72b775..c5d7a6a1d99 100644 --- a/tests/mir-opt/or_pattern.shortcut_second_or.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/or_pattern.shortcut_second_or.SimplifyCfg-initial.after.mir @@ -18,15 +18,15 @@ fn shortcut_second_or() -> () { _1 = (move _2, const 0_i32); StorageDead(_2); PlaceMention(_1); - switchInt(((_1.0: (i32, i32)).0: i32)) -> [0: bb2, otherwise: bb1]; + switchInt(copy ((_1.0: (i32, i32)).0: i32)) -> [0: bb2, otherwise: bb1]; } bb1: { - switchInt(((_1.0: (i32, i32)).1: i32)) -> [1: bb4, otherwise: bb3]; + switchInt(copy ((_1.0: (i32, i32)).1: i32)) -> [1: bb4, otherwise: bb3]; } bb2: { - switchInt((_1.1: i32)) -> [2: bb5, 3: bb6, otherwise: bb3]; + switchInt(copy (_1.1: i32)) -> [2: bb5, 3: bb6, otherwise: bb3]; } bb3: { @@ -35,7 +35,7 @@ fn shortcut_second_or() -> () { } bb4: { - switchInt((_1.1: i32)) -> [2: bb7, 3: bb8, otherwise: bb3]; + switchInt(copy (_1.1: i32)) -> [2: bb7, 3: bb8, otherwise: bb3]; } bb5: { @@ -56,33 +56,33 @@ fn shortcut_second_or() -> () { bb9: { StorageLive(_3); - _3 = (_1.0: (i32, i32)); + _3 = copy (_1.0: (i32, i32)); StorageLive(_4); - _4 = (_1.1: i32); + _4 = copy (_1.1: i32); goto -> bb13; } bb10: { StorageLive(_3); - _3 = (_1.0: (i32, i32)); + _3 = copy (_1.0: (i32, i32)); StorageLive(_4); - _4 = (_1.1: i32); + _4 = copy (_1.1: i32); goto -> bb13; } bb11: { StorageLive(_3); - _3 = (_1.0: (i32, i32)); + _3 = copy (_1.0: (i32, i32)); StorageLive(_4); - _4 = (_1.1: i32); + _4 = copy (_1.1: i32); goto -> bb13; } bb12: { StorageLive(_3); - _3 = (_1.0: (i32, i32)); + _3 = copy (_1.0: (i32, i32)); StorageLive(_4); - _4 = (_1.1: i32); + _4 = copy (_1.1: i32); goto -> bb13; } diff --git a/tests/mir-opt/or_pattern.single_switchint.SimplifyCfg-initial.after.mir b/tests/mir-opt/or_pattern.single_switchint.SimplifyCfg-initial.after.mir index 8b0ef7b29d7..889ff6f9f5e 100644 --- a/tests/mir-opt/or_pattern.single_switchint.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/or_pattern.single_switchint.SimplifyCfg-initial.after.mir @@ -10,15 +10,15 @@ fn single_switchint() -> () { StorageLive(_2); _2 = (const 1_i32, const true); PlaceMention(_2); - switchInt((_2.0: i32)) -> [1: bb2, 2: bb4, otherwise: bb1]; + switchInt(copy (_2.0: i32)) -> [1: bb2, 2: bb4, otherwise: bb1]; } bb1: { - switchInt((_2.0: i32)) -> [3: bb8, 4: bb8, otherwise: bb7]; + switchInt(copy (_2.0: i32)) -> [3: bb8, 4: bb8, otherwise: bb7]; } bb2: { - switchInt((_2.1: bool)) -> [0: bb6, otherwise: bb3]; + switchInt(copy (_2.1: bool)) -> [0: bb6, otherwise: bb3]; } bb3: { @@ -26,7 +26,7 @@ fn single_switchint() -> () { } bb4: { - switchInt((_2.1: bool)) -> [0: bb5, otherwise: bb6]; + switchInt(copy (_2.1: bool)) -> [0: bb5, otherwise: bb6]; } bb5: { diff --git a/tests/mir-opt/pre-codegen/chained_comparison.bitand.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/chained_comparison.bitand.PreCodegen.after.mir index 99ca659c637..9b77bdb7cf6 100644 --- a/tests/mir-opt/pre-codegen/chained_comparison.bitand.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/chained_comparison.bitand.PreCodegen.after.mir @@ -29,17 +29,17 @@ fn bitand(_1: &Blueprint, _2: &Blueprint) -> bool { StorageLive(_9); StorageLive(_5); StorageLive(_3); - _3 = ((*_1).0: u32); + _3 = copy ((*_1).0: u32); StorageLive(_4); - _4 = ((*_2).0: u32); + _4 = copy ((*_2).0: u32); _5 = Eq(move _3, move _4); StorageDead(_4); StorageDead(_3); StorageLive(_8); StorageLive(_6); - _6 = ((*_1).1: u32); + _6 = copy ((*_1).1: u32); StorageLive(_7); - _7 = ((*_2).1: u32); + _7 = copy ((*_2).1: u32); _8 = Eq(move _6, move _7); StorageDead(_7); StorageDead(_6); @@ -48,9 +48,9 @@ fn bitand(_1: &Blueprint, _2: &Blueprint) -> bool { StorageDead(_5); StorageLive(_12); StorageLive(_10); - _10 = ((*_1).2: u32); + _10 = copy ((*_1).2: u32); StorageLive(_11); - _11 = ((*_2).2: u32); + _11 = copy ((*_2).2: u32); _12 = Eq(move _10, move _11); StorageDead(_11); StorageDead(_10); @@ -59,9 +59,9 @@ fn bitand(_1: &Blueprint, _2: &Blueprint) -> bool { StorageDead(_9); StorageLive(_16); StorageLive(_14); - _14 = ((*_1).3: u32); + _14 = copy ((*_1).3: u32); StorageLive(_15); - _15 = ((*_2).3: u32); + _15 = copy ((*_2).3: u32); _16 = Eq(move _14, move _15); StorageDead(_15); StorageDead(_14); @@ -70,9 +70,9 @@ fn bitand(_1: &Blueprint, _2: &Blueprint) -> bool { StorageDead(_13); StorageLive(_20); StorageLive(_18); - _18 = ((*_1).4: u32); + _18 = copy ((*_1).4: u32); StorageLive(_19); - _19 = ((*_2).4: u32); + _19 = copy ((*_2).4: u32); _20 = Eq(move _18, move _19); StorageDead(_19); StorageDead(_18); diff --git a/tests/mir-opt/pre-codegen/chained_comparison.naive.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/chained_comparison.naive.PreCodegen.after.mir index 838e30fa35e..9b3e28ab5b8 100644 --- a/tests/mir-opt/pre-codegen/chained_comparison.naive.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/chained_comparison.naive.PreCodegen.after.mir @@ -22,9 +22,9 @@ fn naive(_1: &Blueprint, _2: &Blueprint) -> bool { bb0: { StorageLive(_5); StorageLive(_3); - _3 = ((*_1).0: u32); + _3 = copy ((*_1).0: u32); StorageLive(_4); - _4 = ((*_2).0: u32); + _4 = copy ((*_2).0: u32); _5 = Eq(move _3, move _4); switchInt(move _5) -> [0: bb1, otherwise: bb2]; } @@ -40,9 +40,9 @@ fn naive(_1: &Blueprint, _2: &Blueprint) -> bool { StorageDead(_3); StorageLive(_8); StorageLive(_6); - _6 = ((*_1).1: u32); + _6 = copy ((*_1).1: u32); StorageLive(_7); - _7 = ((*_2).1: u32); + _7 = copy ((*_2).1: u32); _8 = Eq(move _6, move _7); switchInt(move _8) -> [0: bb3, otherwise: bb4]; } @@ -58,9 +58,9 @@ fn naive(_1: &Blueprint, _2: &Blueprint) -> bool { StorageDead(_6); StorageLive(_11); StorageLive(_9); - _9 = ((*_1).2: u32); + _9 = copy ((*_1).2: u32); StorageLive(_10); - _10 = ((*_2).2: u32); + _10 = copy ((*_2).2: u32); _11 = Eq(move _9, move _10); switchInt(move _11) -> [0: bb5, otherwise: bb6]; } @@ -76,9 +76,9 @@ fn naive(_1: &Blueprint, _2: &Blueprint) -> bool { StorageDead(_9); StorageLive(_14); StorageLive(_12); - _12 = ((*_1).3: u32); + _12 = copy ((*_1).3: u32); StorageLive(_13); - _13 = ((*_2).3: u32); + _13 = copy ((*_2).3: u32); _14 = Eq(move _12, move _13); switchInt(move _14) -> [0: bb7, otherwise: bb9]; } @@ -98,9 +98,9 @@ fn naive(_1: &Blueprint, _2: &Blueprint) -> bool { StorageDead(_13); StorageDead(_12); StorageLive(_15); - _15 = ((*_1).4: u32); + _15 = copy ((*_1).4: u32); StorageLive(_16); - _16 = ((*_2).4: u32); + _16 = copy ((*_2).4: u32); _0 = Eq(move _15, move _16); StorageDead(_16); StorageDead(_15); diff --git a/tests/mir-opt/pre-codegen/chained_comparison.returning.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/chained_comparison.returning.PreCodegen.after.mir index 8452fa12f31..72d52701d11 100644 --- a/tests/mir-opt/pre-codegen/chained_comparison.returning.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/chained_comparison.returning.PreCodegen.after.mir @@ -23,9 +23,9 @@ fn returning(_1: &Blueprint, _2: &Blueprint) -> bool { bb0: { StorageLive(_5); StorageLive(_3); - _3 = ((*_1).0: u32); + _3 = copy ((*_1).0: u32); StorageLive(_4); - _4 = ((*_2).0: u32); + _4 = copy ((*_2).0: u32); _5 = Ne(move _3, move _4); switchInt(move _5) -> [0: bb1, otherwise: bb10]; } @@ -36,9 +36,9 @@ fn returning(_1: &Blueprint, _2: &Blueprint) -> bool { StorageDead(_5); StorageLive(_8); StorageLive(_6); - _6 = ((*_1).1: u32); + _6 = copy ((*_1).1: u32); StorageLive(_7); - _7 = ((*_2).1: u32); + _7 = copy ((*_2).1: u32); _8 = Ne(move _6, move _7); switchInt(move _8) -> [0: bb2, otherwise: bb9]; } @@ -49,9 +49,9 @@ fn returning(_1: &Blueprint, _2: &Blueprint) -> bool { StorageDead(_8); StorageLive(_11); StorageLive(_9); - _9 = ((*_1).2: u32); + _9 = copy ((*_1).2: u32); StorageLive(_10); - _10 = ((*_2).2: u32); + _10 = copy ((*_2).2: u32); _11 = Ne(move _9, move _10); switchInt(move _11) -> [0: bb3, otherwise: bb8]; } @@ -62,9 +62,9 @@ fn returning(_1: &Blueprint, _2: &Blueprint) -> bool { StorageDead(_11); StorageLive(_14); StorageLive(_12); - _12 = ((*_1).3: u32); + _12 = copy ((*_1).3: u32); StorageLive(_13); - _13 = ((*_2).3: u32); + _13 = copy ((*_2).3: u32); _14 = Ne(move _12, move _13); switchInt(move _14) -> [0: bb4, otherwise: bb7]; } @@ -75,9 +75,9 @@ fn returning(_1: &Blueprint, _2: &Blueprint) -> bool { StorageDead(_14); StorageLive(_17); StorageLive(_15); - _15 = ((*_1).4: u32); + _15 = copy ((*_1).4: u32); StorageLive(_16); - _16 = ((*_2).4: u32); + _16 = copy ((*_2).4: u32); _17 = Ne(move _15, move _16); switchInt(move _17) -> [0: bb5, otherwise: bb6]; } diff --git a/tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.panic-abort.mir index 4edf0d2c47c..a9dd8886577 100644 --- a/tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.panic-abort.mir @@ -17,7 +17,7 @@ fn checked_shl(_1: u32, _2: u32) -> Option { bb0: { StorageLive(_3); - _3 = Lt(_2, const core::num::::BITS); + _3 = Lt(copy _2, const core::num::::BITS); switchInt(move _3) -> [0: bb1, otherwise: bb2]; } @@ -28,7 +28,7 @@ fn checked_shl(_1: u32, _2: u32) -> Option { bb2: { StorageLive(_4); - _4 = ShlUnchecked(_1, _2); + _4 = ShlUnchecked(copy _1, copy _2); _0 = Option::::Some(move _4); StorageDead(_4); goto -> bb3; diff --git a/tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.panic-unwind.mir index 4edf0d2c47c..a9dd8886577 100644 --- a/tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.panic-unwind.mir @@ -17,7 +17,7 @@ fn checked_shl(_1: u32, _2: u32) -> Option { bb0: { StorageLive(_3); - _3 = Lt(_2, const core::num::::BITS); + _3 = Lt(copy _2, const core::num::::BITS); switchInt(move _3) -> [0: bb1, otherwise: bb2]; } @@ -28,7 +28,7 @@ fn checked_shl(_1: u32, _2: u32) -> Option { bb2: { StorageLive(_4); - _4 = ShlUnchecked(_1, _2); + _4 = ShlUnchecked(copy _1, copy _2); _0 = Option::::Some(move _4); StorageDead(_4); goto -> bb3; diff --git a/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.panic-abort.mir index 69c11ebcacc..935e67fc3c0 100644 --- a/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.panic-abort.mir @@ -32,18 +32,18 @@ fn step_forward(_1: u16, _2: usize) -> u16 { bb0: { StorageLive(_4); StorageLive(_3); - _3 = Gt(_2, const 65535_usize); + _3 = Gt(copy _2, const 65535_usize); switchInt(move _3) -> [0: bb1, otherwise: bb5]; } bb1: { - _4 = _2 as u16 (IntToInt); + _4 = copy _2 as u16 (IntToInt); StorageDead(_3); StorageLive(_7); StorageLive(_6); StorageLive(_5); - _5 = AddWithOverflow(_1, _4); - _6 = (_5.1: bool); + _5 = AddWithOverflow(copy _1, copy _4); + _6 = copy (_5.1: bool); _7 = unlikely(move _6) -> [return: bb2, unwind unreachable]; } @@ -76,8 +76,8 @@ fn step_forward(_1: u16, _2: usize) -> u16 { bb7: { StorageLive(_8); - _8 = _2 as u16 (IntToInt); - _0 = Add(_1, _8); + _8 = copy _2 as u16 (IntToInt); + _0 = Add(copy _1, copy _8); StorageDead(_8); StorageDead(_4); return; diff --git a/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.panic-unwind.mir index e6ea6c51001..bf1ffd1ef32 100644 --- a/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.panic-unwind.mir @@ -32,18 +32,18 @@ fn step_forward(_1: u16, _2: usize) -> u16 { bb0: { StorageLive(_4); StorageLive(_3); - _3 = Gt(_2, const 65535_usize); + _3 = Gt(copy _2, const 65535_usize); switchInt(move _3) -> [0: bb1, otherwise: bb5]; } bb1: { - _4 = _2 as u16 (IntToInt); + _4 = copy _2 as u16 (IntToInt); StorageDead(_3); StorageLive(_7); StorageLive(_6); StorageLive(_5); - _5 = AddWithOverflow(_1, _4); - _6 = (_5.1: bool); + _5 = AddWithOverflow(copy _1, copy _4); + _6 = copy (_5.1: bool); _7 = unlikely(move _6) -> [return: bb2, unwind unreachable]; } @@ -76,8 +76,8 @@ fn step_forward(_1: u16, _2: usize) -> u16 { bb7: { StorageLive(_8); - _8 = _2 as u16 (IntToInt); - _0 = Add(_1, _8); + _8 = copy _2 as u16 (IntToInt); + _0 = Add(copy _1, copy _8); StorageDead(_8); StorageDead(_4); return; diff --git a/tests/mir-opt/pre-codegen/derived_ord.{impl#0}-partial_cmp.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/derived_ord.{impl#0}-partial_cmp.PreCodegen.after.mir index 47f10451b05..5f4ec1de270 100644 --- a/tests/mir-opt/pre-codegen/derived_ord.{impl#0}-partial_cmp.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/derived_ord.{impl#0}-partial_cmp.PreCodegen.after.mir @@ -22,13 +22,13 @@ fn ::partial_cmp(_1: &MultiField, _2: &M bb0: { StorageLive(_3); - _3 = ((*_1).0: char); + _3 = copy ((*_1).0: char); StorageLive(_4); - _4 = ((*_2).0: char); + _4 = copy ((*_2).0: char); _5 = Cmp(move _3, move _4); StorageDead(_4); StorageDead(_3); - _6 = Option::::Some(_5); + _6 = Option::::Some(copy _5); _7 = discriminant(_5); switchInt(move _7) -> [0: bb1, otherwise: bb2]; } @@ -36,9 +36,9 @@ fn ::partial_cmp(_1: &MultiField, _2: &M bb1: { StorageLive(_10); StorageLive(_8); - _8 = ((*_1).1: i16); + _8 = copy ((*_1).1: i16); StorageLive(_9); - _9 = ((*_2).1: i16); + _9 = copy ((*_2).1: i16); _10 = Cmp(move _8, move _9); StorageDead(_9); StorageDead(_8); @@ -48,7 +48,7 @@ fn ::partial_cmp(_1: &MultiField, _2: &M } bb2: { - _0 = _6; + _0 = copy _6; goto -> bb3; } diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff index 30c122ddea0..6cac8b109ee 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff @@ -73,12 +73,12 @@ StorageLive(_6); StorageLive(_7); _9 = const main::promoted[0]; - _7 = _9; + _7 = copy _9; StorageLive(_8); -- _8 = _1; +- _8 = copy _1; - _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb4, unwind unreachable]; + _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}; -+ _6 = std::alloc::Global::alloc_impl(_9, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb4, unwind unreachable]; ++ _6 = std::alloc::Global::alloc_impl(copy _9, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb4, unwind unreachable]; } bb4: { @@ -93,7 +93,7 @@ bb5: { StorageLive(_15); _16 = &_13; - _15 = _16 as &dyn std::fmt::Debug (PointerCoercion(Unsize)); + _15 = copy _16 as &dyn std::fmt::Debug (PointerCoercion(Unsize)); _14 = result::unwrap_failed(const "called `Result::unwrap()` on an `Err` value", move _15) -> unwind unreachable; } @@ -104,14 +104,14 @@ StorageDead(_6); - StorageLive(_17); + nop; - _17 = (_5.0: *const [u8]); + _17 = copy (_5.0: *const [u8]); - _4 = move _17 as *mut [u8] (PtrToPtr); - StorageDead(_17); -+ _4 = _17 as *mut [u8] (PtrToPtr); ++ _4 = copy _17 as *mut [u8] (PtrToPtr); + nop; StorageDead(_5); - _3 = move _4 as *mut u8 (PtrToPtr); -+ _3 = _17 as *mut u8 (PtrToPtr); ++ _3 = copy _17 as *mut u8 (PtrToPtr); StorageDead(_4); StorageDead(_3); - StorageDead(_1); diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff index 93449462c3d..5fcece2280d 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff @@ -47,14 +47,14 @@ StorageDead(_6); - StorageLive(_12); + nop; - _12 = (_5.0: *const [u8]); + _12 = copy (_5.0: *const [u8]); - _4 = move _12 as *mut [u8] (PtrToPtr); - StorageDead(_12); -+ _4 = _12 as *mut [u8] (PtrToPtr); ++ _4 = copy _12 as *mut [u8] (PtrToPtr); + nop; StorageDead(_5); - _3 = move _4 as *mut u8 (PtrToPtr); -+ _3 = _12 as *mut u8 (PtrToPtr); ++ _3 = copy _12 as *mut u8 (PtrToPtr); StorageDead(_4); StorageDead(_3); - StorageDead(_1); @@ -81,12 +81,12 @@ StorageLive(_6); StorageLive(_7); _9 = const main::promoted[0]; - _7 = _9; + _7 = copy _9; StorageLive(_8); -- _8 = _1; +- _8 = copy _1; - _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb5, unwind continue]; + _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}; -+ _6 = std::alloc::Global::alloc_impl(_9, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb5, unwind continue]; ++ _6 = std::alloc::Global::alloc_impl(copy _9, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb5, unwind continue]; } bb5: { diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff index 44435956ec4..10fde25e317 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff @@ -73,12 +73,12 @@ StorageLive(_6); StorageLive(_7); _9 = const main::promoted[0]; - _7 = _9; + _7 = copy _9; StorageLive(_8); -- _8 = _1; +- _8 = copy _1; - _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb4, unwind unreachable]; + _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}; -+ _6 = std::alloc::Global::alloc_impl(_9, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb4, unwind unreachable]; ++ _6 = std::alloc::Global::alloc_impl(copy _9, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb4, unwind unreachable]; } bb4: { @@ -93,7 +93,7 @@ bb5: { StorageLive(_15); _16 = &_13; - _15 = _16 as &dyn std::fmt::Debug (PointerCoercion(Unsize)); + _15 = copy _16 as &dyn std::fmt::Debug (PointerCoercion(Unsize)); _14 = result::unwrap_failed(const "called `Result::unwrap()` on an `Err` value", move _15) -> unwind unreachable; } @@ -104,14 +104,14 @@ StorageDead(_6); - StorageLive(_17); + nop; - _17 = (_5.0: *const [u8]); + _17 = copy (_5.0: *const [u8]); - _4 = move _17 as *mut [u8] (PtrToPtr); - StorageDead(_17); -+ _4 = _17 as *mut [u8] (PtrToPtr); ++ _4 = copy _17 as *mut [u8] (PtrToPtr); + nop; StorageDead(_5); - _3 = move _4 as *mut u8 (PtrToPtr); -+ _3 = _17 as *mut u8 (PtrToPtr); ++ _3 = copy _17 as *mut u8 (PtrToPtr); StorageDead(_4); StorageDead(_3); - StorageDead(_1); diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff index c958480a9c7..0821ea272bf 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff @@ -47,14 +47,14 @@ StorageDead(_6); - StorageLive(_12); + nop; - _12 = (_5.0: *const [u8]); + _12 = copy (_5.0: *const [u8]); - _4 = move _12 as *mut [u8] (PtrToPtr); - StorageDead(_12); -+ _4 = _12 as *mut [u8] (PtrToPtr); ++ _4 = copy _12 as *mut [u8] (PtrToPtr); + nop; StorageDead(_5); - _3 = move _4 as *mut u8 (PtrToPtr); -+ _3 = _12 as *mut u8 (PtrToPtr); ++ _3 = copy _12 as *mut u8 (PtrToPtr); StorageDead(_4); StorageDead(_3); - StorageDead(_1); @@ -81,12 +81,12 @@ StorageLive(_6); StorageLive(_7); _9 = const main::promoted[0]; - _7 = _9; + _7 = copy _9; StorageLive(_8); -- _8 = _1; +- _8 = copy _1; - _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb5, unwind continue]; + _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}; -+ _6 = std::alloc::Global::alloc_impl(_9, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb5, unwind continue]; ++ _6 = std::alloc::Global::alloc_impl(copy _9, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb5, unwind continue]; } bb5: { diff --git a/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir index 8d182069adc..75e8cb1d861 100644 --- a/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir @@ -32,7 +32,7 @@ fn filter_mapped(_1: impl Iterator, _2: impl Fn(T) -> Option) -> () bb1: { StorageLive(_4); - _4 = _3; + _4 = copy _3; goto -> bb2; } diff --git a/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir index cdb7eea74fb..be69bbf10e7 100644 --- a/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir @@ -41,9 +41,9 @@ fn int_range(_1: usize, _2: usize) -> () { } bb0: { - _3 = std::ops::Range:: { start: _1, end: _2 }; + _3 = std::ops::Range:: { start: copy _1, end: copy _2 }; StorageLive(_4); - _4 = _3; + _4 = copy _3; goto -> bb1; } @@ -57,9 +57,9 @@ fn int_range(_1: usize, _2: usize) -> () { StorageLive(_7); _7 = &(_4.1: usize); StorageLive(_8); - _8 = (_4.0: usize); + _8 = copy (_4.0: usize); StorageLive(_9); - _9 = (_4.1: usize); + _9 = copy (_4.1: usize); _10 = Lt(move _8, move _9); StorageDead(_9); StorageDead(_8); @@ -79,18 +79,18 @@ fn int_range(_1: usize, _2: usize) -> () { bb3: { StorageDead(_7); StorageDead(_6); - _11 = (_4.0: usize); + _11 = copy (_4.0: usize); StorageLive(_12); - _12 = ::forward_unchecked(_11, const 1_usize) -> [return: bb4, unwind continue]; + _12 = ::forward_unchecked(copy _11, const 1_usize) -> [return: bb4, unwind continue]; } bb4: { (_4.0: usize) = move _12; StorageDead(_12); - _13 = Option::::Some(_11); + _13 = Option::::Some(copy _11); StorageDead(_10); StorageDead(_11); - _14 = ((_13 as Some).0: usize); + _14 = copy ((_13 as Some).0: usize); _15 = opaque::(move _14) -> [return: bb5, unwind continue]; } diff --git a/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir index 51d41e9ff05..4977f39ccef 100644 --- a/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir @@ -43,7 +43,7 @@ fn mapped(_1: impl Iterator, _2: impl Fn(T) -> U) -> () { bb1: { StorageLive(_4); - _4 = _3; + _4 = copy _3; goto -> bb2; } @@ -84,7 +84,7 @@ fn mapped(_1: impl Iterator, _2: impl Fn(T) -> U) -> () { _10 = move ((_7 as Some).0: T); StorageLive(_12); StorageLive(_11); - _11 = (_10,); + _11 = (copy _10,); _12 = <&mut impl Fn(T) -> U as FnOnce<(T,)>>::call_once(move _8, move _11) -> [return: bb7, unwind: bb10]; } diff --git a/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-abort.mir index 3ca24e152a4..c10f3c42962 100644 --- a/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-abort.mir @@ -9,8 +9,8 @@ fn manual_replace(_1: &mut u32, _2: u32) -> u32 { } bb0: { - _0 = (*_1); - (*_1) = _2; + _0 = copy (*_1); + (*_1) = copy _2; return; } } diff --git a/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-unwind.mir index 3ca24e152a4..c10f3c42962 100644 --- a/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-unwind.mir @@ -9,8 +9,8 @@ fn manual_replace(_1: &mut u32, _2: u32) -> u32 { } bb0: { - _0 = (*_1); - (*_1) = _2; + _0 = copy (*_1); + (*_1) = copy _2; return; } } diff --git a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-abort.mir index a3dc54f73c8..ed494f6e74c 100644 --- a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-abort.mir @@ -14,8 +14,8 @@ fn mem_replace(_1: &mut u32, _2: u32) -> u32 { } bb0: { - _0 = (*_1); - (*_1) = _2; + _0 = copy (*_1); + (*_1) = copy _2; return; } } diff --git a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-unwind.mir index a3dc54f73c8..ed494f6e74c 100644 --- a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-unwind.mir @@ -14,8 +14,8 @@ fn mem_replace(_1: &mut u32, _2: u32) -> u32 { } bb0: { - _0 = (*_1); - (*_1) = _2; + _0 = copy (*_1); + (*_1) = copy _2; return; } } diff --git a/tests/mir-opt/pre-codegen/no_inlined_clone.{impl#0}-clone.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/no_inlined_clone.{impl#0}-clone.PreCodegen.after.mir index 71898daa1bf..62a9cd9131f 100644 --- a/tests/mir-opt/pre-codegen/no_inlined_clone.{impl#0}-clone.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/no_inlined_clone.{impl#0}-clone.PreCodegen.after.mir @@ -7,7 +7,7 @@ fn ::clone(_1: &Foo) -> Foo { bb0: { StorageLive(_2); - _2 = ((*_1).0: i32); + _2 = copy ((*_1).0: i32); _0 = Foo { a: move _2 }; StorageDead(_2); return; diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-abort.diff index 45b8d89c0f4..6575610727b 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-abort.diff @@ -39,21 +39,21 @@ StorageLive(_5); _5 = const 3_usize; _6 = const 6_usize; -- _7 = Lt(_5, _6); -- assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> [success: bb2, unwind unreachable]; +- _7 = Lt(copy _5, copy _6); +- assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, copy _5) -> [success: bb2, unwind unreachable]; + _7 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 6_usize, const 3_usize) -> [success: bb2, unwind unreachable]; } bb2: { -- _3 = _4[_5]; +- _3 = copy _4[_5]; + _3 = const 3_i32; StorageDead(_5); StorageDead(_4); StorageLive(_8); StorageLive(_9); _9 = const 42_u32; -- _8 = _9; +- _8 = copy _9; + _8 = const 42_u32; StorageDead(_9); StorageDead(_8); diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-unwind.diff index e6ee1e6f9a3..1a4ed5767fe 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-unwind.diff @@ -39,21 +39,21 @@ StorageLive(_5); _5 = const 3_usize; _6 = const 6_usize; -- _7 = Lt(_5, _6); -- assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> [success: bb2, unwind continue]; +- _7 = Lt(copy _5, copy _6); +- assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, copy _5) -> [success: bb2, unwind continue]; + _7 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 6_usize, const 3_usize) -> [success: bb2, unwind continue]; } bb2: { -- _3 = _4[_5]; +- _3 = copy _4[_5]; + _3 = const 3_i32; StorageDead(_5); StorageDead(_4); StorageLive(_8); StorageLive(_9); _9 = const 42_u32; -- _8 = _9; +- _8 = copy _9; + _8 = const 42_u32; StorageDead(_9); StorageDead(_8); diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-abort.diff index 45b8d89c0f4..6575610727b 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-abort.diff @@ -39,21 +39,21 @@ StorageLive(_5); _5 = const 3_usize; _6 = const 6_usize; -- _7 = Lt(_5, _6); -- assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> [success: bb2, unwind unreachable]; +- _7 = Lt(copy _5, copy _6); +- assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, copy _5) -> [success: bb2, unwind unreachable]; + _7 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 6_usize, const 3_usize) -> [success: bb2, unwind unreachable]; } bb2: { -- _3 = _4[_5]; +- _3 = copy _4[_5]; + _3 = const 3_i32; StorageDead(_5); StorageDead(_4); StorageLive(_8); StorageLive(_9); _9 = const 42_u32; -- _8 = _9; +- _8 = copy _9; + _8 = const 42_u32; StorageDead(_9); StorageDead(_8); diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-unwind.diff index e6ee1e6f9a3..1a4ed5767fe 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-unwind.diff @@ -39,21 +39,21 @@ StorageLive(_5); _5 = const 3_usize; _6 = const 6_usize; -- _7 = Lt(_5, _6); -- assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> [success: bb2, unwind continue]; +- _7 = Lt(copy _5, copy _6); +- assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, copy _5) -> [success: bb2, unwind continue]; + _7 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 6_usize, const 3_usize) -> [success: bb2, unwind continue]; } bb2: { -- _3 = _4[_5]; +- _3 = copy _4[_5]; + _3 = const 3_i32; StorageDead(_5); StorageDead(_4); StorageLive(_8); StorageLive(_9); _9 = const 42_u32; -- _8 = _9; +- _8 = copy _9; + _8 = const 42_u32; StorageDead(_9); StorageDead(_8); diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-abort.diff index c01a12eaa4f..e2420a341e0 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-abort.diff @@ -38,18 +38,18 @@ StorageLive(_5); _5 = const 3_usize; _6 = const 6_usize; - _7 = Lt(_5, _6); - assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> [success: bb2, unwind unreachable]; + _7 = Lt(copy _5, copy _6); + assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, copy _5) -> [success: bb2, unwind unreachable]; } bb2: { - _3 = _4[_5]; + _3 = copy _4[_5]; StorageDead(_5); StorageDead(_4); StorageLive(_8); - StorageLive(_9); - _9 = Point { x: const 12_u32, y: const 42_u32 }; -- _8 = (_9.1: u32); +- _8 = copy (_9.1: u32); - StorageDead(_9); + StorageLive(_10); + StorageLive(_11); @@ -57,7 +57,7 @@ + _10 = const 12_u32; + _11 = const 42_u32; + nop; -+ _8 = _11; ++ _8 = copy _11; + StorageDead(_10); + StorageDead(_11); + nop; diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-unwind.diff index 64028e4437b..a2fb3b979e6 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-unwind.diff @@ -38,18 +38,18 @@ StorageLive(_5); _5 = const 3_usize; _6 = const 6_usize; - _7 = Lt(_5, _6); - assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> [success: bb2, unwind continue]; + _7 = Lt(copy _5, copy _6); + assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, copy _5) -> [success: bb2, unwind continue]; } bb2: { - _3 = _4[_5]; + _3 = copy _4[_5]; StorageDead(_5); StorageDead(_4); StorageLive(_8); - StorageLive(_9); - _9 = Point { x: const 12_u32, y: const 42_u32 }; -- _8 = (_9.1: u32); +- _8 = copy (_9.1: u32); - StorageDead(_9); + StorageLive(_10); + StorageLive(_11); @@ -57,7 +57,7 @@ + _10 = const 12_u32; + _11 = const 42_u32; + nop; -+ _8 = _11; ++ _8 = copy _11; + StorageDead(_10); + StorageDead(_11); + nop; diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-abort.diff index c01a12eaa4f..e2420a341e0 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-abort.diff @@ -38,18 +38,18 @@ StorageLive(_5); _5 = const 3_usize; _6 = const 6_usize; - _7 = Lt(_5, _6); - assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> [success: bb2, unwind unreachable]; + _7 = Lt(copy _5, copy _6); + assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, copy _5) -> [success: bb2, unwind unreachable]; } bb2: { - _3 = _4[_5]; + _3 = copy _4[_5]; StorageDead(_5); StorageDead(_4); StorageLive(_8); - StorageLive(_9); - _9 = Point { x: const 12_u32, y: const 42_u32 }; -- _8 = (_9.1: u32); +- _8 = copy (_9.1: u32); - StorageDead(_9); + StorageLive(_10); + StorageLive(_11); @@ -57,7 +57,7 @@ + _10 = const 12_u32; + _11 = const 42_u32; + nop; -+ _8 = _11; ++ _8 = copy _11; + StorageDead(_10); + StorageDead(_11); + nop; diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-unwind.diff index 64028e4437b..a2fb3b979e6 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-unwind.diff @@ -38,18 +38,18 @@ StorageLive(_5); _5 = const 3_usize; _6 = const 6_usize; - _7 = Lt(_5, _6); - assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> [success: bb2, unwind continue]; + _7 = Lt(copy _5, copy _6); + assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, copy _5) -> [success: bb2, unwind continue]; } bb2: { - _3 = _4[_5]; + _3 = copy _4[_5]; StorageDead(_5); StorageDead(_4); StorageLive(_8); - StorageLive(_9); - _9 = Point { x: const 12_u32, y: const 42_u32 }; -- _8 = (_9.1: u32); +- _8 = copy (_9.1: u32); - StorageDead(_9); + StorageLive(_10); + StorageLive(_11); @@ -57,7 +57,7 @@ + _10 = const 12_u32; + _11 = const 42_u32; + nop; -+ _8 = _11; ++ _8 = copy _11; + StorageDead(_10); + StorageDead(_11); + nop; diff --git a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir index 2f6139712ff..5faa1e210cf 100644 --- a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir @@ -23,12 +23,12 @@ fn demo_byte_add_fat(_1: *const [u32], _2: usize) -> *const [u32] { bb0: { StorageLive(_4); StorageLive(_3); - _3 = _1 as *const u8 (PtrToPtr); - _4 = Offset(_3, _2); + _3 = copy _1 as *const u8 (PtrToPtr); + _4 = Offset(copy _3, copy _2); StorageDead(_3); StorageLive(_5); - _5 = PtrMetadata(_1); - _0 = *const [u32] from (_4, _5); + _5 = PtrMetadata(copy _1); + _0 = *const [u32] from (copy _4, copy _5); StorageDead(_5); StorageDead(_4); return; diff --git a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir index 2f6139712ff..5faa1e210cf 100644 --- a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir @@ -23,12 +23,12 @@ fn demo_byte_add_fat(_1: *const [u32], _2: usize) -> *const [u32] { bb0: { StorageLive(_4); StorageLive(_3); - _3 = _1 as *const u8 (PtrToPtr); - _4 = Offset(_3, _2); + _3 = copy _1 as *const u8 (PtrToPtr); + _4 = Offset(copy _3, copy _2); StorageDead(_3); StorageLive(_5); - _5 = PtrMetadata(_1); - _0 = *const [u32] from (_4, _5); + _5 = PtrMetadata(copy _1); + _0 = *const [u32] from (copy _4, copy _5); StorageDead(_5); StorageDead(_4); return; diff --git a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir index 8d47e63eff2..9429785045a 100644 --- a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir @@ -22,10 +22,10 @@ fn demo_byte_add_thin(_1: *const u32, _2: usize) -> *const u32 { bb0: { StorageLive(_4); StorageLive(_3); - _3 = _1 as *const u8 (PtrToPtr); - _4 = Offset(_3, _2); + _3 = copy _1 as *const u8 (PtrToPtr); + _4 = Offset(copy _3, copy _2); StorageDead(_3); - _0 = _4 as *const u32 (PtrToPtr); + _0 = copy _4 as *const u32 (PtrToPtr); StorageDead(_4); return; } diff --git a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir index 8d47e63eff2..9429785045a 100644 --- a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir @@ -22,10 +22,10 @@ fn demo_byte_add_thin(_1: *const u32, _2: usize) -> *const u32 { bb0: { StorageLive(_4); StorageLive(_3); - _3 = _1 as *const u8 (PtrToPtr); - _4 = Offset(_3, _2); + _3 = copy _1 as *const u8 (PtrToPtr); + _4 = Offset(copy _3, copy _2); StorageDead(_3); - _0 = _4 as *const u32 (PtrToPtr); + _0 = copy _4 as *const u32 (PtrToPtr); StorageDead(_4); return; } diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir index 96b4962854d..5d33c33d73f 100644 --- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir @@ -35,7 +35,7 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { bb0: { StorageLive(_4); - _4 = _1; + _4 = copy _1; goto -> bb1; } @@ -44,8 +44,8 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { StorageLive(_7); StorageLive(_6); StorageLive(_5); - _5 = _4; - _6 = Lt(move _5, _2); + _5 = copy _4; + _6 = Lt(move _5, copy _2); StorageDead(_5); switchInt(move _6) -> [0: bb2, otherwise: bb4]; } @@ -63,22 +63,22 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { } bb4: { - _7 = _4; + _7 = copy _4; StorageLive(_8); - _8 = ::forward_unchecked(_7, const 1_usize) -> [return: bb5, unwind unreachable]; + _8 = ::forward_unchecked(copy _7, const 1_usize) -> [return: bb5, unwind unreachable]; } bb5: { _4 = move _8; StorageDead(_8); - _9 = Option::::Some(_7); + _9 = Option::::Some(copy _7); StorageDead(_6); StorageDead(_7); - _10 = ((_9 as Some).0: u32); + _10 = copy ((_9 as Some).0: u32); StorageLive(_11); _11 = &_3; StorageLive(_12); - _12 = (_10,); + _12 = (copy _10,); _13 = >::call(move _11, move _12) -> [return: bb6, unwind unreachable]; } diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir index ce8e2bd083e..ded30a15520 100644 --- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -35,7 +35,7 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { bb0: { StorageLive(_4); - _4 = _1; + _4 = copy _1; goto -> bb1; } @@ -44,8 +44,8 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { StorageLive(_7); StorageLive(_6); StorageLive(_5); - _5 = _4; - _6 = Lt(move _5, _2); + _5 = copy _4; + _6 = Lt(move _5, copy _2); StorageDead(_5); switchInt(move _6) -> [0: bb2, otherwise: bb4]; } @@ -63,22 +63,22 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { } bb4: { - _7 = _4; + _7 = copy _4; StorageLive(_8); - _8 = ::forward_unchecked(_7, const 1_usize) -> [return: bb5, unwind: bb7]; + _8 = ::forward_unchecked(copy _7, const 1_usize) -> [return: bb5, unwind: bb7]; } bb5: { _4 = move _8; StorageDead(_8); - _9 = Option::::Some(_7); + _9 = Option::::Some(copy _7); StorageDead(_6); StorageDead(_7); - _10 = ((_9 as Some).0: u32); + _10 = copy ((_9 as Some).0: u32); StorageLive(_11); _11 = &_3; StorageLive(_12); - _12 = (_10,); + _12 = (copy _10,); _13 = >::call(move _11, move _12) -> [return: bb6, unwind: bb7]; } diff --git a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir index a7fe52d8390..60c0b8afa53 100644 --- a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir @@ -28,9 +28,9 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { } bb0: { - _4 = RangeInclusive:: { start: _1, end: _2, exhausted: const false }; + _4 = RangeInclusive:: { start: copy _1, end: copy _2, exhausted: const false }; StorageLive(_5); - _5 = _4; + _5 = copy _4; goto -> bb1; } @@ -56,11 +56,11 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { } bb5: { - _9 = ((_7 as Some).0: u32); + _9 = copy ((_7 as Some).0: u32); StorageLive(_10); _10 = &_3; StorageLive(_11); - _11 = (_9,); + _11 = (copy _9,); _12 = >::call(move _10, move _11) -> [return: bb6, unwind unreachable]; } diff --git a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir index 3e2bbcd3c91..7145da58ce1 100644 --- a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir @@ -28,9 +28,9 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { } bb0: { - _4 = RangeInclusive:: { start: _1, end: _2, exhausted: const false }; + _4 = RangeInclusive:: { start: copy _1, end: copy _2, exhausted: const false }; StorageLive(_5); - _5 = _4; + _5 = copy _4; goto -> bb1; } @@ -56,11 +56,11 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { } bb5: { - _9 = ((_7 as Some).0: u32); + _9 = copy ((_7 as Some).0: u32); StorageLive(_10); _10 = &_3; StorageLive(_11); - _11 = (_9,); + _11 = (copy _9,); _12 = >::call(move _10, move _11) -> [return: bb6, unwind: bb8]; } diff --git a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir index 2ac7e880ccb..2621ec67531 100644 --- a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir @@ -21,9 +21,9 @@ fn range_iter_next(_1: &mut std::ops::Range) -> Option { StorageLive(_5); StorageLive(_4); StorageLive(_2); - _2 = ((*_1).0: u32); + _2 = copy ((*_1).0: u32); StorageLive(_3); - _3 = ((*_1).1: u32); + _3 = copy ((*_1).1: u32); _4 = Lt(move _2, move _3); StorageDead(_3); StorageDead(_2); @@ -36,15 +36,15 @@ fn range_iter_next(_1: &mut std::ops::Range) -> Option { } bb2: { - _5 = ((*_1).0: u32); + _5 = copy ((*_1).0: u32); StorageLive(_6); - _6 = ::forward_unchecked(_5, const 1_usize) -> [return: bb3, unwind unreachable]; + _6 = ::forward_unchecked(copy _5, const 1_usize) -> [return: bb3, unwind unreachable]; } bb3: { ((*_1).0: u32) = move _6; StorageDead(_6); - _0 = Option::::Some(_5); + _0 = Option::::Some(copy _5); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir index 60bf644fce6..338fb4b9523 100644 --- a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir @@ -21,9 +21,9 @@ fn range_iter_next(_1: &mut std::ops::Range) -> Option { StorageLive(_5); StorageLive(_4); StorageLive(_2); - _2 = ((*_1).0: u32); + _2 = copy ((*_1).0: u32); StorageLive(_3); - _3 = ((*_1).1: u32); + _3 = copy ((*_1).1: u32); _4 = Lt(move _2, move _3); StorageDead(_3); StorageDead(_2); @@ -36,15 +36,15 @@ fn range_iter_next(_1: &mut std::ops::Range) -> Option { } bb2: { - _5 = ((*_1).0: u32); + _5 = copy ((*_1).0: u32); StorageLive(_6); - _6 = ::forward_unchecked(_5, const 1_usize) -> [return: bb3, unwind continue]; + _6 = ::forward_unchecked(copy _5, const 1_usize) -> [return: bb3, unwind continue]; } bb3: { ((*_1).0: u32) = move _6; StorageDead(_6); - _0 = Option::::Some(_5); + _0 = Option::::Some(copy _5); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir index 030f9c3b93e..cbfc58194cc 100644 --- a/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir @@ -25,9 +25,9 @@ fn ezmap(_1: Option) -> Option { } bb2: { - _3 = ((_1 as Some).0: i32); + _3 = copy ((_1 as Some).0: i32); StorageLive(_4); - _4 = Add(_3, const 1_i32); + _4 = Add(copy _3, const 1_i32); _0 = Option::::Some(move _4); StorageDead(_4); goto -> bb3; diff --git a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir index e382f744723..cbdd194afd3 100644 --- a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir @@ -68,7 +68,7 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2 } bb0: { - _3 = (*_2); + _3 = copy (*_2); _4 = &((*_3).0: usize); _5 = &((*_3).1: usize); _6 = &((*_3).2: usize); @@ -78,11 +78,11 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2 _8 = &_4; StorageLive(_10); StorageLive(_9); - _9 = _6; + _9 = copy _6; _10 = &_9; - _11 = ((*_3).0: usize); - _12 = ((*_3).2: usize); - _13 = Le(_11, _12); + _11 = copy ((*_3).0: usize); + _12 = copy ((*_3).2: usize); + _13 = Le(copy _11, copy _12); switchInt(move _13) -> [0: bb1, otherwise: bb2]; } @@ -102,12 +102,12 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2 _14 = &_7; StorageLive(_16); StorageLive(_15); - _15 = _5; + _15 = copy _5; _16 = &_15; StorageLive(_17); - _17 = ((*_3).3: usize); + _17 = copy ((*_3).3: usize); StorageLive(_18); - _18 = ((*_3).1: usize); + _18 = copy ((*_3).1: usize); _19 = Le(move _17, move _18); StorageDead(_18); StorageDead(_17); @@ -127,9 +127,9 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2 _20 = &_6; StorageLive(_22); StorageLive(_21); - _21 = _4; + _21 = copy _4; _22 = &_21; - _23 = Le(_12, _11); + _23 = Le(copy _12, copy _11); switchInt(move _23) -> [0: bb5, otherwise: bb6]; } @@ -149,12 +149,12 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2 _24 = &_5; StorageLive(_26); StorageLive(_25); - _25 = _7; + _25 = copy _7; _26 = &_25; StorageLive(_27); - _27 = ((*_3).1: usize); + _27 = copy ((*_3).1: usize); StorageLive(_28); - _28 = ((*_3).3: usize); + _28 = copy ((*_3).3: usize); _0 = Le(move _27, move _28); StorageDead(_28); StorageDead(_27); diff --git a/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir index d9e118d879a..bc7a31d5219 100644 --- a/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir @@ -18,25 +18,25 @@ fn variant_b::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:11:25: 11:41}, } bb0: { - _3 = (*_2); - _4 = ((*_3).0: usize); - _5 = ((*_3).1: usize); - _6 = ((*_3).2: usize); - _7 = ((*_3).3: usize); + _3 = copy (*_2); + _4 = copy ((*_3).0: usize); + _5 = copy ((*_3).1: usize); + _6 = copy ((*_3).2: usize); + _7 = copy ((*_3).3: usize); StorageLive(_8); - _8 = Le(_4, _6); + _8 = Le(copy _4, copy _6); switchInt(move _8) -> [0: bb2, otherwise: bb1]; } bb1: { StorageLive(_9); - _9 = Le(_7, _5); + _9 = Le(copy _7, copy _5); switchInt(move _9) -> [0: bb2, otherwise: bb6]; } bb2: { StorageLive(_10); - _10 = Le(_6, _4); + _10 = Le(copy _6, copy _4); switchInt(move _10) -> [0: bb3, otherwise: bb4]; } @@ -46,7 +46,7 @@ fn variant_b::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:11:25: 11:41}, } bb4: { - _0 = Le(_5, _7); + _0 = Le(copy _5, copy _7); goto -> bb5; } diff --git a/tests/mir-opt/pre-codegen/slice_index.rs b/tests/mir-opt/pre-codegen/slice_index.rs index 6ddc4ad0220..574062d6c35 100644 --- a/tests/mir-opt/pre-codegen/slice_index.rs +++ b/tests/mir-opt/pre-codegen/slice_index.rs @@ -10,17 +10,17 @@ use std::ops::Range; pub fn slice_index_usize(slice: &[u32], index: usize) -> u32 { // CHECK-LABEL: slice_index_usize // CHECK: [[LEN:_[0-9]+]] = Len((*_1)) - // CHECK: Lt(_2, [[LEN]]) + // CHECK: Lt(copy _2, copy [[LEN]]) // CHECK-NOT: precondition_check - // CHECK: _0 = (*_1)[_2]; + // CHECK: _0 = copy (*_1)[_2]; slice[index] } // EMIT_MIR slice_index.slice_get_mut_usize.PreCodegen.after.mir pub fn slice_get_mut_usize(slice: &mut [u32], index: usize) -> Option<&mut u32> { // CHECK-LABEL: slice_get_mut_usize - // CHECK: [[LEN:_[0-9]+]] = PtrMetadata(_1) - // CHECK: Lt(_2, move [[LEN]]) + // CHECK: [[LEN:_[0-9]+]] = PtrMetadata(copy _1) + // CHECK: Lt(copy _2, move [[LEN]]) // CHECK-NOT: precondition_check slice.get_mut(index) } @@ -37,9 +37,9 @@ pub unsafe fn slice_get_unchecked_mut_range(slice: &mut [u32], index: Range Option<&mut u32> { StorageLive(_8); StorageLive(_4); StorageLive(_3); - _3 = PtrMetadata(_1); - _4 = Lt(_2, move _3); + _3 = PtrMetadata(copy _1); + _4 = Lt(copy _2, move _3); switchInt(move _4) -> [0: bb1, otherwise: bb2]; } @@ -40,12 +40,12 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { StorageLive(_5); _5 = &raw mut (*_1); StorageLive(_6); - _6 = _5 as *mut u32 (PtrToPtr); - _7 = Offset(_6, _2); + _6 = copy _5 as *mut u32 (PtrToPtr); + _7 = Offset(copy _6, copy _2); StorageDead(_6); StorageDead(_5); _8 = &mut (*_7); - _0 = Option::<&mut u32>::Some(_8); + _0 = Option::<&mut u32>::Some(copy _8); StorageDead(_7); goto -> bb3; } diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir index 58e9b45a4a0..ec67193bc79 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir @@ -23,8 +23,8 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { StorageLive(_8); StorageLive(_4); StorageLive(_3); - _3 = PtrMetadata(_1); - _4 = Lt(_2, move _3); + _3 = PtrMetadata(copy _1); + _4 = Lt(copy _2, move _3); switchInt(move _4) -> [0: bb1, otherwise: bb2]; } @@ -40,12 +40,12 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { StorageLive(_5); _5 = &raw mut (*_1); StorageLive(_6); - _6 = _5 as *mut u32 (PtrToPtr); - _7 = Offset(_6, _2); + _6 = copy _5 as *mut u32 (PtrToPtr); + _7 = Offset(copy _6, copy _2); StorageDead(_6); StorageDead(_5); _8 = &mut (*_7); - _0 = Option::<&mut u32>::Some(_8); + _0 = Option::<&mut u32>::Some(copy _8); StorageDead(_7); goto -> bb3; } diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir index ee80726a675..220e881f866 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir @@ -40,19 +40,19 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> _5 = &raw mut (*_1); StorageLive(_8); StorageLive(_6); - _6 = PtrMetadata(_1); - _7 = as SliceIndex<[T]>>::get_unchecked_mut::precondition_check(_3, _4, move _6) -> [return: bb1, unwind unreachable]; + _6 = PtrMetadata(copy _1); + _7 = as SliceIndex<[T]>>::get_unchecked_mut::precondition_check(copy _3, copy _4, move _6) -> [return: bb1, unwind unreachable]; } bb1: { StorageDead(_6); - _8 = SubUnchecked(_4, _3); + _8 = SubUnchecked(copy _4, copy _3); StorageLive(_10); StorageLive(_9); - _9 = _5 as *mut u32 (PtrToPtr); - _10 = Offset(_9, _3); + _9 = copy _5 as *mut u32 (PtrToPtr); + _10 = Offset(copy _9, copy _3); StorageDead(_9); - _11 = *mut [u32] from (_10, _8); + _11 = *mut [u32] from (copy _10, copy _8); StorageDead(_10); StorageDead(_8); StorageDead(_5); diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir index ee80726a675..220e881f866 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir @@ -40,19 +40,19 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> _5 = &raw mut (*_1); StorageLive(_8); StorageLive(_6); - _6 = PtrMetadata(_1); - _7 = as SliceIndex<[T]>>::get_unchecked_mut::precondition_check(_3, _4, move _6) -> [return: bb1, unwind unreachable]; + _6 = PtrMetadata(copy _1); + _7 = as SliceIndex<[T]>>::get_unchecked_mut::precondition_check(copy _3, copy _4, move _6) -> [return: bb1, unwind unreachable]; } bb1: { StorageDead(_6); - _8 = SubUnchecked(_4, _3); + _8 = SubUnchecked(copy _4, copy _3); StorageLive(_10); StorageLive(_9); - _9 = _5 as *mut u32 (PtrToPtr); - _10 = Offset(_9, _3); + _9 = copy _5 as *mut u32 (PtrToPtr); + _10 = Offset(copy _9, copy _3); StorageDead(_9); - _11 = *mut [u32] from (_10, _8); + _11 = *mut [u32] from (copy _10, copy _8); StorageDead(_10); StorageDead(_8); StorageDead(_5); diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_index_usize.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_index_usize.PreCodegen.after.panic-abort.mir index 210f9d6a124..cc1034229fc 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_index_usize.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_index_usize.PreCodegen.after.panic-abort.mir @@ -9,12 +9,12 @@ fn slice_index_usize(_1: &[u32], _2: usize) -> u32 { bb0: { _3 = Len((*_1)); - _4 = Lt(_2, _3); - assert(move _4, "index out of bounds: the length is {} but the index is {}", move _3, _2) -> [success: bb1, unwind unreachable]; + _4 = Lt(copy _2, copy _3); + assert(move _4, "index out of bounds: the length is {} but the index is {}", move _3, copy _2) -> [success: bb1, unwind unreachable]; } bb1: { - _0 = (*_1)[_2]; + _0 = copy (*_1)[_2]; return; } } diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_index_usize.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_index_usize.PreCodegen.after.panic-unwind.mir index d576520a8d5..358226fb529 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_index_usize.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_index_usize.PreCodegen.after.panic-unwind.mir @@ -9,12 +9,12 @@ fn slice_index_usize(_1: &[u32], _2: usize) -> u32 { bb0: { _3 = Len((*_1)); - _4 = Lt(_2, _3); - assert(move _4, "index out of bounds: the length is {} but the index is {}", move _3, _2) -> [success: bb1, unwind continue]; + _4 = Lt(copy _2, copy _3); + assert(move _4, "index out of bounds: the length is {} but the index is {}", move _3, copy _2) -> [success: bb1, unwind continue]; } bb1: { - _0 = (*_1)[_2]; + _0 = copy (*_1)[_2]; return; } } diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-abort.mir index c61bebe6cc3..1e0df94b67f 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-abort.mir @@ -35,19 +35,19 @@ fn slice_ptr_get_unchecked_range(_1: *const [u32], _2: std::ops::Range) - _4 = move (_2.1: usize); StorageLive(_7); StorageLive(_5); - _5 = PtrMetadata(_1); - _6 = as SliceIndex<[T]>>::get_unchecked::precondition_check(_3, _4, move _5) -> [return: bb1, unwind unreachable]; + _5 = PtrMetadata(copy _1); + _6 = as SliceIndex<[T]>>::get_unchecked::precondition_check(copy _3, copy _4, move _5) -> [return: bb1, unwind unreachable]; } bb1: { StorageDead(_5); - _7 = SubUnchecked(_4, _3); + _7 = SubUnchecked(copy _4, copy _3); StorageLive(_9); StorageLive(_8); - _8 = _1 as *const u32 (PtrToPtr); - _9 = Offset(_8, _3); + _8 = copy _1 as *const u32 (PtrToPtr); + _9 = Offset(copy _8, copy _3); StorageDead(_8); - _0 = *const [u32] from (_9, _7); + _0 = *const [u32] from (copy _9, copy _7); StorageDead(_9); StorageDead(_7); return; diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-unwind.mir index c61bebe6cc3..1e0df94b67f 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-unwind.mir @@ -35,19 +35,19 @@ fn slice_ptr_get_unchecked_range(_1: *const [u32], _2: std::ops::Range) - _4 = move (_2.1: usize); StorageLive(_7); StorageLive(_5); - _5 = PtrMetadata(_1); - _6 = as SliceIndex<[T]>>::get_unchecked::precondition_check(_3, _4, move _5) -> [return: bb1, unwind unreachable]; + _5 = PtrMetadata(copy _1); + _6 = as SliceIndex<[T]>>::get_unchecked::precondition_check(copy _3, copy _4, move _5) -> [return: bb1, unwind unreachable]; } bb1: { StorageDead(_5); - _7 = SubUnchecked(_4, _3); + _7 = SubUnchecked(copy _4, copy _3); StorageLive(_9); StorageLive(_8); - _8 = _1 as *const u32 (PtrToPtr); - _9 = Offset(_8, _3); + _8 = copy _1 as *const u32 (PtrToPtr); + _9 = Offset(copy _8, copy _3); StorageDead(_8); - _0 = *const [u32] from (_9, _7); + _0 = *const [u32] from (copy _9, copy _7); StorageDead(_9); StorageDead(_7); return; diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir index 953e7550479..3aa483ed1ae 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir @@ -31,7 +31,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } scope 19 { scope 20 { - scope 26 (inlined as FromResidual>::from_residual) { + scope 26 (inlined as FromResidual>>::from_residual) { } } } @@ -90,10 +90,10 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { StorageLive(_6); StorageLive(_4); StorageLive(_5); - _3 = PtrMetadata(_1); + _3 = PtrMetadata(copy _1); _4 = &raw const (*_1); - _5 = _4 as *const T (PtrToPtr); - _6 = NonNull:: { pointer: _5 }; + _5 = copy _4 as *const T (PtrToPtr); + _6 = NonNull:: { pointer: copy _5 }; StorageLive(_9); switchInt(const ::IS_ZST) -> [0: bb1, otherwise: bb2]; } @@ -101,8 +101,8 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb1: { StorageLive(_8); StorageLive(_7); - _7 = _4 as *mut T (PtrToPtr); - _8 = Offset(_7, _3); + _7 = copy _4 as *mut T (PtrToPtr); + _8 = Offset(copy _7, copy _3); StorageDead(_7); _9 = move _8 as *const T (PtrToPtr); StorageDead(_8); @@ -110,24 +110,24 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb2: { - _9 = _3 as *const T (Transmute); + _9 = copy _3 as *const T (Transmute); goto -> bb3; } bb3: { StorageLive(_10); - _10 = _9; - _11 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> }; + _10 = copy _9; + _11 = std::slice::Iter::<'_, T> { ptr: copy _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> }; StorageDead(_10); StorageDead(_9); StorageDead(_5); StorageDead(_4); StorageDead(_6); StorageDead(_3); - _12 = Enumerate::> { iter: _11, count: const 0_usize }; + _12 = Enumerate::> { iter: copy _11, count: const 0_usize }; StorageDead(_11); StorageLive(_13); - _13 = _12; + _13 = copy _12; goto -> bb4; } @@ -166,25 +166,25 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { _17 = move ((_15 as Some).0: &T); StorageDead(_16); StorageDead(_15); - _18 = (_13.1: usize); - _19 = AddWithOverflow((_13.1: usize), const 1_usize); - assert(!move (_19.1: bool), "attempt to compute `{} + {}`, which would overflow", (_13.1: usize), const 1_usize) -> [success: bb9, unwind unreachable]; + _18 = copy (_13.1: usize); + _19 = AddWithOverflow(copy (_13.1: usize), const 1_usize); + assert(!move (_19.1: bool), "attempt to compute `{} + {}`, which would overflow", copy (_13.1: usize), const 1_usize) -> [success: bb9, unwind unreachable]; } bb9: { (_13.1: usize) = move (_19.0: usize); StorageLive(_20); - _20 = (_18, _17); + _20 = (copy _18, copy _17); _21 = Option::<(usize, &T)>::Some(move _20); StorageDead(_20); StorageDead(_19); StorageDead(_18); - _22 = (((_21 as Some).0: (usize, &T)).0: usize); - _23 = (((_21 as Some).0: (usize, &T)).1: &T); + _22 = copy (((_21 as Some).0: (usize, &T)).0: usize); + _23 = copy (((_21 as Some).0: (usize, &T)).1: &T); StorageLive(_24); _24 = &_2; StorageLive(_25); - _25 = (_22, _23); + _25 = (copy _22, copy _23); _26 = >::call(move _24, move _25) -> [return: bb10, unwind unreachable]; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir index 4c766c6497a..4cc0aa0ed78 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir @@ -65,10 +65,10 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { StorageLive(_6); StorageLive(_4); StorageLive(_5); - _3 = PtrMetadata(_1); + _3 = PtrMetadata(copy _1); _4 = &raw const (*_1); - _5 = _4 as *const T (PtrToPtr); - _6 = NonNull:: { pointer: _5 }; + _5 = copy _4 as *const T (PtrToPtr); + _6 = NonNull:: { pointer: copy _5 }; StorageLive(_9); switchInt(const ::IS_ZST) -> [0: bb1, otherwise: bb2]; } @@ -76,8 +76,8 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb1: { StorageLive(_8); StorageLive(_7); - _7 = _4 as *mut T (PtrToPtr); - _8 = Offset(_7, _3); + _7 = copy _4 as *mut T (PtrToPtr); + _8 = Offset(copy _7, copy _3); StorageDead(_7); _9 = move _8 as *const T (PtrToPtr); StorageDead(_8); @@ -85,24 +85,24 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb2: { - _9 = _3 as *const T (Transmute); + _9 = copy _3 as *const T (Transmute); goto -> bb3; } bb3: { StorageLive(_10); - _10 = _9; - _11 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> }; + _10 = copy _9; + _11 = std::slice::Iter::<'_, T> { ptr: copy _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> }; StorageDead(_10); StorageDead(_9); StorageDead(_5); StorageDead(_4); StorageDead(_6); StorageDead(_3); - _12 = Enumerate::> { iter: _11, count: const 0_usize }; + _12 = Enumerate::> { iter: copy _11, count: const 0_usize }; StorageDead(_11); StorageLive(_13); - _13 = _12; + _13 = copy _12; goto -> bb4; } @@ -128,12 +128,12 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb8: { - _17 = (((_15 as Some).0: (usize, &T)).0: usize); - _18 = (((_15 as Some).0: (usize, &T)).1: &T); + _17 = copy (((_15 as Some).0: (usize, &T)).0: usize); + _18 = copy (((_15 as Some).0: (usize, &T)).1: &T); StorageLive(_19); _19 = &_2; StorageLive(_20); - _20 = (_17, _18); + _20 = (copy _17, copy _18); _21 = >::call(move _19, move _20) -> [return: bb9, unwind: bb11]; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir index 03de9fd938e..507afa63c68 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir @@ -57,10 +57,10 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { StorageLive(_6); StorageLive(_4); StorageLive(_5); - _3 = PtrMetadata(_1); + _3 = PtrMetadata(copy _1); _4 = &raw const (*_1); - _5 = _4 as *const T (PtrToPtr); - _6 = NonNull:: { pointer: _5 }; + _5 = copy _4 as *const T (PtrToPtr); + _6 = NonNull:: { pointer: copy _5 }; StorageLive(_9); switchInt(const ::IS_ZST) -> [0: bb1, otherwise: bb2]; } @@ -68,8 +68,8 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { bb1: { StorageLive(_8); StorageLive(_7); - _7 = _4 as *mut T (PtrToPtr); - _8 = Offset(_7, _3); + _7 = copy _4 as *mut T (PtrToPtr); + _8 = Offset(copy _7, copy _3); StorageDead(_7); _9 = move _8 as *const T (PtrToPtr); StorageDead(_8); @@ -77,14 +77,14 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb2: { - _9 = _3 as *const T (Transmute); + _9 = copy _3 as *const T (Transmute); goto -> bb3; } bb3: { StorageLive(_10); - _10 = _9; - _11 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> }; + _10 = copy _9; + _11 = std::slice::Iter::<'_, T> { ptr: copy _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> }; StorageDead(_10); StorageDead(_9); StorageDead(_5); @@ -92,7 +92,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { StorageDead(_6); StorageDead(_3); StorageLive(_12); - _12 = _11; + _12 = copy _11; goto -> bb4; } @@ -118,11 +118,11 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _16 = ((_14 as Some).0: &T); + _16 = copy ((_14 as Some).0: &T); StorageLive(_17); _17 = &_2; StorageLive(_18); - _18 = (_16,); + _18 = (copy _16,); _19 = >::call(move _17, move _18) -> [return: bb9, unwind unreachable]; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir index c7c722274f2..a25f12edc28 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -57,10 +57,10 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { StorageLive(_6); StorageLive(_4); StorageLive(_5); - _3 = PtrMetadata(_1); + _3 = PtrMetadata(copy _1); _4 = &raw const (*_1); - _5 = _4 as *const T (PtrToPtr); - _6 = NonNull:: { pointer: _5 }; + _5 = copy _4 as *const T (PtrToPtr); + _6 = NonNull:: { pointer: copy _5 }; StorageLive(_9); switchInt(const ::IS_ZST) -> [0: bb1, otherwise: bb2]; } @@ -68,8 +68,8 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { bb1: { StorageLive(_8); StorageLive(_7); - _7 = _4 as *mut T (PtrToPtr); - _8 = Offset(_7, _3); + _7 = copy _4 as *mut T (PtrToPtr); + _8 = Offset(copy _7, copy _3); StorageDead(_7); _9 = move _8 as *const T (PtrToPtr); StorageDead(_8); @@ -77,14 +77,14 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb2: { - _9 = _3 as *const T (Transmute); + _9 = copy _3 as *const T (Transmute); goto -> bb3; } bb3: { StorageLive(_10); - _10 = _9; - _11 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> }; + _10 = copy _9; + _11 = std::slice::Iter::<'_, T> { ptr: copy _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> }; StorageDead(_10); StorageDead(_9); StorageDead(_5); @@ -92,7 +92,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { StorageDead(_6); StorageDead(_3); StorageLive(_12); - _12 = _11; + _12 = copy _11; goto -> bb4; } @@ -118,11 +118,11 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _16 = ((_14 as Some).0: &T); + _16 = copy ((_14 as Some).0: &T); StorageLive(_17); _17 = &_2; StorageLive(_18); - _18 = (_16,); + _18 = (copy _16,); _19 = >::call(move _17, move _18) -> [return: bb9, unwind: bb11]; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir index cea2fcbcdc0..ecac03ad0f9 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir @@ -40,7 +40,7 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb0: { - _3 = PtrMetadata(_1); + _3 = PtrMetadata(copy _1); StorageLive(_4); _4 = const 0_usize; goto -> bb1; @@ -51,8 +51,8 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { StorageLive(_7); StorageLive(_6); StorageLive(_5); - _5 = _4; - _6 = Lt(move _5, _3); + _5 = copy _4; + _6 = Lt(move _5, copy _3); StorageDead(_5); switchInt(move _6) -> [0: bb2, otherwise: bb4]; } @@ -70,21 +70,21 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb4: { - _7 = _4; + _7 = copy _4; StorageLive(_8); - _8 = ::forward_unchecked(_7, const 1_usize) -> [return: bb5, unwind unreachable]; + _8 = ::forward_unchecked(copy _7, const 1_usize) -> [return: bb5, unwind unreachable]; } bb5: { _4 = move _8; StorageDead(_8); - _9 = Option::::Some(_7); + _9 = Option::::Some(copy _7); StorageDead(_6); StorageDead(_7); - _10 = ((_9 as Some).0: usize); + _10 = copy ((_9 as Some).0: usize); _11 = Len((*_1)); - _12 = Lt(_10, _11); - assert(move _12, "index out of bounds: the length is {} but the index is {}", move _11, _10) -> [success: bb6, unwind unreachable]; + _12 = Lt(copy _10, copy _11); + assert(move _12, "index out of bounds: the length is {} but the index is {}", move _11, copy _10) -> [success: bb6, unwind unreachable]; } bb6: { @@ -92,7 +92,7 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { StorageLive(_14); _14 = &_2; StorageLive(_15); - _15 = (_10, _13); + _15 = (copy _10, copy _13); _16 = >::call(move _14, move _15) -> [return: bb7, unwind unreachable]; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir index bd658a770ea..1032473b9b2 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir @@ -40,7 +40,7 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb0: { - _3 = PtrMetadata(_1); + _3 = PtrMetadata(copy _1); StorageLive(_4); _4 = const 0_usize; goto -> bb1; @@ -51,8 +51,8 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { StorageLive(_7); StorageLive(_6); StorageLive(_5); - _5 = _4; - _6 = Lt(move _5, _3); + _5 = copy _4; + _6 = Lt(move _5, copy _3); StorageDead(_5); switchInt(move _6) -> [0: bb2, otherwise: bb4]; } @@ -70,21 +70,21 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb4: { - _7 = _4; + _7 = copy _4; StorageLive(_8); - _8 = ::forward_unchecked(_7, const 1_usize) -> [return: bb5, unwind: bb8]; + _8 = ::forward_unchecked(copy _7, const 1_usize) -> [return: bb5, unwind: bb8]; } bb5: { _4 = move _8; StorageDead(_8); - _9 = Option::::Some(_7); + _9 = Option::::Some(copy _7); StorageDead(_6); StorageDead(_7); - _10 = ((_9 as Some).0: usize); + _10 = copy ((_9 as Some).0: usize); _11 = Len((*_1)); - _12 = Lt(_10, _11); - assert(move _12, "index out of bounds: the length is {} but the index is {}", move _11, _10) -> [success: bb6, unwind: bb8]; + _12 = Lt(copy _10, copy _11); + assert(move _12, "index out of bounds: the length is {} but the index is {}", move _11, copy _10) -> [success: bb6, unwind: bb8]; } bb6: { @@ -92,7 +92,7 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { StorageLive(_14); _14 = &_2; StorageLive(_15); - _15 = (_10, _13); + _15 = (copy _10, copy _13); _16 = >::call(move _14, move _15) -> [return: bb7, unwind: bb8]; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir index fbb887fe76a..1b397a4e4cd 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir @@ -65,10 +65,10 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { StorageLive(_6); StorageLive(_4); StorageLive(_5); - _3 = PtrMetadata(_1); + _3 = PtrMetadata(copy _1); _4 = &raw const (*_1); - _5 = _4 as *const T (PtrToPtr); - _6 = NonNull:: { pointer: _5 }; + _5 = copy _4 as *const T (PtrToPtr); + _6 = NonNull:: { pointer: copy _5 }; StorageLive(_9); switchInt(const ::IS_ZST) -> [0: bb1, otherwise: bb2]; } @@ -76,8 +76,8 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { bb1: { StorageLive(_8); StorageLive(_7); - _7 = _4 as *mut T (PtrToPtr); - _8 = Offset(_7, _3); + _7 = copy _4 as *mut T (PtrToPtr); + _8 = Offset(copy _7, copy _3); StorageDead(_7); _9 = move _8 as *const T (PtrToPtr); StorageDead(_8); @@ -85,24 +85,24 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb2: { - _9 = _3 as *const T (Transmute); + _9 = copy _3 as *const T (Transmute); goto -> bb3; } bb3: { StorageLive(_10); - _10 = _9; - _11 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> }; + _10 = copy _9; + _11 = std::slice::Iter::<'_, T> { ptr: copy _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> }; StorageDead(_10); StorageDead(_9); StorageDead(_5); StorageDead(_4); StorageDead(_6); StorageDead(_3); - _12 = Rev::> { iter: _11 }; + _12 = Rev::> { iter: copy _11 }; StorageDead(_11); StorageLive(_13); - _13 = _12; + _13 = copy _12; goto -> bb4; } @@ -130,11 +130,11 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _17 = ((_15 as Some).0: &T); + _17 = copy ((_15 as Some).0: &T); StorageLive(_18); _18 = &_2; StorageLive(_19); - _19 = (_17,); + _19 = (copy _17,); _20 = >::call(move _18, move _19) -> [return: bb9, unwind unreachable]; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir index db9409f72ab..77689dd9b51 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir @@ -65,10 +65,10 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { StorageLive(_6); StorageLive(_4); StorageLive(_5); - _3 = PtrMetadata(_1); + _3 = PtrMetadata(copy _1); _4 = &raw const (*_1); - _5 = _4 as *const T (PtrToPtr); - _6 = NonNull:: { pointer: _5 }; + _5 = copy _4 as *const T (PtrToPtr); + _6 = NonNull:: { pointer: copy _5 }; StorageLive(_9); switchInt(const ::IS_ZST) -> [0: bb1, otherwise: bb2]; } @@ -76,8 +76,8 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { bb1: { StorageLive(_8); StorageLive(_7); - _7 = _4 as *mut T (PtrToPtr); - _8 = Offset(_7, _3); + _7 = copy _4 as *mut T (PtrToPtr); + _8 = Offset(copy _7, copy _3); StorageDead(_7); _9 = move _8 as *const T (PtrToPtr); StorageDead(_8); @@ -85,24 +85,24 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb2: { - _9 = _3 as *const T (Transmute); + _9 = copy _3 as *const T (Transmute); goto -> bb3; } bb3: { StorageLive(_10); - _10 = _9; - _11 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> }; + _10 = copy _9; + _11 = std::slice::Iter::<'_, T> { ptr: copy _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> }; StorageDead(_10); StorageDead(_9); StorageDead(_5); StorageDead(_4); StorageDead(_6); StorageDead(_3); - _12 = Rev::> { iter: _11 }; + _12 = Rev::> { iter: copy _11 }; StorageDead(_11); StorageLive(_13); - _13 = _12; + _13 = copy _12; goto -> bb4; } @@ -130,11 +130,11 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _17 = ((_15 as Some).0: &T); + _17 = copy ((_15 as Some).0: &T); StorageLive(_18); _18 = &_2; StorageLive(_19); - _19 = (_17,); + _19 = (copy _17,); _20 = >::call(move _18, move _19) -> [return: bb9, unwind: bb11]; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-abort.mir index 96e71c298e0..f8b0e749bfc 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-abort.mir @@ -43,27 +43,27 @@ fn slice_iter_generic_is_empty(_1: &std::slice::Iter<'_, T>) -> bool { StorageLive(_3); StorageLive(_2); _2 = &raw const ((*_1).1: *const T); - _3 = _2 as *const std::ptr::NonNull (PtrToPtr); + _3 = copy _2 as *const std::ptr::NonNull (PtrToPtr); StorageDead(_2); - _4 = (*_3); + _4 = copy (*_3); StorageDead(_3); StorageLive(_6); StorageLive(_7); StorageLive(_5); - _5 = ((*_1).0: std::ptr::NonNull); - _6 = (_5.0: *const T); + _5 = copy ((*_1).0: std::ptr::NonNull); + _6 = copy (_5.0: *const T); StorageDead(_5); - _7 = (_4.0: *const T); - _0 = Eq(_6, _7); + _7 = copy (_4.0: *const T); + _0 = Eq(copy _6, copy _7); StorageDead(_7); StorageDead(_6); goto -> bb3; } bb2: { - _8 = ((*_1).1: *const T); - _9 = _8 as usize (Transmute); - _0 = Eq(_9, const 0_usize); + _8 = copy ((*_1).1: *const T); + _9 = copy _8 as usize (Transmute); + _0 = Eq(copy _9, const 0_usize); goto -> bb3; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-unwind.mir index 96e71c298e0..f8b0e749bfc 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-unwind.mir @@ -43,27 +43,27 @@ fn slice_iter_generic_is_empty(_1: &std::slice::Iter<'_, T>) -> bool { StorageLive(_3); StorageLive(_2); _2 = &raw const ((*_1).1: *const T); - _3 = _2 as *const std::ptr::NonNull (PtrToPtr); + _3 = copy _2 as *const std::ptr::NonNull (PtrToPtr); StorageDead(_2); - _4 = (*_3); + _4 = copy (*_3); StorageDead(_3); StorageLive(_6); StorageLive(_7); StorageLive(_5); - _5 = ((*_1).0: std::ptr::NonNull); - _6 = (_5.0: *const T); + _5 = copy ((*_1).0: std::ptr::NonNull); + _6 = copy (_5.0: *const T); StorageDead(_5); - _7 = (_4.0: *const T); - _0 = Eq(_6, _7); + _7 = copy (_4.0: *const T); + _0 = Eq(copy _6, copy _7); StorageDead(_7); StorageDead(_6); goto -> bb3; } bb2: { - _8 = ((*_1).1: *const T); - _9 = _8 as usize (Transmute); - _0 = Eq(_9, const 0_usize); + _8 = copy ((*_1).1: *const T); + _9 = copy _8 as usize (Transmute); + _0 = Eq(copy _9, const 0_usize); goto -> bb3; } diff --git a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir index c76e5315db9..fe4e2deab87 100644 --- a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir @@ -10,7 +10,7 @@ fn outer(_1: u8) -> u8 { bb0: { _2 = &_1; // scope 0 at $DIR/spans.rs:11:11: 11:13 - _0 = _1; // scope 1 at $DIR/spans.rs:15:5: 15:7 + _0 = copy _1; // scope 1 at $DIR/spans.rs:15:5: 15:7 return; // scope 0 at $DIR/spans.rs:12:2: 12:2 } } diff --git a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir index c76e5315db9..fe4e2deab87 100644 --- a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir @@ -10,7 +10,7 @@ fn outer(_1: u8) -> u8 { bb0: { _2 = &_1; // scope 0 at $DIR/spans.rs:11:11: 11:13 - _0 = _1; // scope 1 at $DIR/spans.rs:15:5: 15:7 + _0 = copy _1; // scope 1 at $DIR/spans.rs:15:5: 15:7 return; // scope 0 at $DIR/spans.rs:12:2: 12:2 } } diff --git a/tests/mir-opt/pre-codegen/try_identity.new.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/try_identity.new.PreCodegen.after.mir index 16d6d9719b6..baa01e28a94 100644 --- a/tests/mir-opt/pre-codegen/try_identity.new.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/try_identity.new.PreCodegen.after.mir @@ -30,18 +30,18 @@ fn new(_1: Result) -> Result { bb1: { _3 = move ((_1 as Ok).0: T); - _4 = ControlFlow::::Continue(_3); + _4 = ControlFlow::::Continue(copy _3); _5 = move ((_4 as Continue).0: T); - _0 = Result::::Ok(_5); + _0 = Result::::Ok(copy _5); StorageDead(_4); goto -> bb3; } bb2: { _6 = move ((_1 as Err).0: E); - _4 = ControlFlow::::Break(_6); + _4 = ControlFlow::::Break(copy _6); _7 = move ((_4 as Break).0: E); - _0 = Result::::Err(_7); + _0 = Result::::Err(copy _7); StorageDead(_4); goto -> bb3; } diff --git a/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir index d6883ac9fda..ac485f485b1 100644 --- a/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir @@ -20,13 +20,13 @@ fn old(_1: Result) -> Result { bb1: { _3 = move ((_1 as Ok).0: T); - _0 = Result::::Ok(_3); + _0 = Result::::Ok(copy _3); goto -> bb3; } bb2: { _4 = move ((_1 as Err).0: E); - _0 = Result::::Err(_4); + _0 = Result::::Err(copy _4); goto -> bb3; } diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir index 0fe4fd37072..ce1e4a0abd6 100644 --- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir @@ -78,17 +78,17 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { _3 = &(((*_1).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner); StorageLive(_6); StorageLive(_4); - _4 = (((((*_1).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique).0: std::ptr::NonNull); - _5 = (_4.0: *const u8); - _6 = NonNull:: { pointer: _5 }; + _4 = copy (((((*_1).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique).0: std::ptr::NonNull); + _5 = copy (_4.0: *const u8); + _6 = NonNull:: { pointer: copy _5 }; StorageDead(_4); StorageDead(_6); StorageDead(_3); StorageDead(_2); StorageLive(_7); - _7 = ((*_1).1: usize); + _7 = copy ((*_1).1: usize); StorageLive(_8); - _8 = *const [u8] from (_5, _7); + _8 = *const [u8] from (copy _5, copy _7); _0 = &(*_8); StorageDead(_8); StorageDead(_7); diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir index 0fe4fd37072..ce1e4a0abd6 100644 --- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir @@ -78,17 +78,17 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { _3 = &(((*_1).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner); StorageLive(_6); StorageLive(_4); - _4 = (((((*_1).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique).0: std::ptr::NonNull); - _5 = (_4.0: *const u8); - _6 = NonNull:: { pointer: _5 }; + _4 = copy (((((*_1).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique).0: std::ptr::NonNull); + _5 = copy (_4.0: *const u8); + _6 = NonNull:: { pointer: copy _5 }; StorageDead(_4); StorageDead(_6); StorageDead(_3); StorageDead(_2); StorageLive(_7); - _7 = ((*_1).1: usize); + _7 = copy ((*_1).1: usize); StorageLive(_8); - _8 = *const [u8] from (_5, _7); + _8 = *const [u8] from (copy _5, copy _7); _0 = &(*_8); StorageDead(_8); StorageDead(_7); diff --git a/tests/mir-opt/reference_prop.dominate_storage.ReferencePropagation.diff b/tests/mir-opt/reference_prop.dominate_storage.ReferencePropagation.diff index 012efa9693e..4715f5110eb 100644 --- a/tests/mir-opt/reference_prop.dominate_storage.ReferencePropagation.diff +++ b/tests/mir-opt/reference_prop.dominate_storage.ReferencePropagation.diff @@ -21,15 +21,15 @@ } bb2: { - _5 = (*_2); - _0 = opaque::(_5) -> [return: bb3, unwind continue]; + _5 = copy (*_2); + _0 = opaque::(copy _5) -> [return: bb3, unwind continue]; } bb3: { StorageDead(_1); StorageLive(_1); _6 = const true; - switchInt(_6) -> [0: bb3, otherwise: bb1]; + switchInt(copy _6) -> [0: bb3, otherwise: bb1]; } } diff --git a/tests/mir-opt/reference_prop.maybe_dead.ReferencePropagation.diff b/tests/mir-opt/reference_prop.maybe_dead.ReferencePropagation.diff index c6bd6c21210..b1de380d84d 100644 --- a/tests/mir-opt/reference_prop.maybe_dead.ReferencePropagation.diff +++ b/tests/mir-opt/reference_prop.maybe_dead.ReferencePropagation.diff @@ -19,25 +19,25 @@ _4 = &_2; _5 = &mut _3; (*_5) = const 7_i32; -- _6 = (*_4); -+ _6 = _2; - switchInt(_1) -> [1: bb1, otherwise: bb2]; +- _6 = copy (*_4); ++ _6 = copy _2; + switchInt(copy _1) -> [1: bb1, otherwise: bb2]; } bb1: { StorageDead(_2); StorageDead(_3); - _0 = opaque::(_6) -> [return: bb2, unwind continue]; + _0 = opaque::(copy _6) -> [return: bb2, unwind continue]; } bb2: { - _7 = (*_4); - _0 = opaque::(_7) -> [return: bb3, unwind continue]; + _7 = copy (*_4); + _0 = opaque::(copy _7) -> [return: bb3, unwind continue]; } bb3: { - _8 = (*_5); - _0 = opaque::(_8) -> [return: bb4, unwind continue]; + _8 = copy (*_5); + _0 = opaque::(copy _8) -> [return: bb4, unwind continue]; } bb4: { diff --git a/tests/mir-opt/reference_prop.multiple_storage.ReferencePropagation.diff b/tests/mir-opt/reference_prop.multiple_storage.ReferencePropagation.diff index 0fd74155aa3..2368edea5ba 100644 --- a/tests/mir-opt/reference_prop.multiple_storage.ReferencePropagation.diff +++ b/tests/mir-opt/reference_prop.multiple_storage.ReferencePropagation.diff @@ -13,8 +13,8 @@ _2 = &_1; StorageDead(_1); StorageLive(_1); - _3 = (*_2); - _0 = opaque::(_3) -> [return: bb1, unwind continue]; + _3 = copy (*_2); + _0 = opaque::(copy _3) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/reference_prop.mut_raw_then_mut_shr.ReferencePropagation.diff b/tests/mir-opt/reference_prop.mut_raw_then_mut_shr.ReferencePropagation.diff index 859097d3966..90fd91764cb 100644 --- a/tests/mir-opt/reference_prop.mut_raw_then_mut_shr.ReferencePropagation.diff +++ b/tests/mir-opt/reference_prop.mut_raw_then_mut_shr.ReferencePropagation.diff @@ -41,23 +41,23 @@ - StorageLive(_5); - _5 = &mut (*_2); - _4 = &raw mut (*_5); -- _3 = _4; +- _3 = copy _4; - StorageDead(_5); - StorageDead(_4); - StorageLive(_6); - _6 = &(*_2); StorageLive(_7); -- _7 = (*_6); +- _7 = copy (*_6); - StorageLive(_8); - (*_3) = const 4_i32; - _8 = const (); - StorageDead(_8); -+ _7 = _1; ++ _7 = copy _1; + _1 = const 4_i32; StorageLive(_9); - _9 = _7; + _9 = copy _7; StorageLive(_10); - _10 = _1; + _10 = copy _1; _0 = (move _9, move _10); StorageDead(_10); StorageDead(_9); diff --git a/tests/mir-opt/reference_prop.read_through_raw.ReferencePropagation.diff b/tests/mir-opt/reference_prop.read_through_raw.ReferencePropagation.diff index 371b0e468b1..064711925e0 100644 --- a/tests/mir-opt/reference_prop.read_through_raw.ReferencePropagation.diff +++ b/tests/mir-opt/reference_prop.read_through_raw.ReferencePropagation.diff @@ -13,10 +13,10 @@ - _3 = &mut (*_2); - _4 = &raw mut (*_2); - _5 = &raw mut (*_3); -- _0 = (*_4); -- _0 = (*_5); -+ _0 = (*_1); -+ _0 = (*_1); +- _0 = copy (*_4); +- _0 = copy (*_5); ++ _0 = copy (*_1); ++ _0 = copy (*_1); return; } } diff --git a/tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff b/tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff index 0dfe8781c18..3c6a9a9614c 100644 --- a/tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff +++ b/tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff @@ -191,8 +191,8 @@ StorageLive(_5); _5 = &_4; StorageLive(_6); -- _6 = (*_5); -+ _6 = _4; +- _6 = copy (*_5); ++ _6 = copy _4; StorageLive(_7); StorageLive(_8); _8 = (); @@ -223,7 +223,7 @@ StorageDead(_13); - StorageDead(_14); StorageLive(_15); - _15 = (*_12); + _15 = copy (*_12); StorageLive(_16); StorageLive(_17); _17 = (); @@ -247,11 +247,11 @@ StorageLive(_21); _21 = &_20; StorageLive(_22); -- _22 = (*_20); -+ _22 = _19; +- _22 = copy (*_20); ++ _22 = copy _19; StorageLive(_23); StorageLive(_24); - _24 = _21; + _24 = copy _21; _23 = opaque::<&&usize>(move _24) -> [return: bb3, unwind continue]; } @@ -272,10 +272,10 @@ StorageLive(_28); _28 = &raw mut _27; StorageLive(_29); - _29 = (*_27); + _29 = copy (*_27); StorageLive(_30); StorageLive(_31); - _31 = _28; + _31 = copy _28; _30 = opaque::<*mut &usize>(move _31) -> [return: bb4, unwind continue]; } @@ -294,11 +294,11 @@ StorageLive(_34); _34 = &_33; StorageLive(_35); -- _35 = (*_34); -+ _35 = _33; +- _35 = copy (*_34); ++ _35 = copy _33; StorageLive(_36); StorageLive(_37); - _37 = _34; + _37 = copy _34; _36 = opaque::<&usize>(move _37) -> [return: bb5, unwind continue]; } @@ -316,18 +316,18 @@ StorageLive(_40); _40 = &_39; StorageLive(_41); -- _41 = (*_40); -+ _41 = _39; +- _41 = copy (*_40); ++ _41 = copy _39; StorageLive(_42); - _42 = _40; + _42 = copy _40; StorageLive(_43); -- _43 = (*_42); -+ _43 = _39; +- _43 = copy (*_42); ++ _43 = copy _39; StorageLive(_44); - _44 = _42; + _44 = copy _42; StorageLive(_45); StorageLive(_46); - _46 = _44; + _46 = copy _44; _45 = opaque::<&usize>(move _46) -> [return: bb6, unwind continue]; } @@ -346,8 +346,8 @@ - StorageLive(_48); - _48 = &(*_1); StorageLive(_49); -- _49 = (*_48); -+ _49 = (*_1); +- _49 = copy (*_48); ++ _49 = copy (*_1); StorageLive(_50); StorageLive(_51); _51 = (); @@ -373,7 +373,7 @@ StorageDead(_54); - StorageDead(_55); StorageLive(_56); - _56 = (*_53); + _56 = copy (*_53); StorageLive(_57); StorageLive(_58); _58 = (); @@ -395,8 +395,8 @@ StorageLive(_62); _62 = &_61; StorageLive(_63); -- _63 = (*_61); -+ _63 = _60; +- _63 = copy (*_61); ++ _63 = copy _60; StorageLive(_64); StorageLive(_65); _65 = (); @@ -419,7 +419,7 @@ StorageLive(_68); _68 = &mut _67; StorageLive(_69); - _69 = (*_67); + _69 = copy (*_67); StorageLive(_70); StorageLive(_71); _71 = (); diff --git a/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff b/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff index 21486a8616a..75fe99de938 100644 --- a/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff +++ b/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff @@ -208,8 +208,8 @@ StorageLive(_5); _5 = &raw const _4; StorageLive(_6); -- _6 = (*_5); -+ _6 = _4; +- _6 = copy (*_5); ++ _6 = copy _4; StorageLive(_7); StorageLive(_8); _8 = (); @@ -236,7 +236,7 @@ _12 = move _13; StorageDead(_13); StorageLive(_14); - _14 = (*_12); + _14 = copy (*_12); StorageLive(_15); StorageLive(_16); _16 = (); @@ -260,11 +260,11 @@ StorageLive(_20); _20 = &_19; StorageLive(_21); -- _21 = (*_19); -+ _21 = _18; +- _21 = copy (*_19); ++ _21 = copy _18; StorageLive(_22); StorageLive(_23); - _23 = _20; + _23 = copy _20; _22 = opaque::<&*const usize>(move _23) -> [return: bb3, unwind continue]; } @@ -285,10 +285,10 @@ StorageLive(_27); _27 = &raw mut _26; StorageLive(_28); - _28 = (*_26); + _28 = copy (*_26); StorageLive(_29); StorageLive(_30); - _30 = _27; + _30 = copy _27; _29 = opaque::<*mut *const usize>(move _30) -> [return: bb4, unwind continue]; } @@ -307,11 +307,11 @@ StorageLive(_33); _33 = &raw const _32; StorageLive(_34); -- _34 = (*_33); -+ _34 = _32; +- _34 = copy (*_33); ++ _34 = copy _32; StorageLive(_35); StorageLive(_36); - _36 = _33; + _36 = copy _33; _35 = opaque::<*const usize>(move _36) -> [return: bb5, unwind continue]; } @@ -329,18 +329,18 @@ StorageLive(_39); _39 = &raw const _38; StorageLive(_40); -- _40 = (*_39); -+ _40 = _38; +- _40 = copy (*_39); ++ _40 = copy _38; StorageLive(_41); - _41 = _39; + _41 = copy _39; StorageLive(_42); -- _42 = (*_41); -+ _42 = _38; +- _42 = copy (*_41); ++ _42 = copy _38; StorageLive(_43); - _43 = _41; + _43 = copy _41; StorageLive(_44); StorageLive(_45); - _45 = _43; + _45 = copy _43; _44 = opaque::<*const usize>(move _45) -> [return: bb6, unwind continue]; } @@ -359,8 +359,8 @@ - StorageLive(_47); - _47 = &raw const (*_1); StorageLive(_48); -- _48 = (*_47); -+ _48 = (*_1); +- _48 = copy (*_47); ++ _48 = copy (*_1); StorageLive(_49); StorageLive(_50); _50 = (); @@ -382,7 +382,7 @@ _2 = move _53; StorageDead(_53); StorageLive(_54); - _54 = (*_52); + _54 = copy (*_52); StorageLive(_55); StorageLive(_56); _56 = (); @@ -405,8 +405,8 @@ - _60 = &raw const (*_59); + _60 = &raw const _58; StorageLive(_61); -- _61 = (*_60); -+ _61 = _58; +- _61 = copy (*_60); ++ _61 = copy _58; StorageLive(_62); StorageLive(_63); _63 = (); @@ -430,8 +430,8 @@ StorageLive(_67); _67 = &_66; StorageLive(_68); -- _68 = (*_66); -+ _68 = _65; +- _68 = copy (*_66); ++ _68 = copy _65; StorageLive(_69); StorageLive(_70); _70 = (); @@ -454,7 +454,7 @@ StorageLive(_73); _73 = &mut _72; StorageLive(_74); - _74 = (*_72); + _74 = copy (*_72); StorageLive(_75); StorageLive(_76); _76 = (); diff --git a/tests/mir-opt/reference_prop.reference_propagation_mut.ReferencePropagation.diff b/tests/mir-opt/reference_prop.reference_propagation_mut.ReferencePropagation.diff index 7c7f424bba2..f35b4974d6e 100644 --- a/tests/mir-opt/reference_prop.reference_propagation_mut.ReferencePropagation.diff +++ b/tests/mir-opt/reference_prop.reference_propagation_mut.ReferencePropagation.diff @@ -191,8 +191,8 @@ StorageLive(_5); _5 = &mut _4; StorageLive(_6); -- _6 = (*_5); -+ _6 = _4; +- _6 = copy (*_5); ++ _6 = copy _4; StorageLive(_7); StorageLive(_8); _8 = (); @@ -223,7 +223,7 @@ StorageDead(_13); - StorageDead(_14); StorageLive(_15); - _15 = (*_12); + _15 = copy (*_12); StorageLive(_16); StorageLive(_17); _17 = (); @@ -247,10 +247,10 @@ StorageLive(_21); _21 = &_20; StorageLive(_22); - _22 = (*_20); + _22 = copy (*_20); StorageLive(_23); StorageLive(_24); - _24 = _21; + _24 = copy _21; _23 = opaque::<&&mut usize>(move _24) -> [return: bb3, unwind continue]; } @@ -271,10 +271,10 @@ StorageLive(_28); _28 = &raw mut _27; StorageLive(_29); - _29 = (*_27); + _29 = copy (*_27); StorageLive(_30); StorageLive(_31); - _31 = _28; + _31 = copy _28; _30 = opaque::<*mut &mut usize>(move _31) -> [return: bb4, unwind continue]; } @@ -293,7 +293,7 @@ StorageLive(_34); _34 = &mut _33; StorageLive(_35); - _35 = (*_34); + _35 = copy (*_34); StorageLive(_36); StorageLive(_37); _37 = move _34; @@ -314,11 +314,11 @@ StorageLive(_40); _40 = &mut _39; StorageLive(_41); - _41 = (*_40); + _41 = copy (*_40); StorageLive(_42); _42 = move _40; StorageLive(_43); - _43 = (*_42); + _43 = copy (*_42); StorageLive(_44); _44 = move _42; StorageLive(_45); @@ -342,8 +342,8 @@ - StorageLive(_48); - _48 = &mut (*_1); StorageLive(_49); -- _49 = (*_48); -+ _49 = (*_1); +- _49 = copy (*_48); ++ _49 = copy (*_1); StorageLive(_50); StorageLive(_51); _51 = (); @@ -369,7 +369,7 @@ StorageDead(_54); - StorageDead(_55); StorageLive(_56); - _56 = (*_53); + _56 = copy (*_53); StorageLive(_57); StorageLive(_58); _58 = (); @@ -391,7 +391,7 @@ StorageLive(_62); _62 = &_61; StorageLive(_63); - _63 = (*_61); + _63 = copy (*_61); StorageLive(_64); StorageLive(_65); _65 = (); @@ -414,7 +414,7 @@ StorageLive(_68); _68 = &mut _67; StorageLive(_69); - _69 = (*_67); + _69 = copy (*_67); StorageLive(_70); StorageLive(_71); _71 = (); diff --git a/tests/mir-opt/reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff b/tests/mir-opt/reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff index 5629d04f1b1..21b322b7218 100644 --- a/tests/mir-opt/reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff +++ b/tests/mir-opt/reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff @@ -189,8 +189,8 @@ StorageLive(_5); _5 = &raw mut _4; StorageLive(_6); -- _6 = (*_5); -+ _6 = _4; +- _6 = copy (*_5); ++ _6 = copy _4; StorageLive(_7); StorageLive(_8); _8 = (); @@ -217,7 +217,7 @@ _12 = move _13; StorageDead(_13); StorageLive(_14); - _14 = (*_12); + _14 = copy (*_12); StorageLive(_15); StorageLive(_16); _16 = (); @@ -241,10 +241,10 @@ StorageLive(_20); _20 = &_19; StorageLive(_21); - _21 = (*_19); + _21 = copy (*_19); StorageLive(_22); StorageLive(_23); - _23 = _20; + _23 = copy _20; _22 = opaque::<&*mut usize>(move _23) -> [return: bb3, unwind continue]; } @@ -265,10 +265,10 @@ StorageLive(_27); _27 = &raw mut _26; StorageLive(_28); - _28 = (*_26); + _28 = copy (*_26); StorageLive(_29); StorageLive(_30); - _30 = _27; + _30 = copy _27; _29 = opaque::<*mut *mut usize>(move _30) -> [return: bb4, unwind continue]; } @@ -287,10 +287,10 @@ StorageLive(_33); _33 = &raw mut _32; StorageLive(_34); - _34 = (*_33); + _34 = copy (*_33); StorageLive(_35); StorageLive(_36); - _36 = _33; + _36 = copy _33; _35 = opaque::<*mut usize>(move _36) -> [return: bb5, unwind continue]; } @@ -308,16 +308,16 @@ StorageLive(_39); _39 = &raw mut _38; StorageLive(_40); - _40 = (*_39); + _40 = copy (*_39); StorageLive(_41); - _41 = _39; + _41 = copy _39; StorageLive(_42); - _42 = (*_41); + _42 = copy (*_41); StorageLive(_43); - _43 = _41; + _43 = copy _41; StorageLive(_44); StorageLive(_45); - _45 = _43; + _45 = copy _43; _44 = opaque::<*mut usize>(move _45) -> [return: bb6, unwind continue]; } @@ -336,8 +336,8 @@ - StorageLive(_47); - _47 = &raw mut (*_1); StorageLive(_48); -- _48 = (*_47); -+ _48 = (*_1); +- _48 = copy (*_47); ++ _48 = copy (*_1); StorageLive(_49); StorageLive(_50); _50 = (); @@ -359,7 +359,7 @@ _2 = move _53; StorageDead(_53); StorageLive(_54); - _54 = (*_52); + _54 = copy (*_52); StorageLive(_55); StorageLive(_56); _56 = (); @@ -381,7 +381,7 @@ StorageLive(_60); _60 = &_59; StorageLive(_61); - _61 = (*_59); + _61 = copy (*_59); StorageLive(_62); StorageLive(_63); _63 = (); @@ -404,7 +404,7 @@ StorageLive(_66); _66 = &mut _65; StorageLive(_67); - _67 = (*_65); + _67 = copy (*_65); StorageLive(_68); StorageLive(_69); _69 = (); diff --git a/tests/mir-opt/reference_prop.rs b/tests/mir-opt/reference_prop.rs index 58d8b524ad6..00d48938071 100644 --- a/tests/mir-opt/reference_prop.rs +++ b/tests/mir-opt/reference_prop.rs @@ -2,7 +2,6 @@ //@ test-mir-pass: ReferencePropagation //@ needs-unwind -#![feature(raw_ref_op)] #![feature(core_intrinsics, custom_mir)] #[inline(never)] @@ -16,7 +15,7 @@ fn reference_propagation<'a, T: Copy>(single: &'a T, mut multiple: &'a T) { // CHECK: bb0: { // CHECK: [[a:_.*]] = const 5_usize; // CHECK: [[b:_.*]] = &[[a]]; - // CHECK: [[c:_.*]] = [[a]]; + // CHECK: [[c:_.*]] = copy [[a]]; let a = 5_usize; let b = &a; // This borrow is only used once. @@ -32,7 +31,7 @@ fn reference_propagation<'a, T: Copy>(single: &'a T, mut multiple: &'a T) { // CHECK: [[b:_.*]] = &[[a]]; // CHECK: [[btmp:_.*]] = &[[a2]]; // CHECK: [[b]] = move [[btmp]]; - // CHECK: [[c:_.*]] = (*[[b]]); + // CHECK: [[c:_.*]] = copy (*[[b]]); let a = 5_usize; let a2 = 7_usize; @@ -49,7 +48,7 @@ fn reference_propagation<'a, T: Copy>(single: &'a T, mut multiple: &'a T) { // CHECK: [[a:_.*]] = const 5_usize; // CHECK: [[b:_.*]] = &[[a]]; // CHECK: [[d:_.*]] = &[[b]]; - // CHECK: [[c:_.*]] = [[a]]; + // CHECK: [[c:_.*]] = copy [[a]]; let a = 5_usize; let b = &a; @@ -64,7 +63,7 @@ fn reference_propagation<'a, T: Copy>(single: &'a T, mut multiple: &'a T) { // CHECK: [[a:_.*]] = const 5_usize; // CHECK: [[b:_.*]] = &[[a]]; // CHECK: [[d:_.*]] = &raw mut [[b]]; - // CHECK: [[c:_.*]] = (*[[b]]); + // CHECK: [[c:_.*]] = copy (*[[b]]); let a = 5_usize; let mut b = &a; @@ -78,7 +77,7 @@ fn reference_propagation<'a, T: Copy>(single: &'a T, mut multiple: &'a T) { // CHECK: bb4: { // CHECK: [[a:_.*]] = const 7_usize; // CHECK: [[b:_.*]] = &[[a]]; - // CHECK: [[c:_.*]] = [[a]]; + // CHECK: [[c:_.*]] = copy [[a]]; let a = 7_usize; let b = &a; @@ -91,10 +90,10 @@ fn reference_propagation<'a, T: Copy>(single: &'a T, mut multiple: &'a T) { // CHECK: bb5: { // CHECK: [[a:_.*]] = const 7_usize; // CHECK: [[b1:_.*]] = &[[a]]; - // CHECK: [[c:_.*]] = [[a]]; - // CHECK: [[b2:_.*]] = [[b1]]; - // CHECK: [[c2:_.*]] = [[a]]; - // CHECK: [[b3:_.*]] = [[b2]]; + // CHECK: [[c:_.*]] = copy [[a]]; + // CHECK: [[b2:_.*]] = copy [[b1]]; + // CHECK: [[c2:_.*]] = copy [[a]]; + // CHECK: [[b3:_.*]] = copy [[b2]]; let a = 7_usize; let b1 = &a; @@ -111,7 +110,7 @@ fn reference_propagation<'a, T: Copy>(single: &'a T, mut multiple: &'a T) { { // CHECK: bb6: { // CHECK-NOT: {{_.*}} = &(*_1); - // CHECK: [[b:_.*]] = (*_1); + // CHECK: [[b:_.*]] = copy (*_1); let a = &*single; let b = *a; // This should be optimized as `*single`. @@ -124,7 +123,7 @@ fn reference_propagation<'a, T: Copy>(single: &'a T, mut multiple: &'a T) { // CHECK: [[a:_.*]] = &(*_2); // CHECK: [[tmp:_.*]] = &(*_1); // CHECK: _2 = move [[tmp]]; - // CHECK: [[b:_.*]] = (*[[a]]); + // CHECK: [[b:_.*]] = copy (*[[a]]); let a = &*multiple; multiple = &*single; @@ -138,7 +137,7 @@ fn reference_propagation<'a, T: Copy>(single: &'a T, mut multiple: &'a T) { // CHECK: [[a:_.*]] = const 5_usize; // CHECK: [[b:_.*]] = &[[a]]; // CHECK: [[d:_.*]] = &[[b]]; - // CHECK: [[c:_.*]] = [[a]]; + // CHECK: [[c:_.*]] = copy [[a]]; let a = 5_usize; let b = &a; @@ -154,7 +153,7 @@ fn reference_propagation<'a, T: Copy>(single: &'a T, mut multiple: &'a T) { // CHECK: [[b:_.*]] = &[[a]]; // CHECK: [[d:_.*]] = &mut [[b]]; // FIXME this could be [[a]] - // CHECK: [[c:_.*]] = (*[[b]]); + // CHECK: [[c:_.*]] = copy (*[[b]]); let a = 5_usize; let mut b = &a; @@ -172,7 +171,7 @@ fn reference_propagation_mut<'a, T: Copy>(single: &'a mut T, mut multiple: &'a m // CHECK: bb0: { // CHECK: [[a:_.*]] = const 5_usize; // CHECK: [[b:_.*]] = &mut [[a]]; - // CHECK: [[c:_.*]] = [[a]]; + // CHECK: [[c:_.*]] = copy [[a]]; let mut a = 5_usize; let b = &mut a; // This borrow is only used once. @@ -188,7 +187,7 @@ fn reference_propagation_mut<'a, T: Copy>(single: &'a mut T, mut multiple: &'a m // CHECK: [[b:_.*]] = &mut [[a]]; // CHECK: [[btmp:_.*]] = &mut [[a2]]; // CHECK: [[b]] = move [[btmp]]; - // CHECK: [[c:_.*]] = (*[[b]]); + // CHECK: [[c:_.*]] = copy (*[[b]]); let mut a = 5_usize; let mut a2 = 7_usize; @@ -205,7 +204,7 @@ fn reference_propagation_mut<'a, T: Copy>(single: &'a mut T, mut multiple: &'a m // CHECK: [[a:_.*]] = const 5_usize; // CHECK: [[b:_.*]] = &mut [[a]]; // CHECK: [[d:_.*]] = &[[b]]; - // CHECK: [[c:_.*]] = (*[[b]]); + // CHECK: [[c:_.*]] = copy (*[[b]]); let mut a = 5_usize; let b = &mut a; @@ -220,7 +219,7 @@ fn reference_propagation_mut<'a, T: Copy>(single: &'a mut T, mut multiple: &'a m // CHECK: [[a:_.*]] = const 5_usize; // CHECK: [[b:_.*]] = &mut [[a]]; // CHECK: [[d:_.*]] = &raw mut [[b]]; - // CHECK: [[c:_.*]] = (*[[b]]); + // CHECK: [[c:_.*]] = copy (*[[b]]); let mut a = 5_usize; let mut b = &mut a; @@ -234,7 +233,7 @@ fn reference_propagation_mut<'a, T: Copy>(single: &'a mut T, mut multiple: &'a m // CHECK: bb4: { // CHECK: [[a:_.*]] = const 7_usize; // CHECK: [[b:_.*]] = &mut [[a]]; - // CHECK: [[c:_.*]] = (*[[b]]); + // CHECK: [[c:_.*]] = copy (*[[b]]); let mut a = 7_usize; let b = &mut a; @@ -247,9 +246,9 @@ fn reference_propagation_mut<'a, T: Copy>(single: &'a mut T, mut multiple: &'a m // CHECK: bb5: { // CHECK: [[a:_.*]] = const 7_usize; // CHECK: [[b1:_.*]] = &mut [[a]]; - // CHECK: [[c:_.*]] = (*[[b1]]); + // CHECK: [[c:_.*]] = copy (*[[b1]]); // CHECK: [[b2:_.*]] = move [[b1]]; - // CHECK: [[c2:_.*]] = (*[[b2]]); + // CHECK: [[c2:_.*]] = copy (*[[b2]]); // CHECK: [[b3:_.*]] = move [[b2]]; let mut a = 7_usize; @@ -267,7 +266,7 @@ fn reference_propagation_mut<'a, T: Copy>(single: &'a mut T, mut multiple: &'a m { // CHECK: bb6: { // CHECK-NOT: {{_.*}} = &(*_1); - // CHECK: [[b:_.*]] = (*_1); + // CHECK: [[b:_.*]] = copy (*_1); let a = &mut *single; let b = *a; // This should be optimized as `*single`. @@ -280,7 +279,7 @@ fn reference_propagation_mut<'a, T: Copy>(single: &'a mut T, mut multiple: &'a m // CHECK: [[a:_.*]] = &mut (*_2); // CHECK: [[tmp:_.*]] = &mut (*_1); // CHECK: _2 = move [[tmp]]; - // CHECK: [[b:_.*]] = (*[[a]]); + // CHECK: [[b:_.*]] = copy (*[[a]]); let a = &mut *multiple; multiple = &mut *single; @@ -295,7 +294,7 @@ fn reference_propagation_mut<'a, T: Copy>(single: &'a mut T, mut multiple: &'a m // CHECK: [[b:_.*]] = &mut [[a]]; // CHECK: [[d:_.*]] = &[[b]]; // FIXME this could be [[a]] - // CHECK: [[c:_.*]] = (*[[b]]); + // CHECK: [[c:_.*]] = copy (*[[b]]); let mut a = 5_usize; let b = &mut a; @@ -311,7 +310,7 @@ fn reference_propagation_mut<'a, T: Copy>(single: &'a mut T, mut multiple: &'a m // CHECK: [[b:_.*]] = &mut [[a]]; // CHECK: [[d:_.*]] = &mut [[b]]; // FIXME this could be [[a]] - // CHECK: [[c:_.*]] = (*[[b]]); + // CHECK: [[c:_.*]] = copy (*[[b]]); let mut a = 5_usize; let mut b = &mut a; @@ -329,7 +328,7 @@ fn reference_propagation_const_ptr(single: *const T, mut multiple: *con // CHECK: bb0: { // CHECK: [[a:_.*]] = const 5_usize; // CHECK: [[b:_.*]] = &raw const [[a]]; - // CHECK: [[c:_.*]] = [[a]]; + // CHECK: [[c:_.*]] = copy [[a]]; let a = 5_usize; let b = &raw const a; // This borrow is only used once. @@ -345,7 +344,7 @@ fn reference_propagation_const_ptr(single: *const T, mut multiple: *con // CHECK: [[b:_.*]] = &raw const [[a]]; // CHECK: [[btmp:_.*]] = &raw const [[a2]]; // CHECK: [[b]] = move [[btmp]]; - // CHECK: [[c:_.*]] = (*[[b]]); + // CHECK: [[c:_.*]] = copy (*[[b]]); let a = 5_usize; let a2 = 7_usize; @@ -362,7 +361,7 @@ fn reference_propagation_const_ptr(single: *const T, mut multiple: *con // CHECK: [[a:_.*]] = const 5_usize; // CHECK: [[b:_.*]] = &raw const [[a]]; // CHECK: [[d:_.*]] = &[[b]]; - // CHECK: [[c:_.*]] = [[a]]; + // CHECK: [[c:_.*]] = copy [[a]]; let a = 5_usize; let b = &raw const a; @@ -377,7 +376,7 @@ fn reference_propagation_const_ptr(single: *const T, mut multiple: *con // CHECK: [[a:_.*]] = const 5_usize; // CHECK: [[b:_.*]] = &raw const [[a]]; // CHECK: [[d:_.*]] = &raw mut [[b]]; - // CHECK: [[c:_.*]] = (*[[b]]); + // CHECK: [[c:_.*]] = copy (*[[b]]); let a = 5_usize; let mut b = &raw const a; @@ -391,7 +390,7 @@ fn reference_propagation_const_ptr(single: *const T, mut multiple: *con // CHECK: bb4: { // CHECK: [[a:_.*]] = const 7_usize; // CHECK: [[b:_.*]] = &raw const [[a]]; - // CHECK: [[c:_.*]] = [[a]]; + // CHECK: [[c:_.*]] = copy [[a]]; let a = 7_usize; let b = &raw const a; @@ -404,10 +403,10 @@ fn reference_propagation_const_ptr(single: *const T, mut multiple: *con // CHECK: bb5: { // CHECK: [[a:_.*]] = const 7_usize; // CHECK: [[b1:_.*]] = &raw const [[a]]; - // CHECK: [[c:_.*]] = [[a]]; - // CHECK: [[b2:_.*]] = [[b1]]; - // CHECK: [[c2:_.*]] = [[a]]; - // CHECK: [[b3:_.*]] = [[b2]]; + // CHECK: [[c:_.*]] = copy [[a]]; + // CHECK: [[b2:_.*]] = copy [[b1]]; + // CHECK: [[c2:_.*]] = copy [[a]]; + // CHECK: [[b3:_.*]] = copy [[b2]]; let a = 7_usize; let b1 = &raw const a; @@ -424,7 +423,7 @@ fn reference_propagation_const_ptr(single: *const T, mut multiple: *con unsafe { // CHECK: bb6: { // CHECK-NOT: {{_.*}} = &(*_1); - // CHECK: [[b:_.*]] = (*_1); + // CHECK: [[b:_.*]] = copy (*_1); let a = &raw const *single; let b = *a; // This should be optimized as `*single`. @@ -437,7 +436,7 @@ fn reference_propagation_const_ptr(single: *const T, mut multiple: *con // CHECK: [[a:_.*]] = &raw const (*_2); // CHECK: [[tmp:_.*]] = &raw const (*_1); // CHECK: _2 = move [[tmp]]; - // CHECK: [[b:_.*]] = (*[[a]]); + // CHECK: [[b:_.*]] = copy (*[[a]]); let a = &raw const *multiple; multiple = &raw const *single; @@ -451,7 +450,7 @@ fn reference_propagation_const_ptr(single: *const T, mut multiple: *con // CHECK: [[a:_.*]] = const 13_usize; // CHECK: [[b:_.*]] = &raw const [[a]]; // CHECK: [[d:_.*]] = &raw const [[a]]; - // CHECK: [[c:_.*]] = [[a]]; + // CHECK: [[c:_.*]] = copy [[a]]; let a = 13_usize; let b = &raw const a; @@ -466,7 +465,7 @@ fn reference_propagation_const_ptr(single: *const T, mut multiple: *con // CHECK: [[a:_.*]] = const 5_usize; // CHECK: [[b:_.*]] = &raw const [[a]]; // CHECK: [[d:_.*]] = &[[b]]; - // CHECK: [[c:_.*]] = [[a]]; + // CHECK: [[c:_.*]] = copy [[a]]; let a = 5_usize; let b = &raw const a; @@ -482,7 +481,7 @@ fn reference_propagation_const_ptr(single: *const T, mut multiple: *con // CHECK: [[b:_.*]] = &raw const [[a]]; // CHECK: [[d:_.*]] = &mut [[b]]; // FIXME this could be [[a]] - // CHECK: [[c:_.*]] = (*[[b]]); + // CHECK: [[c:_.*]] = copy (*[[b]]); let a = 5_usize; let mut b = &raw const a; @@ -500,7 +499,7 @@ fn reference_propagation_mut_ptr(single: *mut T, mut multiple: *mut T) // CHECK: bb0: { // CHECK: [[a:_.*]] = const 5_usize; // CHECK: [[b:_.*]] = &raw mut [[a]]; - // CHECK: [[c:_.*]] = [[a]]; + // CHECK: [[c:_.*]] = copy [[a]]; let mut a = 5_usize; let b = &raw mut a; // This borrow is only used once. @@ -516,7 +515,7 @@ fn reference_propagation_mut_ptr(single: *mut T, mut multiple: *mut T) // CHECK: [[b:_.*]] = &raw mut [[a]]; // CHECK: [[btmp:_.*]] = &raw mut [[a2]]; // CHECK: [[b]] = move [[btmp]]; - // CHECK: [[c:_.*]] = (*[[b]]); + // CHECK: [[c:_.*]] = copy (*[[b]]); let mut a = 5_usize; let mut a2 = 7_usize; @@ -533,7 +532,7 @@ fn reference_propagation_mut_ptr(single: *mut T, mut multiple: *mut T) // CHECK: [[a:_.*]] = const 5_usize; // CHECK: [[b:_.*]] = &raw mut [[a]]; // CHECK: [[d:_.*]] = &[[b]]; - // CHECK: [[c:_.*]] = (*[[b]]); + // CHECK: [[c:_.*]] = copy (*[[b]]); let mut a = 5_usize; let b = &raw mut a; @@ -548,7 +547,7 @@ fn reference_propagation_mut_ptr(single: *mut T, mut multiple: *mut T) // CHECK: [[a:_.*]] = const 5_usize; // CHECK: [[b:_.*]] = &raw mut [[a]]; // CHECK: [[d:_.*]] = &raw mut [[b]]; - // CHECK: [[c:_.*]] = (*[[b]]); + // CHECK: [[c:_.*]] = copy (*[[b]]); let mut a = 5_usize; let mut b = &raw mut a; @@ -562,7 +561,7 @@ fn reference_propagation_mut_ptr(single: *mut T, mut multiple: *mut T) // CHECK: bb4: { // CHECK: [[a:_.*]] = const 7_usize; // CHECK: [[b:_.*]] = &raw mut [[a]]; - // CHECK: [[c:_.*]] = (*[[b]]); + // CHECK: [[c:_.*]] = copy (*[[b]]); let mut a = 7_usize; let b = &raw mut a; @@ -575,10 +574,10 @@ fn reference_propagation_mut_ptr(single: *mut T, mut multiple: *mut T) // CHECK: bb5: { // CHECK: [[a:_.*]] = const 7_usize; // CHECK: [[b1:_.*]] = &raw mut [[a]]; - // CHECK: [[c:_.*]] = (*[[b1]]); - // CHECK: [[b2:_.*]] = [[b1]]; - // CHECK: [[c2:_.*]] = (*[[b2]]); - // CHECK: [[b3:_.*]] = [[b2]]; + // CHECK: [[c:_.*]] = copy (*[[b1]]); + // CHECK: [[b2:_.*]] = copy [[b1]]; + // CHECK: [[c2:_.*]] = copy (*[[b2]]); + // CHECK: [[b3:_.*]] = copy [[b2]]; let mut a = 7_usize; let b1 = &raw mut a; @@ -595,7 +594,7 @@ fn reference_propagation_mut_ptr(single: *mut T, mut multiple: *mut T) unsafe { // CHECK: bb6: { // CHECK-NOT: {{_.*}} = &(*_1); - // CHECK: [[b:_.*]] = (*_1); + // CHECK: [[b:_.*]] = copy (*_1); let a = &raw mut *single; let b = *a; // This should be optimized as `*single`. @@ -608,7 +607,7 @@ fn reference_propagation_mut_ptr(single: *mut T, mut multiple: *mut T) // CHECK: [[a:_.*]] = &raw mut (*_2); // CHECK: [[tmp:_.*]] = &raw mut (*_1); // CHECK: _2 = move [[tmp]]; - // CHECK: [[b:_.*]] = (*[[a]]); + // CHECK: [[b:_.*]] = copy (*[[a]]); let a = &raw mut *multiple; multiple = &raw mut *single; @@ -623,7 +622,7 @@ fn reference_propagation_mut_ptr(single: *mut T, mut multiple: *mut T) // CHECK: [[b:_.*]] = &raw mut [[a]]; // CHECK: [[d:_.*]] = &[[b]]; // FIXME this could be [[a]] - // CHECK: [[c:_.*]] = (*[[b]]); + // CHECK: [[c:_.*]] = copy (*[[b]]); let mut a = 5_usize; let b = &raw mut a; @@ -639,7 +638,7 @@ fn reference_propagation_mut_ptr(single: *mut T, mut multiple: *mut T) // CHECK: [[b:_.*]] = &raw mut [[a]]; // CHECK: [[d:_.*]] = &mut [[b]]; // FIXME this could be [[a]] - // CHECK: [[c:_.*]] = (*[[b]]); + // CHECK: [[c:_.*]] = copy (*[[b]]); let mut a = 5_usize; let mut b = &raw mut a; @@ -653,8 +652,8 @@ fn reference_propagation_mut_ptr(single: *mut T, mut multiple: *mut T) fn read_through_raw(x: &mut usize) -> usize { // CHECK-LABEL: read_through_raw // CHECK: bb0: { - // CHECK-NEXT: _0 = (*_1); - // CHECK-NEXT: _0 = (*_1); + // CHECK-NEXT: _0 = copy (*_1); + // CHECK-NEXT: _0 = copy (*_1); // CHECK-NEXT: return; use std::intrinsics::mir::*; @@ -680,7 +679,7 @@ fn read_through_raw(x: &mut usize) -> usize { #[custom_mir(dialect = "runtime", phase = "post-cleanup")] fn multiple_storage() { // CHECK-LABEL: multiple_storage - // CHECK: _3 = (*_2); + // CHECK: _3 = copy (*_2); use std::intrinsics::mir::*; mir! { @@ -706,7 +705,7 @@ fn multiple_storage() { #[custom_mir(dialect = "runtime", phase = "post-cleanup")] fn dominate_storage() { // CHECK-LABEL: dominate_storage - // CHECK: _5 = (*_2); + // CHECK: _5 = copy (*_2); use std::intrinsics::mir::*; mir! { @@ -798,12 +797,12 @@ fn unique_with_copies() { // CHECK: [[a:_.*]] = const 0_i32; // CHECK: [[x:_.*]] = &raw mut [[a]]; // CHECK-NOT: [[a]] - // CHECK: [[tmp:_.*]] = (*[[x]]); + // CHECK: [[tmp:_.*]] = copy (*[[x]]); // CHECK-NEXT: opaque::(move [[tmp]]) // CHECK-NOT: [[a]] // CHECK: StorageDead([[a]]); // CHECK-NOT: [[a]] - // CHECK: [[tmp:_.*]] = (*[[x]]); + // CHECK: [[tmp:_.*]] = copy (*[[x]]); // CHECK-NEXT: opaque::(move [[tmp]]) let y = { diff --git a/tests/mir-opt/reference_prop.unique_with_copies.ReferencePropagation.diff b/tests/mir-opt/reference_prop.unique_with_copies.ReferencePropagation.diff index a5427cea1f8..d2ba9db2b89 100644 --- a/tests/mir-opt/reference_prop.unique_with_copies.ReferencePropagation.diff +++ b/tests/mir-opt/reference_prop.unique_with_copies.ReferencePropagation.diff @@ -29,20 +29,20 @@ _3 = &raw mut _2; StorageLive(_4); StorageLive(_5); - _5 = (*_3); + _5 = copy (*_3); _4 = opaque::(move _5) -> [return: bb1, unwind continue]; } bb1: { StorageDead(_5); StorageDead(_4); -- _1 = _3; +- _1 = copy _3; - StorageDead(_3); StorageDead(_2); StorageLive(_6); StorageLive(_7); -- _7 = (*_1); -+ _7 = (*_3); +- _7 = copy (*_1); ++ _7 = copy (*_3); _6 = opaque::(move _7) -> [return: bb2, unwind continue]; } diff --git a/tests/mir-opt/remove_fake_borrows.match_guard.CleanupPostBorrowck.panic-abort.diff b/tests/mir-opt/remove_fake_borrows.match_guard.CleanupPostBorrowck.panic-abort.diff index d76d65a18a7..8c6c5e0d993 100644 --- a/tests/mir-opt/remove_fake_borrows.match_guard.CleanupPostBorrowck.panic-abort.diff +++ b/tests/mir-opt/remove_fake_borrows.match_guard.CleanupPostBorrowck.panic-abort.diff @@ -24,7 +24,7 @@ } bb2: { - switchInt((*(*((_1 as Some).0: &&i32)))) -> [0: bb3, otherwise: bb1]; + switchInt(copy (*(*((_1 as Some).0: &&i32)))) -> [0: bb3, otherwise: bb1]; } bb3: { @@ -42,7 +42,7 @@ + nop; + nop; StorageLive(_8); - _8 = _2; + _8 = copy _2; switchInt(move _8) -> [0: bb6, otherwise: bb5]; } diff --git a/tests/mir-opt/remove_fake_borrows.match_guard.CleanupPostBorrowck.panic-unwind.diff b/tests/mir-opt/remove_fake_borrows.match_guard.CleanupPostBorrowck.panic-unwind.diff index d76d65a18a7..8c6c5e0d993 100644 --- a/tests/mir-opt/remove_fake_borrows.match_guard.CleanupPostBorrowck.panic-unwind.diff +++ b/tests/mir-opt/remove_fake_borrows.match_guard.CleanupPostBorrowck.panic-unwind.diff @@ -24,7 +24,7 @@ } bb2: { - switchInt((*(*((_1 as Some).0: &&i32)))) -> [0: bb3, otherwise: bb1]; + switchInt(copy (*(*((_1 as Some).0: &&i32)))) -> [0: bb3, otherwise: bb1]; } bb3: { @@ -42,7 +42,7 @@ + nop; + nop; StorageLive(_8); - _8 = _2; + _8 = copy _2; switchInt(move _8) -> [0: bb6, otherwise: bb5]; } diff --git a/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.panic-abort.diff b/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.panic-abort.diff index 14762b9c40f..38cdbf5684b 100644 --- a/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.panic-abort.diff +++ b/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.panic-abort.diff @@ -64,10 +64,10 @@ bb5: { - StorageLive(_12); - _12 = ((_7 as Some).0: i32); + _12 = copy ((_7 as Some).0: i32); - StorageLive(_13); - _13 = _12; - _1 = Add(_1, move _13); + _13 = copy _12; + _1 = Add(copy _1, move _13); - StorageDead(_13); _6 = const (); - StorageDead(_12); diff --git a/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.panic-unwind.diff b/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.panic-unwind.diff index 24797424b5c..2b5aaa95fe1 100644 --- a/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.panic-unwind.diff +++ b/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.panic-unwind.diff @@ -64,10 +64,10 @@ bb5: { - StorageLive(_12); - _12 = ((_7 as Some).0: i32); + _12 = copy ((_7 as Some).0: i32); - StorageLive(_13); - _13 = _12; - _1 = Add(_1, move _13); + _13 = copy _12; + _1 = Add(copy _1, move _13); - StorageDead(_13); _6 = const (); - StorageDead(_12); diff --git a/tests/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.panic-abort.diff b/tests/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.panic-abort.diff index 5afeb8620a1..01eb6d4901f 100644 --- a/tests/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.panic-abort.diff +++ b/tests/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.panic-abort.diff @@ -12,7 +12,7 @@ bb0: { - nop; StorageLive(_3); - _3 = _1; + _3 = copy _1; - drop(_3) -> [return: bb1, unwind unreachable]; - } - diff --git a/tests/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.panic-unwind.diff b/tests/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.panic-unwind.diff index b9919ddea56..c2c3cb76e83 100644 --- a/tests/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.panic-unwind.diff +++ b/tests/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.panic-unwind.diff @@ -12,7 +12,7 @@ bb0: { - nop; StorageLive(_3); - _3 = _1; + _3 = copy _1; - drop(_3) -> [return: bb1, unwind continue]; - } - diff --git a/tests/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.panic-abort.diff b/tests/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.panic-abort.diff index b89432dd6d6..a82ede6196e 100644 --- a/tests/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.panic-abort.diff +++ b/tests/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.panic-abort.diff @@ -12,7 +12,7 @@ bb0: { - nop; StorageLive(_3); - _3 = _1; + _3 = copy _1; - drop(_3) -> [return: bb1, unwind unreachable]; - } - diff --git a/tests/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.panic-unwind.diff b/tests/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.panic-unwind.diff index 48d02605332..6e7c9ead740 100644 --- a/tests/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.panic-unwind.diff +++ b/tests/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.panic-unwind.diff @@ -12,7 +12,7 @@ bb0: { - nop; StorageLive(_3); - _3 = _1; + _3 = copy _1; - drop(_3) -> [return: bb1, unwind continue]; - } - diff --git a/tests/mir-opt/retag.array_casts.SimplifyCfg-pre-optimizations.after.panic-abort.mir b/tests/mir-opt/retag.array_casts.SimplifyCfg-pre-optimizations.after.panic-abort.mir index 6dba667dd15..ae7b2cc0b6f 100644 --- a/tests/mir-opt/retag.array_casts.SimplifyCfg-pre-optimizations.after.panic-abort.mir +++ b/tests/mir-opt/retag.array_casts.SimplifyCfg-pre-optimizations.after.panic-abort.mir @@ -70,7 +70,7 @@ fn array_casts() -> () { StorageLive(_5); StorageLive(_6); StorageLive(_7); - _7 = _2; + _7 = copy _2; _6 = std::ptr::mut_ptr::::add(move _7, const 1_usize) -> [return: bb1, unwind unreachable]; } @@ -96,13 +96,13 @@ fn array_casts() -> () { StorageLive(_15); StorageLive(_16); StorageLive(_17); - _17 = _9; + _17 = copy _9; _16 = std::ptr::const_ptr::::add(move _17, const 1_usize) -> [return: bb2, unwind unreachable]; } bb2: { StorageDead(_17); - _15 = (*_16); + _15 = copy (*_16); _14 = &_15; StorageLive(_18); _34 = const array_casts::promoted[0]; @@ -113,16 +113,16 @@ fn array_casts() -> () { StorageDead(_18); StorageDead(_14); StorageLive(_20); - _20 = (_13.0: &usize); + _20 = copy (_13.0: &usize); Retag(_20); StorageLive(_21); - _21 = (_13.1: &usize); + _21 = copy (_13.1: &usize); Retag(_21); StorageLive(_22); StorageLive(_23); - _23 = (*_20); + _23 = copy (*_20); StorageLive(_24); - _24 = (*_21); + _24 = copy (*_21); _22 = Eq(move _23, move _24); switchInt(move _22) -> [0: bb4, otherwise: bb3]; } diff --git a/tests/mir-opt/retag.array_casts.SimplifyCfg-pre-optimizations.after.panic-unwind.mir b/tests/mir-opt/retag.array_casts.SimplifyCfg-pre-optimizations.after.panic-unwind.mir index fa812002e26..789bc342638 100644 --- a/tests/mir-opt/retag.array_casts.SimplifyCfg-pre-optimizations.after.panic-unwind.mir +++ b/tests/mir-opt/retag.array_casts.SimplifyCfg-pre-optimizations.after.panic-unwind.mir @@ -70,7 +70,7 @@ fn array_casts() -> () { StorageLive(_5); StorageLive(_6); StorageLive(_7); - _7 = _2; + _7 = copy _2; _6 = std::ptr::mut_ptr::::add(move _7, const 1_usize) -> [return: bb1, unwind continue]; } @@ -96,13 +96,13 @@ fn array_casts() -> () { StorageLive(_15); StorageLive(_16); StorageLive(_17); - _17 = _9; + _17 = copy _9; _16 = std::ptr::const_ptr::::add(move _17, const 1_usize) -> [return: bb2, unwind continue]; } bb2: { StorageDead(_17); - _15 = (*_16); + _15 = copy (*_16); _14 = &_15; StorageLive(_18); _34 = const array_casts::promoted[0]; @@ -113,16 +113,16 @@ fn array_casts() -> () { StorageDead(_18); StorageDead(_14); StorageLive(_20); - _20 = (_13.0: &usize); + _20 = copy (_13.0: &usize); Retag(_20); StorageLive(_21); - _21 = (_13.1: &usize); + _21 = copy (_13.1: &usize); Retag(_21); StorageLive(_22); StorageLive(_23); - _23 = (*_20); + _23 = copy (*_20); StorageLive(_24); - _24 = (*_21); + _24 = copy (*_21); _22 = Eq(move _23, move _24); switchInt(move _22) -> [0: bb4, otherwise: bb3]; } diff --git a/tests/mir-opt/retag.box_to_raw_mut.SimplifyCfg-pre-optimizations.after.panic-abort.mir b/tests/mir-opt/retag.box_to_raw_mut.SimplifyCfg-pre-optimizations.after.panic-abort.mir index 0e568f6a568..ca02e7b49cc 100644 --- a/tests/mir-opt/retag.box_to_raw_mut.SimplifyCfg-pre-optimizations.after.panic-abort.mir +++ b/tests/mir-opt/retag.box_to_raw_mut.SimplifyCfg-pre-optimizations.after.panic-abort.mir @@ -9,7 +9,7 @@ fn box_to_raw_mut(_1: &mut Box) -> *mut i32 { bb0: { Retag([fn entry] _1); _2 = deref_copy (*_1); - _3 = (((_2.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const i32); + _3 = copy (((_2.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const i32); _0 = &raw mut (*_3); Retag([raw] _0); return; diff --git a/tests/mir-opt/retag.box_to_raw_mut.SimplifyCfg-pre-optimizations.after.panic-unwind.mir b/tests/mir-opt/retag.box_to_raw_mut.SimplifyCfg-pre-optimizations.after.panic-unwind.mir index 0e568f6a568..ca02e7b49cc 100644 --- a/tests/mir-opt/retag.box_to_raw_mut.SimplifyCfg-pre-optimizations.after.panic-unwind.mir +++ b/tests/mir-opt/retag.box_to_raw_mut.SimplifyCfg-pre-optimizations.after.panic-unwind.mir @@ -9,7 +9,7 @@ fn box_to_raw_mut(_1: &mut Box) -> *mut i32 { bb0: { Retag([fn entry] _1); _2 = deref_copy (*_1); - _3 = (((_2.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const i32); + _3 = copy (((_2.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const i32); _0 = &raw mut (*_3); Retag([raw] _0); return; diff --git a/tests/mir-opt/retag.main-{closure#0}.SimplifyCfg-pre-optimizations.after.panic-abort.mir b/tests/mir-opt/retag.main-{closure#0}.SimplifyCfg-pre-optimizations.after.panic-abort.mir index 2620929e896..63b32ceb5c0 100644 --- a/tests/mir-opt/retag.main-{closure#0}.SimplifyCfg-pre-optimizations.after.panic-abort.mir +++ b/tests/mir-opt/retag.main-{closure#0}.SimplifyCfg-pre-optimizations.after.panic-abort.mir @@ -12,7 +12,7 @@ fn main::{closure#0}(_1: &{closure@main::{closure#0}}, _2: &i32) -> &i32 { Retag([fn entry] _1); Retag([fn entry] _2); StorageLive(_3); - _3 = _2; + _3 = copy _2; Retag(_3); _0 = &(*_2); StorageDead(_3); diff --git a/tests/mir-opt/retag.main-{closure#0}.SimplifyCfg-pre-optimizations.after.panic-unwind.mir b/tests/mir-opt/retag.main-{closure#0}.SimplifyCfg-pre-optimizations.after.panic-unwind.mir index 2620929e896..63b32ceb5c0 100644 --- a/tests/mir-opt/retag.main-{closure#0}.SimplifyCfg-pre-optimizations.after.panic-unwind.mir +++ b/tests/mir-opt/retag.main-{closure#0}.SimplifyCfg-pre-optimizations.after.panic-unwind.mir @@ -12,7 +12,7 @@ fn main::{closure#0}(_1: &{closure@main::{closure#0}}, _2: &i32) -> &i32 { Retag([fn entry] _1); Retag([fn entry] _2); StorageLive(_3); - _3 = _2; + _3 = copy _2; Retag(_3); _0 = &(*_2); StorageDead(_3); diff --git a/tests/mir-opt/retag.main.SimplifyCfg-pre-optimizations.after.panic-abort.mir b/tests/mir-opt/retag.main.SimplifyCfg-pre-optimizations.after.panic-abort.mir index a35af43cefd..d0f454e4569 100644 --- a/tests/mir-opt/retag.main.SimplifyCfg-pre-optimizations.after.panic-abort.mir +++ b/tests/mir-opt/retag.main.SimplifyCfg-pre-optimizations.after.panic-abort.mir @@ -93,7 +93,7 @@ fn main() -> () { StorageLive(_11); StorageLive(_12); _12 = &raw mut (*_10); - _11 = _12; + _11 = copy _12; StorageDead(_12); _2 = const (); StorageDead(_11); @@ -109,7 +109,7 @@ fn main() -> () { StorageDead(_14); StorageLive(_15); StorageLive(_16); - _16 = _13; + _16 = copy _13; StorageLive(_17); StorageLive(_18); _18 = &_1; @@ -150,7 +150,7 @@ fn main() -> () { StorageLive(_25); StorageLive(_26); _26 = &raw const (*_15); - _25 = _26; + _25 = copy _26; StorageDead(_26); StorageLive(_27); _27 = array_casts() -> [return: bb6, unwind unreachable]; diff --git a/tests/mir-opt/retag.main.SimplifyCfg-pre-optimizations.after.panic-unwind.mir b/tests/mir-opt/retag.main.SimplifyCfg-pre-optimizations.after.panic-unwind.mir index 2495719ec1c..685277d7a53 100644 --- a/tests/mir-opt/retag.main.SimplifyCfg-pre-optimizations.after.panic-unwind.mir +++ b/tests/mir-opt/retag.main.SimplifyCfg-pre-optimizations.after.panic-unwind.mir @@ -93,7 +93,7 @@ fn main() -> () { StorageLive(_11); StorageLive(_12); _12 = &raw mut (*_10); - _11 = _12; + _11 = copy _12; StorageDead(_12); _2 = const (); StorageDead(_11); @@ -109,7 +109,7 @@ fn main() -> () { StorageDead(_14); StorageLive(_15); StorageLive(_16); - _16 = _13; + _16 = copy _13; StorageLive(_17); StorageLive(_18); _18 = &_1; @@ -150,7 +150,7 @@ fn main() -> () { StorageLive(_25); StorageLive(_26); _26 = &raw const (*_15); - _25 = _26; + _25 = copy _26; StorageDead(_26); StorageLive(_27); _27 = array_casts() -> [return: bb6, unwind continue]; diff --git a/tests/mir-opt/retag.{impl#0}-foo_shr.SimplifyCfg-pre-optimizations.after.panic-abort.mir b/tests/mir-opt/retag.{impl#0}-foo_shr.SimplifyCfg-pre-optimizations.after.panic-abort.mir index 4f90413e38b..b873c5aabbf 100644 --- a/tests/mir-opt/retag.{impl#0}-foo_shr.SimplifyCfg-pre-optimizations.after.panic-abort.mir +++ b/tests/mir-opt/retag.{impl#0}-foo_shr.SimplifyCfg-pre-optimizations.after.panic-abort.mir @@ -8,7 +8,7 @@ fn ::foo_shr(_1: &Test, _2: &i32) -> &i32 { bb0: { Retag([fn entry] _1); Retag([fn entry] _2); - _0 = _2; + _0 = copy _2; Retag(_0); return; } diff --git a/tests/mir-opt/retag.{impl#0}-foo_shr.SimplifyCfg-pre-optimizations.after.panic-unwind.mir b/tests/mir-opt/retag.{impl#0}-foo_shr.SimplifyCfg-pre-optimizations.after.panic-unwind.mir index 4f90413e38b..b873c5aabbf 100644 --- a/tests/mir-opt/retag.{impl#0}-foo_shr.SimplifyCfg-pre-optimizations.after.panic-unwind.mir +++ b/tests/mir-opt/retag.{impl#0}-foo_shr.SimplifyCfg-pre-optimizations.after.panic-unwind.mir @@ -8,7 +8,7 @@ fn ::foo_shr(_1: &Test, _2: &i32) -> &i32 { bb0: { Retag([fn entry] _1); Retag([fn entry] _2); - _0 = _2; + _0 = copy _2; Retag(_0); return; } diff --git a/tests/mir-opt/separate_const_switch.identity.JumpThreading.diff b/tests/mir-opt/separate_const_switch.identity.JumpThreading.diff index 8dd904c7d7b..ce9d812701a 100644 --- a/tests/mir-opt/separate_const_switch.identity.JumpThreading.diff +++ b/tests/mir-opt/separate_const_switch.identity.JumpThreading.diff @@ -50,16 +50,16 @@ } bb2: { - _5 = ((_2 as Continue).0: i32); - _0 = Result::::Ok(_5); + _5 = copy ((_2 as Continue).0: i32); + _0 = Result::::Ok(copy _5); StorageDead(_2); return; } bb3: { - _4 = ((_2 as Break).0: std::result::Result); - _10 = ((_4 as Err).0: i32); - _0 = Result::::Err(_10); + _4 = copy ((_2 as Break).0: std::result::Result); + _10 = copy ((_4 as Err).0: i32); + _0 = Result::::Err(copy _10); StorageDead(_2); return; } @@ -74,9 +74,9 @@ } bb5: { - _8 = ((_1 as Err).0: i32); + _8 = copy ((_1 as Err).0: i32); StorageLive(_9); - _9 = Result::::Err(_8); + _9 = Result::::Err(copy _8); _2 = ControlFlow::, i32>::Break(move _9); StorageDead(_9); - goto -> bb4; @@ -84,8 +84,8 @@ } bb6: { - _7 = ((_1 as Ok).0: i32); - _2 = ControlFlow::, i32>::Continue(_7); + _7 = copy ((_1 as Ok).0: i32); + _2 = ControlFlow::, i32>::Continue(copy _7); goto -> bb4; + } + diff --git a/tests/mir-opt/separate_const_switch.too_complex.JumpThreading.diff b/tests/mir-opt/separate_const_switch.too_complex.JumpThreading.diff index f7495862992..c88c63e0c13 100644 --- a/tests/mir-opt/separate_const_switch.too_complex.JumpThreading.diff +++ b/tests/mir-opt/separate_const_switch.too_complex.JumpThreading.diff @@ -35,15 +35,15 @@ } bb2: { - _5 = ((_1 as Err).0: usize); - _2 = ControlFlow::::Break(_5); + _5 = copy ((_1 as Err).0: usize); + _2 = ControlFlow::::Break(copy _5); - goto -> bb4; + goto -> bb8; } bb3: { - _4 = ((_1 as Ok).0: i32); - _2 = ControlFlow::::Continue(_4); + _4 = copy ((_1 as Ok).0: i32); + _2 = ControlFlow::::Continue(copy _4); goto -> bb4; } @@ -55,15 +55,15 @@ bb5: { StorageLive(_8); - _8 = ((_2 as Break).0: usize); + _8 = copy ((_2 as Break).0: usize); _0 = const Option::::None; StorageDead(_8); goto -> bb7; } bb6: { - _7 = ((_2 as Continue).0: i32); - _0 = Option::::Some(_7); + _7 = copy ((_2 as Continue).0: i32); + _0 = Option::::Some(copy _7); goto -> bb7; } diff --git a/tests/mir-opt/set_no_discriminant.f.JumpThreading.diff b/tests/mir-opt/set_no_discriminant.f.JumpThreading.diff index bc28e81c9a8..3d9852aef65 100644 --- a/tests/mir-opt/set_no_discriminant.f.JumpThreading.diff +++ b/tests/mir-opt/set_no_discriminant.f.JumpThreading.diff @@ -10,7 +10,7 @@ _2 = E::::A; discriminant(_2) = 1; _1 = discriminant(_2); - switchInt(_1) -> [0: bb1, otherwise: bb2]; + switchInt(copy _1) -> [0: bb1, otherwise: bb2]; } bb1: { diff --git a/tests/mir-opt/set_no_discriminant.generic.JumpThreading.diff b/tests/mir-opt/set_no_discriminant.generic.JumpThreading.diff index 78bfeef3c64..c7af1638316 100644 --- a/tests/mir-opt/set_no_discriminant.generic.JumpThreading.diff +++ b/tests/mir-opt/set_no_discriminant.generic.JumpThreading.diff @@ -10,7 +10,7 @@ _2 = E::::A; discriminant(_2) = 1; _1 = discriminant(_2); - switchInt(_1) -> [0: bb1, otherwise: bb2]; + switchInt(copy _1) -> [0: bb1, otherwise: bb2]; } bb1: { diff --git a/tests/mir-opt/simplify_dead_blocks.assert_nonzero_nonmax.SimplifyCfg-after-unreachable-enum-branching.diff b/tests/mir-opt/simplify_dead_blocks.assert_nonzero_nonmax.SimplifyCfg-after-unreachable-enum-branching.diff index 4400cfaef81..9c8efab5c84 100644 --- a/tests/mir-opt/simplify_dead_blocks.assert_nonzero_nonmax.SimplifyCfg-after-unreachable-enum-branching.diff +++ b/tests/mir-opt/simplify_dead_blocks.assert_nonzero_nonmax.SimplifyCfg-after-unreachable-enum-branching.diff @@ -5,8 +5,8 @@ let mut _0: u8; bb0: { -- switchInt(_1) -> [0: bb3, 1: bb2, 255: bb3, otherwise: bb4]; -+ switchInt(_1) -> [0: bb2, 1: bb1, 255: bb2, otherwise: bb3]; +- switchInt(copy _1) -> [0: bb3, 1: bb2, 255: bb3, otherwise: bb4]; ++ switchInt(copy _1) -> [0: bb2, 1: bb1, 255: bb2, otherwise: bb3]; } bb1: { @@ -26,7 +26,7 @@ - bb4: { + bb3: { - _0 = _1; + _0 = copy _1; return; } } diff --git a/tests/mir-opt/simplify_dead_blocks.rs b/tests/mir-opt/simplify_dead_blocks.rs index b9a404fd35c..7f2134c6121 100644 --- a/tests/mir-opt/simplify_dead_blocks.rs +++ b/tests/mir-opt/simplify_dead_blocks.rs @@ -10,7 +10,7 @@ use std::intrinsics::mir::*; pub unsafe fn assert_nonzero_nonmax(x: u8) -> u8 { // CHECK-LABEL: fn assert_nonzero_nonmax( // CHECK: bb0: { - // CHECK-NEXT: switchInt({{.*}}) -> [0: [[unreachable:bb.*]], 1: [[retblock2:bb.*]], 255: [[unreachable:bb.*]], otherwise: [[retblock:bb.*]]]; + // CHECK-NEXT: switchInt(copy {{_[0-9]+}}) -> [0: [[unreachable:bb.*]], 1: [[retblock2:bb.*]], 255: [[unreachable:bb.*]], otherwise: [[retblock:bb.*]]]; // CHECK-NEXT: } // CHECK-NOT: _0 = const 1_u8; // CHECK: [[retblock2]]: { @@ -21,7 +21,7 @@ pub unsafe fn assert_nonzero_nonmax(x: u8) -> u8 { // CHECK-NEXT: unreachable; // CHECK-NEXT: } // CHECK: [[retblock]]: { - // CHECK-NEXT: _0 = _1; + // CHECK-NEXT: _0 = copy _1; // CHECK-NEXT: return; // CHECK-NEXT: } mir! { diff --git a/tests/mir-opt/simplify_locals.expose_provenance.SimplifyLocals-before-const-prop.diff b/tests/mir-opt/simplify_locals.expose_provenance.SimplifyLocals-before-const-prop.diff index cc5c642407e..420fb4270b2 100644 --- a/tests/mir-opt/simplify_locals.expose_provenance.SimplifyLocals-before-const-prop.diff +++ b/tests/mir-opt/simplify_locals.expose_provenance.SimplifyLocals-before-const-prop.diff @@ -10,7 +10,7 @@ bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; _2 = move _3 as usize (PointerExposeProvenance); StorageDead(_3); StorageDead(_2); diff --git a/tests/mir-opt/simplify_locals.t1.SimplifyLocals-before-const-prop.diff b/tests/mir-opt/simplify_locals.t1.SimplifyLocals-before-const-prop.diff index 526ff2f25cf..f05a3935d65 100644 --- a/tests/mir-opt/simplify_locals.t1.SimplifyLocals-before-const-prop.diff +++ b/tests/mir-opt/simplify_locals.t1.SimplifyLocals-before-const-prop.diff @@ -10,7 +10,7 @@ - StorageLive(_1); - StorageLive(_2); - _2 = &/*tls*/ mut X; -- _1 = (*_2); +- _1 = copy (*_2); - StorageDead(_2); - StorageDead(_1); _0 = const (); diff --git a/tests/mir-opt/simplify_locals.t3.SimplifyLocals-before-const-prop.diff b/tests/mir-opt/simplify_locals.t3.SimplifyLocals-before-const-prop.diff index 5d45d7ac781..a57c136e64d 100644 --- a/tests/mir-opt/simplify_locals.t3.SimplifyLocals-before-const-prop.diff +++ b/tests/mir-opt/simplify_locals.t3.SimplifyLocals-before-const-prop.diff @@ -13,7 +13,7 @@ - StorageLive(_3); - _3 = &/*tls*/ mut X; - _2 = &mut (*_3); -- _1 = (*_2); +- _1 = copy (*_2); - StorageDead(_3); - StorageDead(_2); - StorageDead(_1); diff --git a/tests/mir-opt/simplify_locals.t4.SimplifyLocals-before-const-prop.diff b/tests/mir-opt/simplify_locals.t4.SimplifyLocals-before-const-prop.diff index 4f4855dbaaf..118193fd4fd 100644 --- a/tests/mir-opt/simplify_locals.t4.SimplifyLocals-before-const-prop.diff +++ b/tests/mir-opt/simplify_locals.t4.SimplifyLocals-before-const-prop.diff @@ -10,7 +10,7 @@ StorageLive(_1); StorageLive(_2); _2 = &/*tls*/ mut X; - _1 = (*_2); + _1 = copy (*_2); _0 = Add(move _1, const 1_u32); StorageDead(_1); StorageDead(_2); diff --git a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff index c520a159f47..c363dfcbf70 100644 --- a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff +++ b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff @@ -33,7 +33,7 @@ bb2: { StorageLive(_6); - _6 = (((_1.0: std::option::Option) as Some).0: u8); + _6 = copy (((_1.0: std::option::Option) as Some).0: u8); StorageDead(_6); goto -> bb3; } diff --git a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff index 686581591fc..895b0067d2e 100644 --- a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff +++ b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff @@ -33,7 +33,7 @@ bb2: { StorageLive(_6); - _6 = (((_1.0: std::option::Option) as Some).0: u8); + _6 = copy (((_1.0: std::option::Option) as Some).0: u8); StorageDead(_6); goto -> bb3; } diff --git a/tests/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.panic-abort.diff b/tests/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.panic-abort.diff index 54d254ee374..58c265c5e60 100644 --- a/tests/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.panic-abort.diff +++ b/tests/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.panic-abort.diff @@ -51,7 +51,7 @@ - _5 = (move _6, move _7); + StorageLive(_8); + _8 = Temp { x: const 40_u8 }; -+ _7 = (_8.0: u8); ++ _7 = copy (_8.0: u8); + _6 = Add(move _7, const 2_u8); StorageDead(_7); - StorageDead(_6); @@ -67,7 +67,7 @@ - StorageLive(_10); - StorageLive(_11); - _11 = Temp { x: const 40_u8 }; -- _10 = (_11.0: u8); +- _10 = copy (_11.0: u8); - _9 = Add(move _10, const 2_u8); - StorageDead(_10); - _8 = use_u8(move _9) -> [return: bb2, unwind unreachable]; diff --git a/tests/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.panic-unwind.diff b/tests/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.panic-unwind.diff index a5d9bbc49af..748e1661c98 100644 --- a/tests/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.panic-unwind.diff +++ b/tests/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.panic-unwind.diff @@ -51,7 +51,7 @@ - _5 = (move _6, move _7); + StorageLive(_8); + _8 = Temp { x: const 40_u8 }; -+ _7 = (_8.0: u8); ++ _7 = copy (_8.0: u8); + _6 = Add(move _7, const 2_u8); StorageDead(_7); - StorageDead(_6); @@ -67,7 +67,7 @@ - StorageLive(_10); - StorageLive(_11); - _11 = Temp { x: const 40_u8 }; -- _10 = (_11.0: u8); +- _10 = copy (_11.0: u8); - _9 = Add(move _10, const 2_u8); - StorageDead(_10); - _8 = use_u8(move _9) -> [return: bb2, unwind continue]; diff --git a/tests/mir-opt/simplify_match.main.GVN.panic-abort.diff b/tests/mir-opt/simplify_match.main.GVN.panic-abort.diff index 33b36f660cb..9e798cbcac0 100644 --- a/tests/mir-opt/simplify_match.main.GVN.panic-abort.diff +++ b/tests/mir-opt/simplify_match.main.GVN.panic-abort.diff @@ -14,9 +14,9 @@ - StorageLive(_2); + nop; _2 = const false; -- _1 = _2; +- _1 = copy _2; - StorageDead(_2); -- switchInt(_1) -> [0: bb2, otherwise: bb1]; +- switchInt(copy _1) -> [0: bb2, otherwise: bb1]; + _1 = const false; + nop; + switchInt(const false) -> [0: bb2, otherwise: bb1]; diff --git a/tests/mir-opt/simplify_match.main.GVN.panic-unwind.diff b/tests/mir-opt/simplify_match.main.GVN.panic-unwind.diff index e5c3adff623..e243ff45ab0 100644 --- a/tests/mir-opt/simplify_match.main.GVN.panic-unwind.diff +++ b/tests/mir-opt/simplify_match.main.GVN.panic-unwind.diff @@ -14,9 +14,9 @@ - StorageLive(_2); + nop; _2 = const false; -- _1 = _2; +- _1 = copy _2; - StorageDead(_2); -- switchInt(_1) -> [0: bb2, otherwise: bb1]; +- switchInt(copy _1) -> [0: bb2, otherwise: bb1]; + _1 = const false; + nop; + switchInt(const false) -> [0: bb2, otherwise: bb1]; diff --git a/tests/mir-opt/single_use_consts.if_const_debug.SingleUseConsts.panic-abort.diff b/tests/mir-opt/single_use_consts.if_const_debug.SingleUseConsts.panic-abort.diff index ad1a2b300f2..0269c2cba20 100644 --- a/tests/mir-opt/single_use_consts.if_const_debug.SingleUseConsts.panic-abort.diff +++ b/tests/mir-opt/single_use_consts.if_const_debug.SingleUseConsts.panic-abort.diff @@ -22,7 +22,7 @@ bb1: { StorageDead(_2); StorageLive(_3); -- _3 = _1; +- _3 = copy _1; + _3 = const ::ASSOC_BOOL; switchInt(move _3) -> [0: bb3, otherwise: bb2]; } diff --git a/tests/mir-opt/single_use_consts.if_const_debug.SingleUseConsts.panic-unwind.diff b/tests/mir-opt/single_use_consts.if_const_debug.SingleUseConsts.panic-unwind.diff index 827a292e5d0..1285b8b33ba 100644 --- a/tests/mir-opt/single_use_consts.if_const_debug.SingleUseConsts.panic-unwind.diff +++ b/tests/mir-opt/single_use_consts.if_const_debug.SingleUseConsts.panic-unwind.diff @@ -22,7 +22,7 @@ bb1: { StorageDead(_2); StorageLive(_3); -- _3 = _1; +- _3 = copy _1; + _3 = const ::ASSOC_BOOL; switchInt(move _3) -> [0: bb3, otherwise: bb2]; } diff --git a/tests/mir-opt/single_use_consts.match_const.SingleUseConsts.panic-abort.diff b/tests/mir-opt/single_use_consts.match_const.SingleUseConsts.panic-abort.diff index 998b89919d1..354e0988a00 100644 --- a/tests/mir-opt/single_use_consts.match_const.SingleUseConsts.panic-abort.diff +++ b/tests/mir-opt/single_use_consts.match_const.SingleUseConsts.panic-abort.diff @@ -8,7 +8,7 @@ bb0: { StorageLive(_1); - _1 = const ::ASSOC_INT; -- switchInt(_1) -> [7: bb3, 42: bb2, otherwise: bb1]; +- switchInt(copy _1) -> [7: bb3, 42: bb2, otherwise: bb1]; + nop; + switchInt(const ::ASSOC_INT) -> [7: bb3, 42: bb2, otherwise: bb1]; } diff --git a/tests/mir-opt/single_use_consts.match_const.SingleUseConsts.panic-unwind.diff b/tests/mir-opt/single_use_consts.match_const.SingleUseConsts.panic-unwind.diff index 998b89919d1..354e0988a00 100644 --- a/tests/mir-opt/single_use_consts.match_const.SingleUseConsts.panic-unwind.diff +++ b/tests/mir-opt/single_use_consts.match_const.SingleUseConsts.panic-unwind.diff @@ -8,7 +8,7 @@ bb0: { StorageLive(_1); - _1 = const ::ASSOC_INT; -- switchInt(_1) -> [7: bb3, 42: bb2, otherwise: bb1]; +- switchInt(copy _1) -> [7: bb3, 42: bb2, otherwise: bb1]; + nop; + switchInt(const ::ASSOC_INT) -> [7: bb3, 42: bb2, otherwise: bb1]; } diff --git a/tests/mir-opt/single_use_consts.match_const_debug.SingleUseConsts.panic-abort.diff b/tests/mir-opt/single_use_consts.match_const_debug.SingleUseConsts.panic-abort.diff index 30f66ef6b82..5cf37dc97cb 100644 --- a/tests/mir-opt/single_use_consts.match_const_debug.SingleUseConsts.panic-abort.diff +++ b/tests/mir-opt/single_use_consts.match_const_debug.SingleUseConsts.panic-abort.diff @@ -20,7 +20,7 @@ bb1: { StorageDead(_2); -- switchInt(_1) -> [7: bb4, 42: bb3, otherwise: bb2]; +- switchInt(copy _1) -> [7: bb4, 42: bb3, otherwise: bb2]; + switchInt(const ::ASSOC_INT) -> [7: bb4, 42: bb3, otherwise: bb2]; } diff --git a/tests/mir-opt/single_use_consts.match_const_debug.SingleUseConsts.panic-unwind.diff b/tests/mir-opt/single_use_consts.match_const_debug.SingleUseConsts.panic-unwind.diff index ed12ad4b93e..bdcf086e8d9 100644 --- a/tests/mir-opt/single_use_consts.match_const_debug.SingleUseConsts.panic-unwind.diff +++ b/tests/mir-opt/single_use_consts.match_const_debug.SingleUseConsts.panic-unwind.diff @@ -20,7 +20,7 @@ bb1: { StorageDead(_2); -- switchInt(_1) -> [7: bb4, 42: bb3, otherwise: bb2]; +- switchInt(copy _1) -> [7: bb4, 42: bb3, otherwise: bb2]; + switchInt(const ::ASSOC_INT) -> [7: bb4, 42: bb3, otherwise: bb2]; } diff --git a/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir b/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir index 3a8b457a7a1..4d1eaa6ffe3 100644 --- a/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir +++ b/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir @@ -28,7 +28,7 @@ fn std::ptr::drop_in_place(_1: *mut [String]) -> () { } bb4 (cleanup): { - _5 = Eq(_3, _2); + _5 = Eq(copy _3, copy _2); switchInt(move _5) -> [0: bb3, otherwise: bb2]; } @@ -39,7 +39,7 @@ fn std::ptr::drop_in_place(_1: *mut [String]) -> () { } bb6: { - _7 = Eq(_3, _2); + _7 = Eq(copy _3, copy _2); switchInt(move _7) -> [0: bb5, otherwise: bb1]; } diff --git a/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff index 819f3f86d14..478dacc3276 100644 --- a/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff +++ b/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff @@ -75,8 +75,8 @@ - _5 = move (_1.0: std::result::Result, ::Err>); + _5 = move _29; StorageLive(_6); -- _6 = (_1.1: u32); -+ _6 = _30; +- _6 = copy (_1.1: u32); ++ _6 = copy _30; _7 = discriminant(_5); switchInt(move _7) -> [0: bb2, otherwise: bb7]; } @@ -171,7 +171,7 @@ } bb11: { - switchInt(_25) -> [0: bb10, otherwise: bb12]; + switchInt(copy _25) -> [0: bb10, otherwise: bb12]; } bb12: { diff --git a/tests/mir-opt/sroa/structs.constant.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/structs.constant.ScalarReplacementOfAggregates.diff index 5d21e793982..4da3eb0ed76 100644 --- a/tests/mir-opt/sroa/structs.constant.ScalarReplacementOfAggregates.diff +++ b/tests/mir-opt/sroa/structs.constant.ScalarReplacementOfAggregates.diff @@ -29,11 +29,11 @@ + _4 = move (_1.0: usize); + _5 = move (_1.1: u8); StorageLive(_2); -- _2 = (_1.0: usize); -+ _2 = _4; +- _2 = copy (_1.0: usize); ++ _2 = copy _4; StorageLive(_3); -- _3 = (_1.1: u8); -+ _3 = _5; +- _3 = copy (_1.1: u8); ++ _3 = copy _5; _0 = const (); StorageDead(_3); StorageDead(_2); diff --git a/tests/mir-opt/sroa/structs.copies.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/structs.copies.ScalarReplacementOfAggregates.diff index 3621338635e..cfc086d6596 100644 --- a/tests/mir-opt/sroa/structs.copies.ScalarReplacementOfAggregates.diff +++ b/tests/mir-opt/sroa/structs.copies.ScalarReplacementOfAggregates.diff @@ -43,38 +43,38 @@ bb0: { - StorageLive(_2); -- _2 = _1; +- _2 = copy _1; + StorageLive(_11); + StorageLive(_12); + StorageLive(_13); + StorageLive(_14); + nop; -+ _11 = (_1.0: u8); -+ _12 = (_1.1: ()); -+ _13 = (_1.2: &str); -+ _14 = (_1.3: std::option::Option); ++ _11 = copy (_1.0: u8); ++ _12 = copy (_1.1: ()); ++ _13 = copy (_1.2: &str); ++ _14 = copy (_1.3: std::option::Option); + nop; StorageLive(_3); -- _3 = (_2.0: u8); -+ _3 = _11; +- _3 = copy (_2.0: u8); ++ _3 = copy _11; StorageLive(_4); -- _4 = (_2.2: &str); +- _4 = copy (_2.2: &str); - StorageLive(_5); -- _5 = _2; -+ _4 = _13; +- _5 = copy _2; ++ _4 = copy _13; + StorageLive(_7); + StorageLive(_8); + StorageLive(_9); + StorageLive(_10); + nop; -+ _7 = _11; -+ _8 = _12; -+ _9 = _13; -+ _10 = _14; ++ _7 = copy _11; ++ _8 = copy _12; ++ _9 = copy _13; ++ _10 = copy _14; + nop; StorageLive(_6); -- _6 = (_5.1: ()); -+ _6 = _8; +- _6 = copy (_5.1: ()); ++ _6 = copy _8; _0 = const (); StorageDead(_6); - StorageDead(_5); diff --git a/tests/mir-opt/sroa/structs.enums.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/structs.enums.ScalarReplacementOfAggregates.diff index b5e39e63247..eda884de822 100644 --- a/tests/mir-opt/sroa/structs.enums.ScalarReplacementOfAggregates.diff +++ b/tests/mir-opt/sroa/structs.enums.ScalarReplacementOfAggregates.diff @@ -15,7 +15,7 @@ bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; _2 = Option::::Some(move _3); StorageDead(_3); _4 = discriminant(_2); @@ -24,8 +24,8 @@ bb1: { StorageLive(_5); - _5 = ((_2 as Some).0: usize); - _0 = _5; + _5 = copy ((_2 as Some).0: usize); + _0 = copy _5; StorageDead(_5); goto -> bb3; } diff --git a/tests/mir-opt/sroa/structs.flat.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/structs.flat.ScalarReplacementOfAggregates.diff index a84048365a4..77c7c1a9012 100644 --- a/tests/mir-opt/sroa/structs.flat.ScalarReplacementOfAggregates.diff +++ b/tests/mir-opt/sroa/structs.flat.ScalarReplacementOfAggregates.diff @@ -49,18 +49,18 @@ StorageDead(_7); StorageDead(_6); StorageLive(_1); -- _1 = (_5.0: u8); -+ _1 = _8; +- _1 = copy (_5.0: u8); ++ _1 = copy _8; StorageLive(_2); -- _2 = (_5.1: ()); -+ _2 = _9; +- _2 = copy (_5.1: ()); ++ _2 = copy _9; StorageLive(_3); -- _3 = (_5.2: &str); -+ _3 = _10; +- _3 = copy (_5.2: &str); ++ _3 = copy _10; StorageLive(_4); -- _4 = (_5.3: std::option::Option); +- _4 = copy (_5.3: std::option::Option); - StorageDead(_5); -+ _4 = _11; ++ _4 = copy _11; + StorageDead(_8); + StorageDead(_9); + StorageDead(_10); diff --git a/tests/mir-opt/sroa/structs.ref_copies.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/structs.ref_copies.ScalarReplacementOfAggregates.diff index 304bf2fb1a7..abe7cd78878 100644 --- a/tests/mir-opt/sroa/structs.ref_copies.ScalarReplacementOfAggregates.diff +++ b/tests/mir-opt/sroa/structs.ref_copies.ScalarReplacementOfAggregates.diff @@ -27,23 +27,23 @@ bb0: { - StorageLive(_2); -- _2 = (*_1); +- _2 = copy (*_1); + StorageLive(_5); + StorageLive(_6); + StorageLive(_7); + StorageLive(_8); + nop; -+ _5 = ((*_1).0: u8); -+ _6 = ((*_1).1: ()); -+ _7 = ((*_1).2: &str); -+ _8 = ((*_1).3: std::option::Option); ++ _5 = copy ((*_1).0: u8); ++ _6 = copy ((*_1).1: ()); ++ _7 = copy ((*_1).2: &str); ++ _8 = copy ((*_1).3: std::option::Option); + nop; StorageLive(_3); -- _3 = (_2.0: u8); -+ _3 = _5; +- _3 = copy (_2.0: u8); ++ _3 = copy _5; StorageLive(_4); -- _4 = (_2.2: &str); -+ _4 = _7; +- _4 = copy (_2.2: &str); ++ _4 = copy _7; _0 = const (); StorageDead(_4); StorageDead(_3); diff --git a/tests/mir-opt/sroa/structs.rs b/tests/mir-opt/sroa/structs.rs index a177dbf71cf..d5f13f8b009 100644 --- a/tests/mir-opt/sroa/structs.rs +++ b/tests/mir-opt/sroa/structs.rs @@ -31,8 +31,8 @@ pub fn enums(a: usize) -> usize { // CHECK: bb0: { // CHECK: [[enum]] = Option::::Some - // CHECK: _5 = (([[enum]] as Some).0: usize) - // CHECK: _0 = _5 + // CHECK: _5 = copy (([[enum]] as Some).0: usize) + // CHECK: _0 = copy _5 if let Some(a) = Some(a) { a } else { 0 } } @@ -51,13 +51,13 @@ pub fn structs(a: f32) -> f32 { // CHECK: bb0: { // CHECK-NOT: [[struct]] - // CHECK: [[a_tmp]] = _1; + // CHECK: [[a_tmp]] = copy _1; // CHECK-NOT: [[struct]] // CHECK: [[foo]] = const 0_usize; // CHECK-NOT: [[struct]] // CHECK: [[a_ret]] = move [[a_tmp]]; // CHECK-NOT: [[struct]] - // CHECK: _0 = [[a_ret]]; + // CHECK: _0 = copy [[a_ret]]; // CHECK-NOT: [[struct]] U { _foo: 0, a }.a } @@ -73,7 +73,7 @@ pub fn unions(a: f32) -> u32 { // CHECK: bb0: { // CHECK: [[union]] = Repr { - // CHECK: _0 = ([[union]].1: u32) + // CHECK: _0 = copy ([[union]].1: u32) unsafe { Repr { f: a }.u } } @@ -156,10 +156,10 @@ fn copies(x: Foo) { // CHECK: [[opt_isize:_[0-9]+]]: std::option::Option; // CHECK: bb0: { - // CHECK: [[byte]] = ([[external]].0 - // CHECK: [[unit]] = ([[external]].1 - // CHECK: [[str]] = ([[external]].2 - // CHECK: [[opt_isize]] = ([[external]].3 + // CHECK: [[byte]] = copy ([[external]].0 + // CHECK: [[unit]] = copy ([[external]].1 + // CHECK: [[str]] = copy ([[external]].2 + // CHECK: [[opt_isize]] = copy ([[external]].3 let y = x; let t = y.a; @@ -181,10 +181,10 @@ fn ref_copies(x: &Foo) { // CHECK: [[opt_isize:_[0-9]+]]: std::option::Option; // CHECK: bb0: { - // CHECK: [[byte]] = ((*[[external]]).0 - // CHECK: [[unit]] = ((*[[external]]).1 - // CHECK: [[str]] = ((*[[external]]).2 - // CHECK: [[opt_isize]] = ((*[[external]]).3 + // CHECK: [[byte]] = copy ((*[[external]]).0 + // CHECK: [[unit]] = copy ((*[[external]]).1 + // CHECK: [[str]] = copy ((*[[external]]).2 + // CHECK: [[opt_isize]] = copy ((*[[external]]).3 let y = *x; let t = y.a; diff --git a/tests/mir-opt/sroa/structs.structs.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/structs.structs.ScalarReplacementOfAggregates.diff index bf5c3e3bd03..fe9deabe940 100644 --- a/tests/mir-opt/sroa/structs.structs.ScalarReplacementOfAggregates.diff +++ b/tests/mir-opt/sroa/structs.structs.ScalarReplacementOfAggregates.diff @@ -15,15 +15,15 @@ + StorageLive(_5); + nop; StorageLive(_3); - _3 = _1; + _3 = copy _1; - _2 = U { _foo: const 0_usize, a: move _3 }; + _4 = const 0_usize; + _5 = move _3; + nop; StorageDead(_3); -- _0 = (_2.1: f32); +- _0 = copy (_2.1: f32); - StorageDead(_2); -+ _0 = _5; ++ _0 = copy _5; + StorageDead(_4); + StorageDead(_5); + nop; diff --git a/tests/mir-opt/sroa/structs.unions.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/structs.unions.ScalarReplacementOfAggregates.diff index 2f8dfcc5d63..115f163cda9 100644 --- a/tests/mir-opt/sroa/structs.unions.ScalarReplacementOfAggregates.diff +++ b/tests/mir-opt/sroa/structs.unions.ScalarReplacementOfAggregates.diff @@ -10,10 +10,10 @@ bb0: { StorageLive(_2); StorageLive(_3); - _3 = _1; + _3 = copy _1; _2 = Repr { f: move _3 }; StorageDead(_3); - _0 = (_2.1: u32); + _0 = copy (_2.1: u32); StorageDead(_2); return; } diff --git a/tests/mir-opt/storage_ranges.main.nll.0.mir b/tests/mir-opt/storage_ranges.main.nll.0.mir index 782efd5acc6..bc2dcfe0a64 100644 --- a/tests/mir-opt/storage_ranges.main.nll.0.mir +++ b/tests/mir-opt/storage_ranges.main.nll.0.mir @@ -43,7 +43,7 @@ fn main() -> () { StorageLive(_3); StorageLive(_4); StorageLive(_5); - _5 = _1; + _5 = copy _1; _4 = Option::::Some(move _5); StorageDead(_5); _3 = &_4; diff --git a/tests/mir-opt/switch_to_self.test.MatchBranchSimplification.diff b/tests/mir-opt/switch_to_self.test.MatchBranchSimplification.diff index c0b599e060b..fef708d9962 100644 --- a/tests/mir-opt/switch_to_self.test.MatchBranchSimplification.diff +++ b/tests/mir-opt/switch_to_self.test.MatchBranchSimplification.diff @@ -9,11 +9,11 @@ } bb1: { - switchInt(_1) -> [0: bb1, otherwise: bb2]; + switchInt(copy _1) -> [0: bb1, otherwise: bb2]; } bb2: { - switchInt(_1) -> [0: bb1, otherwise: bb2]; + switchInt(copy _1) -> [0: bb1, otherwise: bb2]; } } diff --git a/tests/mir-opt/tail_call_drops.f.ElaborateDrops.panic-abort.diff b/tests/mir-opt/tail_call_drops.f.ElaborateDrops.panic-abort.diff index 44673ea00a9..17c64d4baf0 100644 --- a/tests/mir-opt/tail_call_drops.f.ElaborateDrops.panic-abort.diff +++ b/tests/mir-opt/tail_call_drops.f.ElaborateDrops.panic-abort.diff @@ -102,7 +102,7 @@ + } + + bb14 (cleanup): { -+ switchInt(_8) -> [0: bb11, otherwise: bb13]; ++ switchInt(copy _8) -> [0: bb11, otherwise: bb13]; } } diff --git a/tests/mir-opt/tail_call_drops.f.ElaborateDrops.panic-unwind.diff b/tests/mir-opt/tail_call_drops.f.ElaborateDrops.panic-unwind.diff index a6d33a24595..58d8a87986d 100644 --- a/tests/mir-opt/tail_call_drops.f.ElaborateDrops.panic-unwind.diff +++ b/tests/mir-opt/tail_call_drops.f.ElaborateDrops.panic-unwind.diff @@ -103,7 +103,7 @@ + } + + bb14 (cleanup): { -+ switchInt(_8) -> [0: bb11, otherwise: bb13]; ++ switchInt(copy _8) -> [0: bb11, otherwise: bb13]; } } diff --git a/tests/mir-opt/tail_call_drops.f_with_arg.ElaborateDrops.panic-abort.diff b/tests/mir-opt/tail_call_drops.f_with_arg.ElaborateDrops.panic-abort.diff index c7df2bb2207..1a51601bc56 100644 --- a/tests/mir-opt/tail_call_drops.f_with_arg.ElaborateDrops.panic-abort.diff +++ b/tests/mir-opt/tail_call_drops.f_with_arg.ElaborateDrops.panic-abort.diff @@ -178,7 +178,7 @@ + } + + bb31 (cleanup): { -+ switchInt(_12) -> [0: bb26, otherwise: bb30]; ++ switchInt(copy _12) -> [0: bb26, otherwise: bb30]; } } diff --git a/tests/mir-opt/tail_call_drops.f_with_arg.ElaborateDrops.panic-unwind.diff b/tests/mir-opt/tail_call_drops.f_with_arg.ElaborateDrops.panic-unwind.diff index c7df2bb2207..1a51601bc56 100644 --- a/tests/mir-opt/tail_call_drops.f_with_arg.ElaborateDrops.panic-unwind.diff +++ b/tests/mir-opt/tail_call_drops.f_with_arg.ElaborateDrops.panic-unwind.diff @@ -178,7 +178,7 @@ + } + + bb31 (cleanup): { -+ switchInt(_12) -> [0: bb26, otherwise: bb30]; ++ switchInt(copy _12) -> [0: bb26, otherwise: bb30]; } } diff --git a/tests/mir-opt/unnamed-fields/field_access.bar.SimplifyCfg-initial.after.mir b/tests/mir-opt/unnamed-fields/field_access.bar.SimplifyCfg-initial.after.mir index f0311422c17..f1904e5d0f4 100644 --- a/tests/mir-opt/unnamed-fields/field_access.bar.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/unnamed-fields/field_access.bar.SimplifyCfg-initial.after.mir @@ -15,7 +15,7 @@ fn bar(_1: Bar) -> () { bb0: { StorageLive(_2); StorageLive(_3); - _3 = (_1.0: u8); + _3 = copy (_1.0: u8); _2 = access::(move _3) -> [return: bb1, unwind: bb5]; } @@ -24,7 +24,7 @@ fn bar(_1: Bar) -> () { StorageDead(_2); StorageLive(_4); StorageLive(_5); - _5 = ((_1.1: Bar::{anon_adt#0}).0: i8); + _5 = copy ((_1.1: Bar::{anon_adt#0}).0: i8); _4 = access::(move _5) -> [return: bb2, unwind: bb5]; } @@ -33,7 +33,7 @@ fn bar(_1: Bar) -> () { StorageDead(_4); StorageLive(_6); StorageLive(_7); - _7 = ((_1.1: Bar::{anon_adt#0}).1: bool); + _7 = copy ((_1.1: Bar::{anon_adt#0}).1: bool); _6 = access::(move _7) -> [return: bb3, unwind: bb5]; } @@ -42,7 +42,7 @@ fn bar(_1: Bar) -> () { StorageDead(_6); StorageLive(_8); StorageLive(_9); - _9 = (((_1.2: Bar::{anon_adt#1}).0: Bar::{anon_adt#1}::{anon_adt#0}).0: [u8; 1]); + _9 = copy (((_1.2: Bar::{anon_adt#1}).0: Bar::{anon_adt#1}::{anon_adt#0}).0: [u8; 1]); _8 = access::<[u8; 1]>(move _9) -> [return: bb4, unwind: bb5]; } diff --git a/tests/mir-opt/unnamed-fields/field_access.foo.SimplifyCfg-initial.after.mir b/tests/mir-opt/unnamed-fields/field_access.foo.SimplifyCfg-initial.after.mir index d48a969f06e..c279f590012 100644 --- a/tests/mir-opt/unnamed-fields/field_access.foo.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/unnamed-fields/field_access.foo.SimplifyCfg-initial.after.mir @@ -15,7 +15,7 @@ fn foo(_1: Foo) -> () { bb0: { StorageLive(_2); StorageLive(_3); - _3 = (_1.0: u8); + _3 = copy (_1.0: u8); _2 = access::(move _3) -> [return: bb1, unwind: bb5]; } @@ -24,7 +24,7 @@ fn foo(_1: Foo) -> () { StorageDead(_2); StorageLive(_4); StorageLive(_5); - _5 = ((_1.1: Foo::{anon_adt#0}).0: i8); + _5 = copy ((_1.1: Foo::{anon_adt#0}).0: i8); _4 = access::(move _5) -> [return: bb2, unwind: bb5]; } @@ -33,7 +33,7 @@ fn foo(_1: Foo) -> () { StorageDead(_4); StorageLive(_6); StorageLive(_7); - _7 = ((_1.1: Foo::{anon_adt#0}).1: bool); + _7 = copy ((_1.1: Foo::{anon_adt#0}).1: bool); _6 = access::(move _7) -> [return: bb3, unwind: bb5]; } @@ -42,7 +42,7 @@ fn foo(_1: Foo) -> () { StorageDead(_6); StorageLive(_8); StorageLive(_9); - _9 = (((_1.2: Foo::{anon_adt#1}).0: Foo::{anon_adt#1}::{anon_adt#0}).0: [u8; 1]); + _9 = copy (((_1.2: Foo::{anon_adt#1}).0: Foo::{anon_adt#1}::{anon_adt#0}).0: [u8; 1]); _8 = access::<[u8; 1]>(move _9) -> [return: bb4, unwind: bb5]; } diff --git a/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-abort.diff b/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-abort.diff index 1e1ddfae0eb..17ddce0cdf8 100644 --- a/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-abort.diff +++ b/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-abort.diff @@ -20,7 +20,7 @@ bb1: { _2 = discriminant(_1); - switchInt(move _2) -> [1: bb3, otherwise: bb2]; -+ _5 = Ne(_2, const 1_isize); ++ _5 = Ne(copy _2, const 1_isize); + assume(move _5); + goto -> bb2; } diff --git a/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-unwind.diff b/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-unwind.diff index 809d24aa15a..2f78092f5bd 100644 --- a/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-unwind.diff +++ b/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-unwind.diff @@ -20,7 +20,7 @@ bb1: { _2 = discriminant(_1); - switchInt(move _2) -> [1: bb3, otherwise: bb2]; -+ _5 = Ne(_2, const 1_isize); ++ _5 = Ne(copy _2, const 1_isize); + assume(move _5); + goto -> bb2; } diff --git a/tests/mir-opt/unreachable.if_let.UnreachablePropagation.panic-abort.diff b/tests/mir-opt/unreachable.if_let.UnreachablePropagation.panic-abort.diff index 61959732720..2ce37c4422b 100644 --- a/tests/mir-opt/unreachable.if_let.UnreachablePropagation.panic-abort.diff +++ b/tests/mir-opt/unreachable.if_let.UnreachablePropagation.panic-abort.diff @@ -26,7 +26,7 @@ bb1: { _2 = discriminant(_1); - switchInt(move _2) -> [1: bb2, otherwise: bb6]; -+ _8 = Ne(_2, const 1_isize); ++ _8 = Ne(copy _2, const 1_isize); + assume(move _8); + goto -> bb6; } diff --git a/tests/mir-opt/unreachable.if_let.UnreachablePropagation.panic-unwind.diff b/tests/mir-opt/unreachable.if_let.UnreachablePropagation.panic-unwind.diff index 476e2f55994..2dfba10c37d 100644 --- a/tests/mir-opt/unreachable.if_let.UnreachablePropagation.panic-unwind.diff +++ b/tests/mir-opt/unreachable.if_let.UnreachablePropagation.panic-unwind.diff @@ -26,7 +26,7 @@ bb1: { _2 = discriminant(_1); - switchInt(move _2) -> [1: bb2, otherwise: bb6]; -+ _8 = Ne(_2, const 1_isize); ++ _8 = Ne(copy _2, const 1_isize); + assume(move _8); + goto -> bb6; } diff --git a/tests/mir-opt/unreachable_diverging.main.UnreachablePropagation.panic-abort.diff b/tests/mir-opt/unreachable_diverging.main.UnreachablePropagation.panic-abort.diff index 11d7924e736..ba268832ca3 100644 --- a/tests/mir-opt/unreachable_diverging.main.UnreachablePropagation.panic-abort.diff +++ b/tests/mir-opt/unreachable_diverging.main.UnreachablePropagation.panic-abort.diff @@ -35,9 +35,9 @@ _4 = move ((_2 as Some).0: Empty); StorageLive(_5); StorageLive(_6); - _6 = _1; + _6 = copy _1; - switchInt(move _6) -> [0: bb4, otherwise: bb3]; -+ _8 = Ne(_6, const false); ++ _8 = Ne(copy _6, const false); + assume(move _8); + goto -> bb3; } diff --git a/tests/mir-opt/unreachable_diverging.main.UnreachablePropagation.panic-unwind.diff b/tests/mir-opt/unreachable_diverging.main.UnreachablePropagation.panic-unwind.diff index df6f5609fbf..f057f776470 100644 --- a/tests/mir-opt/unreachable_diverging.main.UnreachablePropagation.panic-unwind.diff +++ b/tests/mir-opt/unreachable_diverging.main.UnreachablePropagation.panic-unwind.diff @@ -35,9 +35,9 @@ _4 = move ((_2 as Some).0: Empty); StorageLive(_5); StorageLive(_6); - _6 = _1; + _6 = copy _1; - switchInt(move _6) -> [0: bb4, otherwise: bb3]; -+ _8 = Ne(_6, const false); ++ _8 = Ne(copy _6, const false); + assume(move _8); + goto -> bb3; } diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-abort.diff index 4cd6d3f5683..17e01f38f4e 100644 --- a/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-abort.diff +++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-abort.diff @@ -29,7 +29,7 @@ } bb2: { - switchInt(((_2 as A).0: i32)) -> [1: bb6, 2: bb5, otherwise: bb1]; + switchInt(copy ((_2 as A).0: i32)) -> [1: bb6, 2: bb5, otherwise: bb1]; } bb3: { diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-unwind.diff index 4cd6d3f5683..17e01f38f4e 100644 --- a/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-unwind.diff +++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-unwind.diff @@ -29,7 +29,7 @@ } bb2: { - switchInt(((_2 as A).0: i32)) -> [1: bb6, 2: bb5, otherwise: bb1]; + switchInt(copy ((_2 as A).0: i32)) -> [1: bb6, 2: bb5, otherwise: bb1]; } bb3: { diff --git a/tests/pretty/raw-address-of.rs b/tests/pretty/raw-address-of.rs index 6e97ab99407..c00a16e238a 100644 --- a/tests/pretty/raw-address-of.rs +++ b/tests/pretty/raw-address-of.rs @@ -1,5 +1,4 @@ //@ pp-exact -#![feature(raw_ref_op)] const C_PTR: () = { let a = 1; &raw const a; }; static S_PTR: () = { let b = false; &raw const b; }; diff --git a/tests/run-make/rust-lld-compress-debug-sections/main.rs b/tests/run-make/compressed-debuginfo-zstd/main.rs similarity index 100% rename from tests/run-make/rust-lld-compress-debug-sections/main.rs rename to tests/run-make/compressed-debuginfo-zstd/main.rs diff --git a/tests/run-make/compressed-debuginfo-zstd/rmake.rs b/tests/run-make/compressed-debuginfo-zstd/rmake.rs new file mode 100644 index 00000000000..8356373e949 --- /dev/null +++ b/tests/run-make/compressed-debuginfo-zstd/rmake.rs @@ -0,0 +1,42 @@ +// Checks debuginfo compression both for the always-enabled zlib, and when the optional zstd is +// enabled: +// - via rustc's `debuginfo-compression`, +// - and via rust-lld's `compress-debug-sections` + +//@ needs-llvm-zstd: we want LLVM/LLD to be built with zstd support +//@ needs-rust-lld: the system linker will most likely not support zstd +//@ only-linux +//@ ignore-cross-compile + +use run_make_support::{llvm_readobj, run_in_tmpdir, Rustc}; + +fn check_compression(compression: &str, to_find: &str) { + // check compressed debug sections via rustc flag + prepare_and_check(to_find, |rustc| { + rustc.arg(&format!("-Zdebuginfo-compression={compression}")) + }); + + // check compressed debug sections via rust-lld flag + prepare_and_check(to_find, |rustc| { + rustc.link_arg(&format!("-Wl,--compress-debug-sections={compression}")) + }); +} + +fn prepare_and_check &mut Rustc>(to_find: &str, prepare_rustc: F) { + run_in_tmpdir(|| { + let mut rustc = Rustc::new(); + rustc + .arg("-Zlinker-features=+lld") + .arg("-Clink-self-contained=+linker") + .arg("-Zunstable-options") + .arg("-Cdebuginfo=full") + .input("main.rs"); + prepare_rustc(&mut rustc).run(); + llvm_readobj().arg("-t").arg("main").run().assert_stdout_contains(to_find); + }); +} + +fn main() { + check_compression("zlib", "ZLIB"); + check_compression("zstd", "ZSTD"); +} diff --git a/tests/run-make/crate-loading/multiple-dep-versions-1.rs b/tests/run-make/crate-loading/multiple-dep-versions-1.rs index 2d351633829..d81462504dd 100644 --- a/tests/run-make/crate-loading/multiple-dep-versions-1.rs +++ b/tests/run-make/crate-loading/multiple-dep-versions-1.rs @@ -1,6 +1,12 @@ #![crate_name = "dependency"] #![crate_type = "rlib"] -pub struct Type; -pub trait Trait {} -impl Trait for Type {} +pub struct Type(pub i32); +pub trait Trait { + fn foo(&self); + fn bar(); +} +impl Trait for Type { + fn foo(&self) {} + fn bar() {} +} pub fn do_something(_: X) {} diff --git a/tests/run-make/crate-loading/multiple-dep-versions-2.rs b/tests/run-make/crate-loading/multiple-dep-versions-2.rs index a5df3dc61ed..0a566fe2c60 100644 --- a/tests/run-make/crate-loading/multiple-dep-versions-2.rs +++ b/tests/run-make/crate-loading/multiple-dep-versions-2.rs @@ -1,6 +1,12 @@ #![crate_name = "dependency"] #![crate_type = "rlib"] -pub struct Type(pub i32); -pub trait Trait {} -impl Trait for Type {} +pub struct Type; +pub trait Trait { + fn foo(&self); + fn bar(); +} +impl Trait for Type { + fn foo(&self) {} + fn bar() {} +} pub fn do_something(_: X) {} diff --git a/tests/run-make/crate-loading/multiple-dep-versions-3.rs b/tests/run-make/crate-loading/multiple-dep-versions-3.rs new file mode 100644 index 00000000000..07d888e9f10 --- /dev/null +++ b/tests/run-make/crate-loading/multiple-dep-versions-3.rs @@ -0,0 +1,5 @@ +#![crate_name = "foo"] +#![crate_type = "rlib"] + +extern crate dependency; +pub use dependency::Type; diff --git a/tests/run-make/crate-loading/multiple-dep-versions.rs b/tests/run-make/crate-loading/multiple-dep-versions.rs index 5a6cb03aaa4..8ef042bf418 100644 --- a/tests/run-make/crate-loading/multiple-dep-versions.rs +++ b/tests/run-make/crate-loading/multiple-dep-versions.rs @@ -1,8 +1,10 @@ extern crate dep_2_reexport; extern crate dependency; -use dep_2_reexport::do_something; -use dependency::Type; +use dep_2_reexport::Type; +use dependency::{do_something, Trait}; fn main() { do_something(Type); + Type.foo(); + Type::bar(); } diff --git a/tests/run-make/crate-loading/rmake.rs b/tests/run-make/crate-loading/rmake.rs index d7abd5872c9..95a9011669e 100644 --- a/tests/run-make/crate-loading/rmake.rs +++ b/tests/run-make/crate-loading/rmake.rs @@ -1,26 +1,100 @@ //@ only-linux //@ ignore-wasm32 //@ ignore-wasm64 +// ignore-tidy-linelength use run_make_support::{rust_lib_name, rustc}; fn main() { rustc().input("multiple-dep-versions-1.rs").run(); rustc().input("multiple-dep-versions-2.rs").extra_filename("2").metadata("2").run(); + rustc() + .input("multiple-dep-versions-3.rs") + .extern_("dependency", rust_lib_name("dependency2")) + .run(); rustc() .input("multiple-dep-versions.rs") .extern_("dependency", rust_lib_name("dependency")) - .extern_("dep_2_reexport", rust_lib_name("dependency2")) + .extern_("dep_2_reexport", rust_lib_name("foo")) .run_fail() .assert_stderr_contains( - "you have multiple different versions of crate `dependency` in your dependency graph", + r#"error[E0277]: the trait bound `dep_2_reexport::Type: Trait` is not satisfied + --> multiple-dep-versions.rs:7:18 + | +7 | do_something(Type); + | ------------ ^^^^ the trait `Trait` is not implemented for `dep_2_reexport::Type` + | | + | required by a bound introduced by this call + | +help: there are multiple different versions of crate `dependency` in the dependency graph + --> multiple-dep-versions.rs:1:1 + | +1 | extern crate dep_2_reexport; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one version of crate `dependency` is used here, as a dependency of crate `foo` +2 | extern crate dependency; + | ^^^^^^^^^^^^^^^^^^^^^^^^ one version of crate `dependency` is used here, as a direct dependency of the current crate"#, ) .assert_stderr_contains( - "two types coming from two different versions of the same crate are different types \ - even if they look the same", + r#" +3 | pub struct Type(pub i32); + | ^^^^^^^^^^^^^^^ this type implements the required trait +4 | pub trait Trait { + | --------------- this is the required trait"#, ) - .assert_stderr_contains("this type doesn't implement the required trait") - .assert_stderr_contains("this type implements the required trait") - .assert_stderr_contains("this is the required trait"); + .assert_stderr_contains( + r#" +3 | pub struct Type; + | ^^^^^^^^^^^^^^^ this type doesn't implement the required trait"#, + ) + .assert_stderr_contains( + r#" +error[E0599]: no method named `foo` found for struct `dep_2_reexport::Type` in the current scope + --> multiple-dep-versions.rs:8:10 + | +8 | Type.foo(); + | ^^^ method not found in `Type` + | +note: there are multiple different versions of crate `dependency` in the dependency graph"#, + ) + .assert_stderr_contains( + r#" +4 | pub trait Trait { + | ^^^^^^^^^^^^^^^ this is the trait that is needed +5 | fn foo(&self); + | -------------- the method is available for `dep_2_reexport::Type` here + | + ::: multiple-dep-versions.rs:4:32 + | +4 | use dependency::{do_something, Trait}; + | ----- `Trait` imported here doesn't correspond to the right version of crate `dependency`"#, + ) + .assert_stderr_contains( + r#" +4 | pub trait Trait { + | --------------- this is the trait that was imported"#, + ) + .assert_stderr_contains( + r#" +error[E0599]: no function or associated item named `bar` found for struct `dep_2_reexport::Type` in the current scope + --> multiple-dep-versions.rs:9:11 + | +9 | Type::bar(); + | ^^^ function or associated item not found in `Type` + | +note: there are multiple different versions of crate `dependency` in the dependency graph"#, + ) + .assert_stderr_contains( + r#" +4 | pub trait Trait { + | ^^^^^^^^^^^^^^^ this is the trait that is needed +5 | fn foo(&self); +6 | fn bar(); + | --------- the associated function is available for `dep_2_reexport::Type` here + | + ::: multiple-dep-versions.rs:4:32 + | +4 | use dependency::{do_something, Trait}; + | ----- `Trait` imported here doesn't correspond to the right version of crate `dependency`"#, + ); } diff --git a/tests/run-make/debugger-visualizer-dep-info/foo.py b/tests/run-make/debugger-visualizer-dep-info/foo.py deleted file mode 100644 index 1bb8bf6d7fd..00000000000 --- a/tests/run-make/debugger-visualizer-dep-info/foo.py +++ /dev/null @@ -1 +0,0 @@ -# empty diff --git a/tests/run-make/debugger-visualizer-dep-info/main.rs b/tests/run-make/debugger-visualizer-dep-info/main.rs index 3aede2215ea..3539b305be3 100644 --- a/tests/run-make/debugger-visualizer-dep-info/main.rs +++ b/tests/run-make/debugger-visualizer-dep-info/main.rs @@ -1,4 +1,4 @@ -#![debugger_visualizer(gdb_script_file = "foo.py")] +#![debugger_visualizer(gdb_script_file = "my_gdb_script.py")] fn main() { const _UNUSED: u32 = { diff --git a/tests/run-make/debugger-visualizer-dep-info/my_gdb_script.py b/tests/run-make/debugger-visualizer-dep-info/my_gdb_script.py new file mode 100644 index 00000000000..d319792657e --- /dev/null +++ b/tests/run-make/debugger-visualizer-dep-info/my_gdb_script.py @@ -0,0 +1,6 @@ +# This is a Python script, but we don't actually run it. +# So if you're trying to remove Python scripts from the test suite, +# be aware that there's no value in trying to get rid of this one. +# +# It just needs to exist so that the compiler can embed it via +# `#![debugger_visualizer(gdb_script_file = "...")]`. diff --git a/tests/run-make/debugger-visualizer-dep-info/rmake.rs b/tests/run-make/debugger-visualizer-dep-info/rmake.rs index 65ffb2373e7..f5cf39157ac 100644 --- a/tests/run-make/debugger-visualizer-dep-info/rmake.rs +++ b/tests/run-make/debugger-visualizer-dep-info/rmake.rs @@ -6,6 +6,6 @@ use run_make_support::{invalid_utf8_contains, rustc}; fn main() { rustc().emit("dep-info").input("main.rs").run(); - invalid_utf8_contains("main.d", "foo.py"); + invalid_utf8_contains("main.d", "my_gdb_script.py"); invalid_utf8_contains("main.d", "my_visualizers/bar.natvis"); } diff --git a/tests/run-make/dep-info-doesnt-run-much/Makefile b/tests/run-make/dep-info-doesnt-run-much/Makefile deleted file mode 100644 index b4dc44ad2be..00000000000 --- a/tests/run-make/dep-info-doesnt-run-much/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -include ../tools.mk - -all: - $(RUSTC) foo.rs --emit dep-info diff --git a/tests/run-make/dep-info-spaces/Makefile b/tests/run-make/dep-info-spaces/Makefile deleted file mode 100644 index 0cfe513e490..00000000000 --- a/tests/run-make/dep-info-spaces/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -include ../tools.mk - -# ignore-windows -# ignore-freebsd -# FIXME: (windows: see `../dep-info/Makefile`) - -all: - cp lib.rs $(TMPDIR)/ - cp 'foo foo.rs' $(TMPDIR)/ - cp bar.rs $(TMPDIR)/ - $(RUSTC) --emit link,dep-info --crate-type=lib $(TMPDIR)/lib.rs - sleep 1 - touch $(TMPDIR)/'foo foo.rs' - -rm -f $(TMPDIR)/done - $(MAKE) -drf Makefile.foo - rm $(TMPDIR)/done - pwd - $(MAKE) -drf Makefile.foo - rm $(TMPDIR)/done && exit 1 || exit 0 diff --git a/tests/run-make/dep-info-spaces/Makefile.foo b/tests/run-make/dep-info-spaces/Makefile.foo deleted file mode 100644 index 80a5d4333cd..00000000000 --- a/tests/run-make/dep-info-spaces/Makefile.foo +++ /dev/null @@ -1,7 +0,0 @@ -LIB := $(shell $(RUSTC) --print file-names --crate-type=lib $(TMPDIR)/lib.rs) - -$(TMPDIR)/$(LIB): - $(RUSTC) --emit link,dep-info --crate-type=lib $(TMPDIR)/lib.rs - touch $(TMPDIR)/done - --include $(TMPDIR)/lib.d diff --git a/tests/run-make/dep-info-spaces/bar.rs b/tests/run-make/dep-info-spaces/bar.rs deleted file mode 100644 index c5c0bc606cd..00000000000 --- a/tests/run-make/dep-info-spaces/bar.rs +++ /dev/null @@ -1 +0,0 @@ -pub fn bar() {} diff --git a/tests/run-make/dep-info/Makefile b/tests/run-make/dep-info/Makefile deleted file mode 100644 index c76f43a8eed..00000000000 --- a/tests/run-make/dep-info/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -include ../tools.mk - -# ignore-windows -# ignore-freebsd -# FIXME: on windows `rustc --dep-info` produces Makefile dependency with -# windows native paths (e.g. `c:\path\to\libfoo.a`) -# but msys make seems to fail to recognize such paths, so test fails. - -all: - cp *.rs $(TMPDIR) - $(RUSTC) --emit dep-info,link --crate-type=lib $(TMPDIR)/lib.rs - sleep 2 - touch $(TMPDIR)/foo.rs - -rm -f $(TMPDIR)/done - $(MAKE) -drf Makefile.foo - sleep 2 - rm $(TMPDIR)/done - pwd - $(MAKE) -drf Makefile.foo - rm $(TMPDIR)/done && exit 1 || exit 0 - - # When a source file is deleted `make` should still work - rm $(TMPDIR)/bar.rs - cp $(TMPDIR)/lib2.rs $(TMPDIR)/lib.rs - $(MAKE) -drf Makefile.foo diff --git a/tests/run-make/dep-info/Makefile.foo b/tests/run-make/dep-info/Makefile.foo deleted file mode 100644 index e5df31f88c1..00000000000 --- a/tests/run-make/dep-info/Makefile.foo +++ /dev/null @@ -1,7 +0,0 @@ -LIB := $(shell $(RUSTC) --print file-names --crate-type=lib lib.rs) - -$(TMPDIR)/$(LIB): - $(RUSTC) --emit dep-info,link --crate-type=lib lib.rs - touch $(TMPDIR)/done - --include $(TMPDIR)/foo.d diff --git a/tests/run-make/dep-info-doesnt-run-much/foo.rs b/tests/run-make/dep-info/erroneous.rs similarity index 100% rename from tests/run-make/dep-info-doesnt-run-much/foo.rs rename to tests/run-make/dep-info/erroneous.rs diff --git a/tests/run-make/dep-info-spaces/foo foo.rs b/tests/run-make/dep-info/foo foo.rs similarity index 100% rename from tests/run-make/dep-info-spaces/foo foo.rs rename to tests/run-make/dep-info/foo foo.rs diff --git a/tests/run-make/dep-info-spaces/lib.rs b/tests/run-make/dep-info/lib_foofoo.rs similarity index 100% rename from tests/run-make/dep-info-spaces/lib.rs rename to tests/run-make/dep-info/lib_foofoo.rs diff --git a/tests/run-make/dep-info/rmake.rs b/tests/run-make/dep-info/rmake.rs new file mode 100644 index 00000000000..508569b7671 --- /dev/null +++ b/tests/run-make/dep-info/rmake.rs @@ -0,0 +1,37 @@ +// This is a simple smoke test for rustc's `--emit dep-info` feature. It prints out +// information about dependencies in a Makefile-compatible format, as a `.d` file. +// Note that this test does not check that the `.d` file is Makefile-compatible. + +// This test first checks that emitting dep-info disables static analysis, preventing +// compilation of `erroneous.rs` from causing a compilation failure. +// Then, it checks that compilation using the flag is successful in general, even with +// empty source files or source files that contain a whitespace character. + +// Finally, it removes one dependency and checks that compilation is still successful. +// See https://github.com/rust-lang/rust/pull/10698 + +use run_make_support::{rfs, rustc}; + +fn main() { + // We're only emitting dep info, so we shouldn't be running static analysis to + // figure out that this program is erroneous. + rustc().input("erroneous.rs").emit("dep-info").run(); + + rustc().input("lib.rs").emit("dep-info,link").crate_type("lib").run(); + rfs::remove_file("foo.rs"); + rfs::create_file("foo.rs"); + // Compilation should succeed even if `foo.rs` is empty. + rustc().input("lib.rs").emit("dep-info,link").crate_type("lib").run(); + + // Again, with a space in the filename this time around. + rustc().input("lib_foofoo.rs").emit("dep-info,link").crate_type("lib").run(); + rfs::remove_file("foo foo.rs"); + rfs::create_file("foo foo.rs"); + // Compilation should succeed even if `foo foo.rs` is empty. + rustc().input("lib_foofoo.rs").emit("dep-info,link").crate_type("lib").run(); + + // When a source file is deleted, compilation should still succeed if the library + // also loses this source file dependency. + rfs::remove_file("bar.rs"); + rustc().input("lib2.rs").emit("dep-info,link").crate_type("lib").run(); +} diff --git a/tests/run-make/deref-impl-rustdoc-ice/rmake.rs b/tests/run-make/deref-impl-rustdoc-ice/rmake.rs index 91fc0a9025f..0ad5934f62e 100644 --- a/tests/run-make/deref-impl-rustdoc-ice/rmake.rs +++ b/tests/run-make/deref-impl-rustdoc-ice/rmake.rs @@ -12,5 +12,5 @@ use run_make_support::{cwd, rustc, rustdoc}; fn main() { rustc().input("foo.rs").run(); rustc().input("bar.rs").run(); - rustdoc().input("baz.rs").library_search_path(cwd()).output(cwd()).run(); + rustdoc().input("baz.rs").library_search_path(cwd()).out_dir(cwd()).run(); } diff --git a/tests/run-make/doctests-keep-binaries-2024/rmake.rs b/tests/run-make/doctests-keep-binaries-2024/rmake.rs new file mode 100644 index 00000000000..3e8ffcbf244 --- /dev/null +++ b/tests/run-make/doctests-keep-binaries-2024/rmake.rs @@ -0,0 +1,67 @@ +// Check that valid binaries are persisted by running them, regardless of whether the +// --run or --no-run option is used. + +//@ ignore-cross-compile + +use std::path::Path; + +use run_make_support::{rfs, run, rustc, rustdoc}; + +fn setup_test_env(callback: F) { + let out_dir = Path::new("doctests"); + rfs::create_dir(&out_dir); + rustc().input("t.rs").crate_type("rlib").run(); + callback(&out_dir, Path::new("libt.rlib")); + rfs::remove_dir_all(out_dir); +} + +fn check_generated_binaries() { + run("doctests/merged_doctest_2024/rust_out"); +} + +fn main() { + setup_test_env(|out_dir, extern_path| { + rustdoc() + .input("t.rs") + .arg("-Zunstable-options") + .arg("--test") + .arg("--persist-doctests") + .arg(out_dir) + .extern_("t", extern_path) + .edition("2024") + .run(); + check_generated_binaries(); + }); + setup_test_env(|out_dir, extern_path| { + rustdoc() + .input("t.rs") + .arg("-Zunstable-options") + .arg("--test") + .arg("--persist-doctests") + .arg(out_dir) + .extern_("t", extern_path) + .arg("--no-run") + .edition("2024") + .run(); + check_generated_binaries(); + }); + // Behavior with --test-run-directory with relative paths. + setup_test_env(|_, _| { + let run_dir_path = Path::new("rundir"); + rfs::create_dir(&run_dir_path); + + rustdoc() + .input("t.rs") + .arg("-Zunstable-options") + .arg("--test") + .arg("--persist-doctests") + .arg("doctests") + .arg("--test-run-directory") + .arg(run_dir_path) + .extern_("t", "libt.rlib") + .edition("2024") + .run(); + + rfs::remove_dir_all(run_dir_path); + }); +} diff --git a/tests/run-make/doctests-keep-binaries-2024/t.rs b/tests/run-make/doctests-keep-binaries-2024/t.rs new file mode 100644 index 00000000000..c38cf0a0b25 --- /dev/null +++ b/tests/run-make/doctests-keep-binaries-2024/t.rs @@ -0,0 +1,11 @@ +/// Fungle the foople. +/// ``` +/// t::foople(); +/// ``` +pub fn foople() {} + +/// Flomble the florp +/// ``` +/// t::florp(); +/// ``` +pub fn florp() {} diff --git a/tests/run-make/doctests-merge/doctest-2021.stdout b/tests/run-make/doctests-merge/doctest-2021.stdout new file mode 100644 index 00000000000..7da08d68faa --- /dev/null +++ b/tests/run-make/doctests-merge/doctest-2021.stdout @@ -0,0 +1,7 @@ + +running 2 tests +test doctest.rs - (line 4) ... ok +test doctest.rs - init (line 8) ... ok + +test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/tests/run-make/doctests-merge/doctest-2024.stdout b/tests/run-make/doctests-merge/doctest-2024.stdout new file mode 100644 index 00000000000..7da08d68faa --- /dev/null +++ b/tests/run-make/doctests-merge/doctest-2024.stdout @@ -0,0 +1,7 @@ + +running 2 tests +test doctest.rs - (line 4) ... ok +test doctest.rs - init (line 8) ... ok + +test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/tests/run-make/doctests-merge/doctest-standalone.rs b/tests/run-make/doctests-merge/doctest-standalone.rs new file mode 100644 index 00000000000..134ffb58285 --- /dev/null +++ b/tests/run-make/doctests-merge/doctest-standalone.rs @@ -0,0 +1,18 @@ +#![crate_name = "foo"] +#![crate_type = "lib"] + +//! ```standalone +//! foo::init(); +//! ``` + +/// ```standalone +/// foo::init(); +/// ``` +pub fn init() { + static mut IS_INIT: bool = false; + + unsafe { + assert!(!IS_INIT); + IS_INIT = true; + } +} diff --git a/tests/run-make/doctests-merge/doctest-standalone.stdout b/tests/run-make/doctests-merge/doctest-standalone.stdout new file mode 100644 index 00000000000..ee9f62326ab --- /dev/null +++ b/tests/run-make/doctests-merge/doctest-standalone.stdout @@ -0,0 +1,7 @@ + +running 2 tests +test doctest-standalone.rs - (line 4) ... ok +test doctest-standalone.rs - init (line 8) ... ok + +test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/tests/run-make/doctests-merge/doctest.rs b/tests/run-make/doctests-merge/doctest.rs new file mode 100644 index 00000000000..66a5d88db67 --- /dev/null +++ b/tests/run-make/doctests-merge/doctest.rs @@ -0,0 +1,18 @@ +#![crate_name = "foo"] +#![crate_type = "lib"] + +//! ``` +//! foo::init(); +//! ``` + +/// ``` +/// foo::init(); +/// ``` +pub fn init() { + static mut IS_INIT: bool = false; + + unsafe { + assert!(!IS_INIT); + IS_INIT = true; + } +} diff --git a/tests/run-make/doctests-merge/rmake.rs b/tests/run-make/doctests-merge/rmake.rs new file mode 100644 index 00000000000..a25da7403e2 --- /dev/null +++ b/tests/run-make/doctests-merge/rmake.rs @@ -0,0 +1,39 @@ +use std::path::Path; + +use run_make_support::{cwd, diff, rustc, rustdoc}; + +fn test_and_compare(input_file: &str, stdout_file: &str, edition: &str, dep: &Path) { + let mut cmd = rustdoc(); + + let output = cmd + .input(input_file) + .arg("--test") + .arg("-Zunstable-options") + .edition(edition) + .arg("--test-args=--test-threads=1") + .extern_("foo", dep.display().to_string()) + .env("RUST_BACKTRACE", "short") + .run(); + + diff() + .expected_file(stdout_file) + .actual_text("output", output.stdout_utf8()) + .normalize(r#"finished in \d+\.\d+s"#, "finished in $$TIME") + .run(); +} + +fn main() { + let out_file = cwd().join("libfoo.rlib"); + + rustc().input("doctest.rs").crate_type("rlib").output(&out_file).run(); + + // First we ensure that running with the 2024 edition will not fail at runtime. + test_and_compare("doctest.rs", "doctest-2024.stdout", "2024", &out_file); + + // Then we ensure that running with an edition < 2024 will not fail at runtime. + test_and_compare("doctest.rs", "doctest-2021.stdout", "2021", &out_file); + + // Now we check with the standalone attribute which should succeed in all cases. + test_and_compare("doctest-standalone.rs", "doctest-standalone.stdout", "2024", &out_file); + test_and_compare("doctest-standalone.rs", "doctest-standalone.stdout", "2021", &out_file); +} diff --git a/tests/run-make/dump-ice-to-disk/rmake.rs b/tests/run-make/dump-ice-to-disk/rmake.rs index 48b4071e065..15f35eb2d3d 100644 --- a/tests/run-make/dump-ice-to-disk/rmake.rs +++ b/tests/run-make/dump-ice-to-disk/rmake.rs @@ -14,11 +14,17 @@ //! that `RUSTC_ICE_PATH` takes precedence and no ICE dump is emitted under `METRICS_PATH`. //! //! See . +//! +//! # Test history +//! +//! - The previous rmake.rs iteration of this test was flakey for unknown reason on `i686-mingw` +//! *specifically*, so assertion failures in this test was made extremely verbose to help +//! diagnose why the ICE messages was different *specifically* on `i686-mingw`. +//! - An attempt is made to re-enable this test on `i686-mingw` (by removing `ignore-windows`). If +//! this test is still flakey, please restore the `ignore-windows` directive. //@ ignore-windows -// FIXME(#128911): @jieyouxu: This test is sometimes for whatever forsaken reason flakey in -// `i686-mingw`, and I cannot reproduce it locally. The error messages upon assertion failure in -// this test is intentionally extremely verbose to aid debugging that issue. +//FIXME(#128911): still flakey on i686-mingw. use std::cell::OnceCell; use std::path::{Path, PathBuf}; diff --git a/tests/run-make/embed-source-dwarf/main.rs b/tests/run-make/embed-source-dwarf/main.rs new file mode 100644 index 00000000000..c80af84f414 --- /dev/null +++ b/tests/run-make/embed-source-dwarf/main.rs @@ -0,0 +1,2 @@ +// hello +fn main() {} diff --git a/tests/run-make/embed-source-dwarf/rmake.rs b/tests/run-make/embed-source-dwarf/rmake.rs new file mode 100644 index 00000000000..06d550121b0 --- /dev/null +++ b/tests/run-make/embed-source-dwarf/rmake.rs @@ -0,0 +1,70 @@ +//@ ignore-windows +//@ ignore-apple + +// LLVM 17's embed-source implementation requires that source code is attached +// for all files in the output DWARF debug info. This restriction was lifted in +// LLVM 18 (87e22bdd2bd6d77d782f9d64b3e3ae5bdcd5080d). +//@ min-llvm-version: 18 + +// This test should be replaced with one in tests/debuginfo once we can easily +// tell via GDB or LLDB if debuginfo contains source code. Cheap tricks in LLDB +// like setting an invalid source map path don't appear to work, maybe this'll +// become easier once GDB supports DWARFv6? + +use std::collections::HashMap; +use std::path::PathBuf; +use std::rc::Rc; + +use gimli::{AttributeValue, EndianRcSlice, Reader, RunTimeEndian}; +use object::{Object, ObjectSection}; +use run_make_support::{gimli, object, rfs, rustc}; + +fn main() { + let output = PathBuf::from("embed-source-main"); + rustc() + .input("main.rs") + .output(&output) + .arg("-g") + .arg("-Zembed-source=yes") + .arg("-Zdwarf-version=5") + .run(); + let output = rfs::read(output); + let obj = object::File::parse(output.as_slice()).unwrap(); + let endian = if obj.is_little_endian() { RunTimeEndian::Little } else { RunTimeEndian::Big }; + let dwarf = gimli::Dwarf::load(|section| -> Result<_, ()> { + let data = obj.section_by_name(section.name()).map(|s| s.uncompressed_data().unwrap()); + Ok(EndianRcSlice::new(Rc::from(data.unwrap_or_default().as_ref()), endian)) + }) + .unwrap(); + + let mut sources = HashMap::new(); + + let mut iter = dwarf.units(); + while let Some(header) = iter.next().unwrap() { + let unit = dwarf.unit(header).unwrap(); + let unit = unit.unit_ref(&dwarf); + + if let Some(program) = &unit.line_program { + let header = program.header(); + for file in header.file_names() { + if let Some(source) = file.source() { + let path = unit + .attr_string(file.path_name()) + .unwrap() + .to_string_lossy() + .unwrap() + .to_string(); + let source = + unit.attr_string(source).unwrap().to_string_lossy().unwrap().to_string(); + if !source.is_empty() { + sources.insert(path, source); + } + } + } + } + } + + dbg!(&sources); + assert_eq!(sources.len(), 1); + assert_eq!(sources.get("main.rs").unwrap(), "// hello\nfn main() {}\n"); +} diff --git a/tests/run-make/emit-shared-files/rmake.rs b/tests/run-make/emit-shared-files/rmake.rs index 8ac9073e993..483f298776c 100644 --- a/tests/run-make/emit-shared-files/rmake.rs +++ b/tests/run-make/emit-shared-files/rmake.rs @@ -13,13 +13,14 @@ fn main() { rustdoc() .arg("-Zunstable-options") .arg("--emit=invocation-specific") - .output("invocation-only") + .out_dir("invocation-only") .arg("--resource-suffix=-xxx") .args(&["--theme", "y.css"]) .args(&["--extend-css", "z.css"]) .input("x.rs") .run(); assert!(Path::new("invocation-only/search-index-xxx.js").exists()); + assert!(Path::new("invocation-only/crates-xxx.js").exists()); assert!(Path::new("invocation-only/settings.html").exists()); assert!(Path::new("invocation-only/x/all.html").exists()); assert!(Path::new("invocation-only/x/index.html").exists()); @@ -34,7 +35,7 @@ fn main() { rustdoc() .arg("-Zunstable-options") .arg("--emit=toolchain-shared-resources") - .output("toolchain-only") + .out_dir("toolchain-only") .arg("--resource-suffix=-xxx") .args(&["--extend-css", "z.css"]) .input("x.rs") @@ -68,7 +69,7 @@ fn main() { rustdoc() .arg("-Zunstable-options") .arg("--emit=toolchain-shared-resources,unversioned-shared-resources") - .output("all-shared") + .out_dir("all-shared") .arg("--resource-suffix=-xxx") .args(&["--extend-css", "z.css"]) .input("x.rs") diff --git a/tests/run-make/exit-code/rmake.rs b/tests/run-make/exit-code/rmake.rs index f290554831d..d3dcc04428c 100644 --- a/tests/run-make/exit-code/rmake.rs +++ b/tests/run-make/exit-code/rmake.rs @@ -16,7 +16,7 @@ fn main() { .run_fail() .assert_exit_code(101); - rustdoc().arg("success.rs").output("exit-code").run(); + rustdoc().arg("success.rs").out_dir("exit-code").run(); rustdoc().arg("--invalid-arg-foo").run_fail().assert_exit_code(1); diff --git a/tests/run-make/libtest-json/Makefile b/tests/run-make/libtest-json/Makefile deleted file mode 100644 index c8bc7b5dd4a..00000000000 --- a/tests/run-make/libtest-json/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# ignore-cross-compile -# needs-unwind -include ../tools.mk - -# Test expected libtest's JSON output - -OUTPUT_FILE_DEFAULT := $(TMPDIR)/libtest-json-output-default.json -OUTPUT_FILE_STDOUT_SUCCESS := $(TMPDIR)/libtest-json-output-stdout-success.json - -all: f.rs validate_json.py output-default.json output-stdout-success.json - $(RUSTC) --test f.rs - RUST_BACKTRACE=0 $(call RUN,f) -Z unstable-options --test-threads=1 --format=json > $(OUTPUT_FILE_DEFAULT) || true - RUST_BACKTRACE=0 $(call RUN,f) -Z unstable-options --test-threads=1 --format=json --show-output > $(OUTPUT_FILE_STDOUT_SUCCESS) || true - - cat $(OUTPUT_FILE_DEFAULT) | "$(PYTHON)" validate_json.py - cat $(OUTPUT_FILE_STDOUT_SUCCESS) | "$(PYTHON)" validate_json.py - - # Normalize the actual output and compare to expected output file - cat $(OUTPUT_FILE_DEFAULT) | sed 's/"exec_time": [0-9.]*/"exec_time": $$TIME/' | diff output-default.json - - cat $(OUTPUT_FILE_STDOUT_SUCCESS) | sed 's/"exec_time": [0-9.]*/"exec_time": $$TIME/' | diff output-stdout-success.json - diff --git a/tests/run-make/libtest-json/output-default.json b/tests/run-make/libtest-json/output-default.json index 01710f59e5d..a2293a032d0 100644 --- a/tests/run-make/libtest-json/output-default.json +++ b/tests/run-make/libtest-json/output-default.json @@ -7,4 +7,4 @@ { "type": "test", "name": "c", "event": "ok" } { "type": "test", "event": "started", "name": "d" } { "type": "test", "name": "d", "event": "ignored", "message": "msg" } -{ "type": "suite", "event": "failed", "passed": 2, "failed": 1, "ignored": 1, "measured": 0, "filtered_out": 0, "exec_time": $TIME } +{ "type": "suite", "event": "failed", "passed": 2, "failed": 1, "ignored": 1, "measured": 0, "filtered_out": 0, "exec_time": "$EXEC_TIME" } diff --git a/tests/run-make/libtest-json/output-stdout-success.json b/tests/run-make/libtest-json/output-stdout-success.json index 878eb6c7c26..cf92f01f63a 100644 --- a/tests/run-make/libtest-json/output-stdout-success.json +++ b/tests/run-make/libtest-json/output-stdout-success.json @@ -7,4 +7,4 @@ { "type": "test", "name": "c", "event": "ok", "stdout": "thread 'c' panicked at f.rs:15:5:\nassertion failed: false\n" } { "type": "test", "event": "started", "name": "d" } { "type": "test", "name": "d", "event": "ignored", "message": "msg" } -{ "type": "suite", "event": "failed", "passed": 2, "failed": 1, "ignored": 1, "measured": 0, "filtered_out": 0, "exec_time": $TIME } +{ "type": "suite", "event": "failed", "passed": 2, "failed": 1, "ignored": 1, "measured": 0, "filtered_out": 0, "exec_time": "$EXEC_TIME" } diff --git a/tests/run-make/libtest-json/rmake.rs b/tests/run-make/libtest-json/rmake.rs new file mode 100644 index 00000000000..c31f4a79b64 --- /dev/null +++ b/tests/run-make/libtest-json/rmake.rs @@ -0,0 +1,42 @@ +// Check libtest's JSON output against snapshots. + +//@ ignore-cross-compile +//@ needs-unwind (test file contains #[should_panic] test) + +use run_make_support::{cmd, diff, rustc, serde_json}; + +fn main() { + rustc().arg("--test").input("f.rs").run(); + + run_tests(&[], "output-default.json"); + run_tests(&["--show-output"], "output-stdout-success.json"); +} + +#[track_caller] +fn run_tests(extra_args: &[&str], expected_file: &str) { + let cmd_out = cmd("./f") + .env("RUST_BACKTRACE", "0") + .args(&["-Zunstable-options", "--test-threads=1", "--format=json"]) + .args(extra_args) + .run_fail(); + let test_stdout = &cmd_out.stdout_utf8(); + + // Verify that the test process output is JSON Lines, i.e. each line is valid JSON. + for (line, n) in test_stdout.lines().zip(1..) { + if let Err(e) = serde_json::from_str::(line) { + panic!( + "could not parse JSON on line {n}: {e}\n\ + \n\ + === STDOUT ===\n\ + {test_stdout}\ + ==============" + ); + } + } + + diff() + .expected_file(expected_file) + .actual_text("stdout", test_stdout) + .normalize(r#"(?"exec_time": )[0-9.]+"#, r#"${prefix}"$$EXEC_TIME""#) + .run(); +} diff --git a/tests/run-make/libtest-json/validate_json.py b/tests/run-make/libtest-json/validate_json.py deleted file mode 100755 index 657f732f2bf..00000000000 --- a/tests/run-make/libtest-json/validate_json.py +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env python - -import sys -import json - -# Try to decode line in order to ensure it is a valid JSON document -for line in sys.stdin: - json.loads(line) diff --git a/tests/run-make/libtest-junit/Makefile b/tests/run-make/libtest-junit/Makefile deleted file mode 100644 index 26e56242dd2..00000000000 --- a/tests/run-make/libtest-junit/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# ignore-cross-compile -# needs-unwind contains should_panic test -include ../tools.mk - -# Test expected libtest's junit output - -OUTPUT_FILE_DEFAULT := $(TMPDIR)/libtest-junit-output-default.xml -OUTPUT_FILE_STDOUT_SUCCESS := $(TMPDIR)/libtest-junit-output-stdout-success.xml - -all: f.rs validate_junit.py output-default.xml output-stdout-success.xml - $(RUSTC) --test f.rs - RUST_BACKTRACE=0 $(call RUN,f) -Z unstable-options --test-threads=1 --format=junit > $(OUTPUT_FILE_DEFAULT) || true - RUST_BACKTRACE=0 $(call RUN,f) -Z unstable-options --test-threads=1 --format=junit --show-output > $(OUTPUT_FILE_STDOUT_SUCCESS) || true - - cat $(OUTPUT_FILE_DEFAULT) | "$(PYTHON)" validate_junit.py - cat $(OUTPUT_FILE_STDOUT_SUCCESS) | "$(PYTHON)" validate_junit.py - - # Normalize the actual output and compare to expected output file - cat $(OUTPUT_FILE_DEFAULT) | sed 's/time="[0-9.]*"/time="$$TIME"/g' | diff output-default.xml - - cat $(OUTPUT_FILE_STDOUT_SUCCESS) | sed 's/time="[0-9.]*"/time="$$TIME"/g' | diff output-stdout-success.xml - diff --git a/tests/run-make/libtest-junit/rmake.rs b/tests/run-make/libtest-junit/rmake.rs new file mode 100644 index 00000000000..d631313ed92 --- /dev/null +++ b/tests/run-make/libtest-junit/rmake.rs @@ -0,0 +1,31 @@ +// Check libtest's JUnit (XML) output against snapshots. + +//@ ignore-cross-compile +//@ needs-unwind (test file contains #[should_panic] test) + +use run_make_support::{cmd, diff, python_command, rustc}; + +fn main() { + rustc().arg("--test").input("f.rs").run(); + + run_tests(&[], "output-default.xml"); + run_tests(&["--show-output"], "output-stdout-success.xml"); +} + +#[track_caller] +fn run_tests(extra_args: &[&str], expected_file: &str) { + let cmd_out = cmd("./f") + .env("RUST_BACKTRACE", "0") + .args(&["-Zunstable-options", "--test-threads=1", "--format=junit"]) + .args(extra_args) + .run_fail(); + let test_stdout = &cmd_out.stdout_utf8(); + + python_command().arg("validate_junit.py").stdin(test_stdout).run(); + + diff() + .expected_file(expected_file) + .actual_text("stdout", test_stdout) + .normalize(r#"\btime="[0-9.]+""#, r#"time="$$TIME""#) + .run(); +} diff --git a/tests/run-make/libtest-junit/validate_junit.py b/tests/run-make/libtest-junit/validate_junit.py index 0d9b34a3cf7..f92473751b0 100755 --- a/tests/run-make/libtest-junit/validate_junit.py +++ b/tests/run-make/libtest-junit/validate_junit.py @@ -1,5 +1,15 @@ #!/usr/bin/env python +# Trivial Python script that reads lines from stdin, and checks that each line +# is a well-formed XML document. +# +# This takes advantage of the fact that Python has a built-in XML parser, +# whereas doing the same check in Rust would require us to pull in an XML +# crate just for this relatively-minor test. +# +# If you're trying to remove Python scripts from the test suite, think twice +# before removing this one. You could do so, but it's probably not worth it. + import sys import xml.etree.ElementTree as ET diff --git a/tests/run-make/libtest-thread-limit/Makefile b/tests/run-make/libtest-thread-limit/Makefile deleted file mode 100644 index 9496fa30159..00000000000 --- a/tests/run-make/libtest-thread-limit/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -include ../tools.mk - -# only-linux - -all: - $(RUSTC) test.rs --test --target $(TARGET) - $(shell ulimit -p 0 && $(call RUN,test)) diff --git a/tests/run-make/libtest-thread-limit/rmake.rs b/tests/run-make/libtest-thread-limit/rmake.rs new file mode 100644 index 00000000000..be0eeaf1717 --- /dev/null +++ b/tests/run-make/libtest-thread-limit/rmake.rs @@ -0,0 +1,64 @@ +// libtest used to panic if it hit the thread limit. This often resulted in spurious test failures +// (thread 'main' panicked at 'called Result::unwrap() on an Err value: Os +// { code: 11, kind: WouldBlock, message: "Resource temporarily unavailable" }' ... +// error: test failed, to rerun pass '--lib'). +// Since the fix in #81546, the test should continue to run synchronously +// if it runs out of threads. Therefore, this test's final execution step +// should succeed without an error. +// See https://github.com/rust-lang/rust/pull/81546 + +//@ only-linux +// Reason: thread limit modification +//@ ignore-cross-compile +// Reason: this test fails armhf-gnu, reasons unknown + +use std::ffi::{self, CStr, CString}; +use std::path::PathBuf; + +use run_make_support::{libc, run, rustc}; + +fn main() { + rustc().input("test.rs").arg("--test").run(); + + // We need to emulate an environment for libtest where threads are exhausted and spawning + // new threads are guaranteed to fail. This was previously achieved by ulimit shell builtin + // that called out to prlimit64 underneath to set resource limits (specifically thread + // number limits). Now that we don't have a shell, we need to implement that ourselves. + // See https://linux.die.net/man/2/setrlimit + + // The fork + exec is required because we cannot first try to limit the number of + // processes/threads to 1 and then try to spawn a new process to run the test. We need to + // setrlimit and run the libtest test program in the same process. + let pid = unsafe { libc::fork() }; + assert!(pid >= 0); + + // If the process ID is 0, this is the child process responsible for running the test + // program. + if pid == 0 { + let test = CString::new("test").unwrap(); + // The argv array should be terminated with a NULL pointer. + let argv = [test.as_ptr(), std::ptr::null()]; + // rlim_cur is soft limit, rlim_max is hard limit. + // By setting the limit very low (max 1), we ensure that libtest is unable to create new + // threads. + let rlimit = libc::rlimit { rlim_cur: 1, rlim_max: 1 }; + // RLIMIT_NPROC: The maximum number of processes (or, more precisely on Linux, + // threads) that can be created for the real user ID of the calling process. Upon + // encountering this limit, fork(2) fails with the error EAGAIN. + // Therefore, set the resource limit to RLIMIT_NPROC. + let ret = unsafe { libc::setrlimit(libc::RLIMIT_NPROC, &rlimit as *const libc::rlimit) }; + assert_eq!(ret, 0); + + // Finally, execute the 2 tests in test.rs. + let ret = unsafe { libc::execv(test.as_ptr(), argv.as_ptr()) }; + assert_eq!(ret, 0); + } else { + // Otherwise, other process IDs indicate that this is the parent process. + + let mut status: libc::c_int = 0; + let ret = unsafe { libc::waitpid(pid, &mut status as *mut libc::c_int, 0) }; + assert_eq!(ret, pid); + assert!(libc::WIFEXITED(status)); + assert_eq!(libc::WEXITSTATUS(status), 0); + } +} diff --git a/tests/run-make/libtest-thread-limit/test.rs b/tests/run-make/libtest-thread-limit/test.rs index 87e1d519171..d4eb1242615 100644 --- a/tests/run-make/libtest-thread-limit/test.rs +++ b/tests/run-make/libtest-thread-limit/test.rs @@ -10,7 +10,12 @@ fn spawn_thread_would_block() { THREAD_ID.set(thread::current().id()).unwrap(); } +// Tests are run in alphabetical order, and the second test is dependent on the +// first to set THREAD_ID. Do not rename the tests in such a way that `test_run_in_same_thread` +// would run before `spawn_thread_would_block`. +// See https://doc.rust-lang.org/rustc/tests/index.html#--shuffle + #[test] -fn run_in_same_thread() { +fn test_run_in_same_thread() { assert_eq!(*THREAD_ID.get().unwrap(), thread::current().id()); } diff --git a/tests/run-make/min-global-align/Makefile b/tests/run-make/min-global-align/Makefile deleted file mode 100644 index 82f38749e00..00000000000 --- a/tests/run-make/min-global-align/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -include ../tools.mk - -# only-linux - -# This tests ensure that global variables respect the target minimum alignment. -# The three bools `STATIC_BOOL`, `STATIC_MUT_BOOL`, and `CONST_BOOL` all have -# type-alignment of 1, but some targets require greater global alignment. - -SRC = min_global_align.rs -LL = $(TMPDIR)/min_global_align.ll - -all: -# Most targets are happy with default alignment -- take i686 for example. -ifeq ($(filter x86,$(LLVM_COMPONENTS)),x86) - $(RUSTC) --target=i686-unknown-linux-gnu --emit=llvm-ir $(SRC) - [ "$$(grep -c 'align 1' "$(LL)")" -eq "3" ] -endif -# SystemZ requires even alignment for PC-relative addressing. -ifeq ($(filter systemz,$(LLVM_COMPONENTS)),systemz) - $(RUSTC) --target=s390x-unknown-linux-gnu --emit=llvm-ir $(SRC) - [ "$$(grep -c 'align 2' "$(LL)")" -eq "3" ] -endif diff --git a/tests/run-make/min-global-align/rmake.rs b/tests/run-make/min-global-align/rmake.rs new file mode 100644 index 00000000000..2adaaf172f4 --- /dev/null +++ b/tests/run-make/min-global-align/rmake.rs @@ -0,0 +1,27 @@ +// This test checks that global variables respect the target minimum alignment. +// The three bools `STATIC_BOOL`, `STATIC_MUT_BOOL`, and `CONST_BOOL` all have +// type-alignment of 1, but some targets require greater global alignment. +// See https://github.com/rust-lang/rust/pull/44440 + +//@ only-linux +// Reason: this test is specific to linux, considering compilation is targeted +// towards linux architectures only. + +use run_make_support::{assert_count_is, llvm_components_contain, rfs, rustc}; + +fn main() { + // Most targets are happy with default alignment -- take i686 for example. + if llvm_components_contain("x86") { + rustc().target("i686-unknown-linux-gnu").emit("llvm-ir").input("min_global_align.rs").run(); + assert_count_is(3, rfs::read_to_string("min_global_align.ll"), "align 1"); + } + // SystemZ requires even alignment for PC-relative addressing. + if llvm_components_contain("systemz") { + rustc() + .target("s390x-unknown-linux-gnu") + .emit("llvm-ir") + .input("min_global_align.rs") + .run(); + assert_count_is(3, rfs::read_to_string("min_global_align.ll"), "align 2"); + } +} diff --git a/tests/run-make/msvc-wholearchive/c.c b/tests/run-make/msvc-wholearchive/c.c new file mode 100644 index 00000000000..d6847845c68 --- /dev/null +++ b/tests/run-make/msvc-wholearchive/c.c @@ -0,0 +1 @@ +// This page is intentionally left blank diff --git a/tests/run-make/msvc-wholearchive/dll.def b/tests/run-make/msvc-wholearchive/dll.def new file mode 100644 index 00000000000..d55819e0d5e --- /dev/null +++ b/tests/run-make/msvc-wholearchive/dll.def @@ -0,0 +1,4 @@ +LIBRARY dll +EXPORTS + hello + number diff --git a/tests/run-make/msvc-wholearchive/rmake.rs b/tests/run-make/msvc-wholearchive/rmake.rs new file mode 100644 index 00000000000..98586fd8cc8 --- /dev/null +++ b/tests/run-make/msvc-wholearchive/rmake.rs @@ -0,0 +1,52 @@ +//! This is a regression test for #129020 +//! It ensures we can use `/WHOLEARCHIVE` to link a rust staticlib into DLL +//! using the MSVC linker + +//@ only-msvc +// Reason: this is testing the MSVC linker + +use std::path::PathBuf; + +use run_make_support::{cc, cmd, env_var, extra_c_flags, rustc}; + +fn main() { + // Build the staticlib + rustc().crate_type("staticlib").input("static.rs").output("static.lib").run(); + // Build an empty object to pass to the linker. + cc().input("c.c").output("c.obj").args(["-c"]).run(); + + // Find the C toolchain's linker. + let mut linker = PathBuf::from(env_var("CC")); + let linker_flavour = if linker.file_stem().is_some_and(|s| s == "cl") { + linker.set_file_name("link.exe"); + "msvc" + } else if linker.file_stem().is_some_and(|s| s == "clang-cl") { + linker.set_file_name("lld-link.exe"); + "llvm" + } else { + panic!("unknown C toolchain"); + }; + + // As a sanity check, make sure this works without /WHOLEARCHIVE. + // Otherwise the actual test failure may be caused by something else. + cmd(&linker) + .args(["c.obj", "./static.lib", "-dll", "-def:dll.def", "-out:dll.dll"]) + .args(extra_c_flags()) + .run(); + + // FIXME(@ChrisDenton): this doesn't currently work with llvm's lld-link for other reasons. + // May need LLVM patches. + if linker_flavour == "msvc" { + // Link in the staticlib using `/WHOLEARCHIVE` and produce a DLL. + cmd(&linker) + .args([ + "c.obj", + "-WHOLEARCHIVE:./static.lib", + "-dll", + "-def:dll.def", + "-out:dll_whole_archive.dll", + ]) + .args(extra_c_flags()) + .run(); + } +} diff --git a/tests/run-make/msvc-wholearchive/static.rs b/tests/run-make/msvc-wholearchive/static.rs new file mode 100644 index 00000000000..881c8856573 --- /dev/null +++ b/tests/run-make/msvc-wholearchive/static.rs @@ -0,0 +1,9 @@ +#[no_mangle] +pub extern "C" fn hello() { + println!("Hello world!"); +} + +#[no_mangle] +pub extern "C" fn number() -> u32 { + 42 +} diff --git a/tests/run-make/native-link-modifier-bundle/Makefile b/tests/run-make/native-link-modifier-bundle/Makefile deleted file mode 100644 index 527720922fe..00000000000 --- a/tests/run-make/native-link-modifier-bundle/Makefile +++ /dev/null @@ -1,38 +0,0 @@ -# ignore-cross-compile -# ignore-windows-msvc - -include ../tools.mk - -# We're using the llvm-nm instead of the system nm to ensure it is compatible -# with the LLVM bitcode generated by rustc. -# Except on Windows where piping/IO redirection under MSYS2 is wonky with llvm-nm. -ifndef IS_WINDOWS -NM = "$(LLVM_BIN_DIR)"/llvm-nm -else -NM = nm -endif - -all: $(call NATIVE_STATICLIB,native-staticlib) - # Build a staticlib and a rlib, the `native_func` symbol will be bundled into them - $(RUSTC) bundled.rs --crate-type=staticlib --crate-type=rlib - $(NM) $(TMPDIR)/libbundled.a | $(CGREP) -e "T _*native_func" - $(NM) $(TMPDIR)/libbundled.a | $(CGREP) -e "U _*native_func" - $(NM) $(TMPDIR)/libbundled.rlib | $(CGREP) -e "T _*native_func" - $(NM) $(TMPDIR)/libbundled.rlib | $(CGREP) -e "U _*native_func" - - # Build a staticlib and a rlib, the `native_func` symbol will not be bundled into it - $(RUSTC) non-bundled.rs --crate-type=staticlib --crate-type=rlib - $(NM) $(TMPDIR)/libnon_bundled.a | $(CGREP) -ve "T _*native_func" - $(NM) $(TMPDIR)/libnon_bundled.a | $(CGREP) -e "U _*native_func" - $(NM) $(TMPDIR)/libnon_bundled.rlib | $(CGREP) -ve "T _*native_func" - $(NM) $(TMPDIR)/libnon_bundled.rlib | $(CGREP) -e "U _*native_func" - - # Build a cdylib, `native-staticlib` will not appear on the linker line because it was bundled previously - # The cdylib will contain the `native_func` symbol in the end - $(RUSTC) cdylib-bundled.rs --crate-type=cdylib --print link-args | $(CGREP) -ve '-l[" ]*native-staticlib' - $(NM) $(call DYLIB,cdylib_bundled) | $(CGREP) -e "[Tt] _*native_func" - - # Build a cdylib, `native-staticlib` will appear on the linker line because it was not bundled previously - # The cdylib will contain the `native_func` symbol in the end - $(RUSTC) cdylib-non-bundled.rs --crate-type=cdylib --print link-args | $(CGREP) -e '-l[" ]*native-staticlib' - $(NM) $(call DYLIB,cdylib_non_bundled) | $(CGREP) -e "[Tt] _*native_func" diff --git a/tests/run-make/native-link-modifier-bundle/rmake.rs b/tests/run-make/native-link-modifier-bundle/rmake.rs new file mode 100644 index 00000000000..058b66b15f1 --- /dev/null +++ b/tests/run-make/native-link-modifier-bundle/rmake.rs @@ -0,0 +1,90 @@ +// This test exercises the `bundle` link argument, which can be turned on or off. + +// When building a rlib or staticlib, +bundle means that all object files from the native static +// library will be added to the rlib or staticlib archive, and then used from it during linking of +// the final binary. + +// When building a rlib -bundle means that the native static library is registered as a dependency +// of that rlib "by name", and object files from it are included only during linking of the final +// binary, the file search by that name is also performed during final linking. +// When building a staticlib -bundle means that the native static library is simply not included +// into the archive and some higher level build system will need to add it later during linking of +// the final binary. + +// This modifier has no effect when building other targets like executables or dynamic libraries. + +// The default for this modifier is +bundle. +// See https://github.com/rust-lang/rust/pull/95818 + +//@ ignore-cross-compile +// Reason: cross-compilation fails to export native symbols + +use run_make_support::{ + build_native_static_lib, dynamic_lib_name, is_msvc, llvm_nm, rust_lib_name, rustc, + static_lib_name, +}; + +fn main() { + build_native_static_lib("native-staticlib"); + // Build a staticlib and a rlib, the `native_func` symbol will be bundled into them + rustc().input("bundled.rs").crate_type("staticlib").crate_type("rlib").run(); + llvm_nm() + .input(static_lib_name("bundled")) + .run() + .assert_stdout_contains_regex("T _*native_func"); + llvm_nm() + .input(static_lib_name("bundled")) + .run() + .assert_stdout_contains_regex("U _*native_func"); + llvm_nm().input(rust_lib_name("bundled")).run().assert_stdout_contains_regex("T _*native_func"); + llvm_nm().input(rust_lib_name("bundled")).run().assert_stdout_contains_regex("U _*native_func"); + + // Build a staticlib and a rlib, the `native_func` symbol will not be bundled into it + build_native_static_lib("native-staticlib"); + rustc().input("non-bundled.rs").crate_type("staticlib").crate_type("rlib").run(); + llvm_nm() + .input(static_lib_name("non_bundled")) + .run() + .assert_stdout_not_contains_regex("T _*native_func"); + llvm_nm() + .input(static_lib_name("non_bundled")) + .run() + .assert_stdout_contains_regex("U _*native_func"); + llvm_nm() + .input(rust_lib_name("non_bundled")) + .run() + .assert_stdout_not_contains_regex("T _*native_func"); + llvm_nm() + .input(rust_lib_name("non_bundled")) + .run() + .assert_stdout_contains_regex("U _*native_func"); + + // This part of the test does not function on Windows MSVC - no symbols are printed. + if !is_msvc() { + // Build a cdylib, `native-staticlib` will not appear on the linker line because it was + // bundled previously. The cdylib will contain the `native_func` symbol in the end. + rustc() + .input("cdylib-bundled.rs") + .crate_type("cdylib") + .print("link-args") + .run() + .assert_stdout_not_contains(r#"-l[" ]*native-staticlib"#); + llvm_nm() + .input(dynamic_lib_name("cdylib_bundled")) + .run() + .assert_stdout_contains_regex("[Tt] _*native_func"); + + // Build a cdylib, `native-staticlib` will appear on the linker line because it was not + // bundled previously. The cdylib will contain the `native_func` symbol in the end + rustc() + .input("cdylib-non-bundled.rs") + .crate_type("cdylib") + .print("link-args") + .run() + .assert_stdout_contains_regex(r#"-l[" ]*native-staticlib"#); + llvm_nm() + .input(dynamic_lib_name("cdylib_non_bundled")) + .run() + .assert_stdout_contains_regex("[Tt] _*native_func"); + } +} diff --git a/tests/run-make/no-alloc-shim/Makefile b/tests/run-make/no-alloc-shim/Makefile deleted file mode 100644 index 568e3f9ba1d..00000000000 --- a/tests/run-make/no-alloc-shim/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -include ../tools.mk - -# ignore-cross-compile -# ignore-msvc FIXME(bjorn3) can't figure out how to link with the MSVC toolchain - -TARGET_LIBDIR = $$($(RUSTC) --print target-libdir) - -all: - $(RUSTC) foo.rs --crate-type bin --emit obj -Cpanic=abort -ifdef IS_MSVC - $(CC) $(CFLAGS) $(TMPDIR)/foo.o $(call OUT_EXE,foo) /link $(TARGET_LIBDIR)/liballoc-*.rlib $(TARGET_LIBDIR)/libcore-*.rlib $(TARGET_LIBDIR)/libcompiler_builtins-*.rlib - $(call OUT_EXE,foo) -else - $(CC) $(CFLAGS) $(TMPDIR)/foo.o $(TARGET_LIBDIR)/liballoc-*.rlib $(TARGET_LIBDIR)/libcore-*.rlib $(TARGET_LIBDIR)/libcompiler_builtins-*.rlib -o $(call RUN_BINFILE,foo) - $(call RUN_BINFILE,foo) -endif - - # Check that linking without __rust_no_alloc_shim_is_unstable defined fails - $(RUSTC) foo.rs --crate-type bin --emit obj -Cpanic=abort --cfg check_feature_gate -ifdef IS_MSVC - $(CC) $(CFLAGS) $(TMPDIR)/foo.o $(call OUT_EXE,foo) /link $(TARGET_LIBDIR)/liballoc-*.rlib $(TARGET_LIBDIR)/libcore-*.rlib $(TARGET_LIBDIR)/libcompiler_builtins-*.rlib || exit 0 && exit 1 -else - $(CC) $(CFLAGS) $(TMPDIR)/foo.o $(TARGET_LIBDIR)/liballoc-*.rlib $(TARGET_LIBDIR)/libcore-*.rlib $(TARGET_LIBDIR)/libcompiler_builtins-*.rlib -o $(call RUN_BINFILE,foo) || exit 0 && exit 1 -endif diff --git a/tests/run-make/no-alloc-shim/rmake.rs b/tests/run-make/no-alloc-shim/rmake.rs new file mode 100644 index 00000000000..c398a3177df --- /dev/null +++ b/tests/run-make/no-alloc-shim/rmake.rs @@ -0,0 +1,55 @@ +// This test checks the compatibility of the interaction between `--emit obj` and +// `#[global_allocator]`, as it is now possible to invoke the latter without the +// allocator shim since #86844. As this feature is unstable, it should fail if +// --cfg check_feature_gate is passed. +// See https://github.com/rust-lang/rust/pull/86844 + +//@ ignore-cross-compile +// Reason: the compiled binary is executed + +//@ ignore-msvc +//FIXME(Oneirical): Getting this to work on MSVC requires passing libcmt.lib to CC, +// which is not trivial to do. +// Tracking issue: https://github.com/rust-lang/rust/issues/128602 +// Discussion: https://github.com/rust-lang/rust/pull/128407#discussion_r1702439172 + +use run_make_support::{cc, cwd, has_extension, has_prefix, run, rustc, shallow_find_files}; + +fn main() { + rustc().input("foo.rs").crate_type("bin").emit("obj").panic("abort").run(); + let libdir = rustc().print("target-libdir").run().stdout_utf8(); + let libdir = libdir.trim(); + + let alloc_libs = shallow_find_files(&libdir, |path| { + has_prefix(path, "liballoc-") && has_extension(path, "rlib") + }); + let core_libs = shallow_find_files(&libdir, |path| { + has_prefix(path, "libcore-") && has_extension(path, "rlib") + }); + let compiler_builtins_libs = shallow_find_files(libdir, |path| { + has_prefix(path, "libcompiler_builtins") && has_extension(path, "rlib") + }); + + cc().input("foo.o") + .out_exe("foo") + .args(&alloc_libs) + .args(&core_libs) + .args(&compiler_builtins_libs) + .run(); + run("foo"); + + // Check that linking without __rust_no_alloc_shim_is_unstable defined fails + rustc() + .input("foo.rs") + .crate_type("bin") + .emit("obj") + .panic("abort") + .cfg("check_feature_gate") + .run(); + cc().input("foo.o") + .out_exe("foo") + .args(&alloc_libs) + .args(&core_libs) + .args(&compiler_builtins_libs) + .run_fail(); +} diff --git a/tests/run-make/remap-path-prefix-dwarf/Makefile b/tests/run-make/remap-path-prefix-dwarf/Makefile deleted file mode 100644 index 8905a00ea28..00000000000 --- a/tests/run-make/remap-path-prefix-dwarf/Makefile +++ /dev/null @@ -1,112 +0,0 @@ -# This test makes sure that --remap-path-prefix has the expected effects on paths in debuginfo. -# It tests several cases, each of them has a detailed description attached to it. - -# ignore-windows - -include ../tools.mk - -SRC_DIR := $(abspath .) -SRC_DIR_PARENT := $(abspath ..) - -ifeq ($(UNAME),Darwin) - DEBUGINFOOPTS := -Csplit-debuginfo=off -else - DEBUGINFOOPTS := -endif - -all: \ - abs_input_outside_working_dir \ - rel_input_remap_working_dir \ - rel_input_remap_working_dir_scope \ - rel_input_remap_working_dir_parent \ - rel_input_remap_working_dir_child \ - rel_input_remap_working_dir_diagnostics \ - abs_input_inside_working_dir \ - abs_input_inside_working_dir_scope \ - abs_input_outside_working_dir - -# The compiler is called with an *ABSOLUTE PATH* as input, and that absolute path *is* within -# the working directory of the compiler. We are remapping the path that contains `src`. -abs_input_inside_working_dir: - # We explicitly switch to a directory that *is* a prefix of the directory our - # source code is contained in. - cd $(SRC_DIR) && $(RUSTC) $(SRC_DIR)/src/quux.rs -o "$(TMPDIR)/abs_input_inside_working_dir.rlib" -Cdebuginfo=2 --remap-path-prefix $(SRC_DIR)=REMAPPED - # We expect the path to the main source file to be remapped. - "$(LLVM_BIN_DIR)"/llvm-dwarfdump $(TMPDIR)/abs_input_inside_working_dir.rlib | $(CGREP) "REMAPPED/src/quux.rs" - # No weird duplication of remapped components (see #78479) - "$(LLVM_BIN_DIR)"/llvm-dwarfdump $(TMPDIR)/abs_input_inside_working_dir.rlib | $(CGREP) -v "REMAPPED/REMAPPED" - -# The compiler is called with an *ABSOLUTE PATH* as input, and that absolute path *is* within -# the working directory of the compiler. We are remapping the path that contains `src`. -abs_input_inside_working_dir_scope: - # We explicitly switch to a directory that *is* a prefix of the directory our - # source code is contained in. - cd $(SRC_DIR) && $(RUSTC) $(SRC_DIR)/src/quux.rs -o "$(TMPDIR)/abs_input_inside_working_dir_scope.rlib" -Cdebuginfo=2 --remap-path-prefix $(SRC_DIR)=REMAPPED -Zremap-path-scope=object $(DEBUGINFOOPTS) - # We expect the path to the main source file to be remapped. - "$(LLVM_BIN_DIR)"/llvm-dwarfdump $(TMPDIR)/abs_input_inside_working_dir_scope.rlib | $(CGREP) "REMAPPED/src/quux.rs" - # No weird duplication of remapped components (see #78479) - "$(LLVM_BIN_DIR)"/llvm-dwarfdump $(TMPDIR)/abs_input_inside_working_dir_scope.rlib | $(CGREP) -v "REMAPPED/REMAPPED" - -# The compiler is called with an *ABSOLUTE PATH* as input, and that absolute path is *not* within -# the working directory of the compiler. We are remapping both the path that contains `src` and -# the working directory to the same thing. This setup corresponds to a workaround that is needed -# when trying to remap everything to something that looks like a local path. -# Relative paths are interpreted as relative to the compiler's working directory (e.g. in -# debuginfo). If we also remap the working directory, the compiler strip it from other paths so -# that the final outcome is the desired one again. -abs_input_outside_working_dir: - # We explicitly switch to a directory that is *not* a prefix of the directory our - # source code is contained in. - cd $(TMPDIR) && $(RUSTC) $(SRC_DIR)/src/quux.rs -o "$(TMPDIR)/abs_input_outside_working_dir.rlib" -Cdebuginfo=2 --remap-path-prefix $(SRC_DIR)=REMAPPED --remap-path-prefix $(TMPDIR)=REMAPPED - "$(LLVM_BIN_DIR)"/llvm-dwarfdump $(TMPDIR)/abs_input_outside_working_dir.rlib | $(CGREP) "REMAPPED/src/quux.rs" - # No weird duplication of remapped components (see #78479) - "$(LLVM_BIN_DIR)"/llvm-dwarfdump $(TMPDIR)/abs_input_outside_working_dir.rlib | $(CGREP) -v "REMAPPED/REMAPPED" - -# The compiler is called with a *RELATIVE PATH* as input. We are remapping the working directory of -# the compiler, which naturally is an implicit prefix of our relative input path. Debuginfo will -# expand the relative path to an absolute path and we expect the working directory to be remapped -# in that expansion. -rel_input_remap_working_dir: - cd $(SRC_DIR) && $(RUSTC) src/quux.rs -o "$(TMPDIR)/rel_input_remap_working_dir.rlib" -Cdebuginfo=2 --remap-path-prefix "$(SRC_DIR)=REMAPPED" - "$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir.rlib" | $(CGREP) "REMAPPED/src/quux.rs" - # No weird duplication of remapped components (see #78479) - "$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir.rlib" | $(CGREP) -v "REMAPPED/REMAPPED" - -# The compiler is called with a *RELATIVE PATH* as input. We are remapping the working directory of -# the compiler, which naturally is an implicit prefix of our relative input path. Debuginfo will -# expand the relative path to an absolute path and we expect the working directory to be remapped -# in that expansion. -rel_input_remap_working_dir_scope: - cd $(SRC_DIR) && $(RUSTC) src/quux.rs -o "$(TMPDIR)/rel_input_remap_working_dir_scope.rlib" -Cdebuginfo=2 --remap-path-prefix "$(SRC_DIR)=REMAPPED" -Zremap-path-scope=object $(DEBUGINFOOPTS) - "$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_scope.rlib" | $(CGREP) "REMAPPED/src/quux.rs" - # No weird duplication of remapped components (see #78479) - "$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_scope.rlib" | $(CGREP) -v "REMAPPED/REMAPPED" - -rel_input_remap_working_dir_diagnostics: - cd $(SRC_DIR) && $(RUSTC) src/quux.rs -o "$(TMPDIR)/rel_input_remap_working_dir_scope.rlib" -Cdebuginfo=2 --remap-path-prefix "$(SRC_DIR)=REMAPPED" -Zremap-path-scope=diagnostics $(DEBUGINFOOPTS) - "$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_scope.rlib" | $(CGREP) -v "REMAPPED/src/quux.rs" - "$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_scope.rlib" | $(CGREP) -v "REMAPPED/REMAPPED" - -# The compiler is called with a *RELATIVE PATH* as input. We are remapping a *SUB-DIRECTORY* of the -# compiler's working directory. This test makes sure that that directory is remapped even though it -# won't actually show up in this form in the compiler's SourceMap and instead is only constructed -# on demand during debuginfo generation. -rel_input_remap_working_dir_child: - cd $(SRC_DIR) && $(RUSTC) src/quux.rs -o "$(TMPDIR)/rel_input_remap_working_dir_child.rlib" -Cdebuginfo=2 --remap-path-prefix "$(SRC_DIR)/src=REMAPPED" - # We expect `src/quux.rs` to have been remapped to `REMAPPED/quux.rs`. - "$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_child.rlib" | $(CGREP) "REMAPPED/quux.rs" - # We don't want to find the path that we just remapped anywhere in the DWARF - "$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_child.rlib" | $(CGREP) -v "$(SRC_DIR)/src" - # No weird duplication of remapped components (see #78479) - "$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_child.rlib" | $(CGREP) -v "REMAPPED/REMAPPED" - -# The compiler is called with a *RELATIVE PATH* as input. We are remapping a *PARENT DIRECTORY* of -# the compiler's working directory. -rel_input_remap_working_dir_parent: - cd $(SRC_DIR) && $(RUSTC) src/quux.rs -o "$(TMPDIR)/rel_input_remap_working_dir_parent.rlib" -Cdebuginfo=2 --remap-path-prefix "$(SRC_DIR_PARENT)=REMAPPED" - # We expect `src/quux.rs` to have been remapped to `REMAPPED/remap-path-prefix-dwarf/src/quux.rs`. - "$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_parent.rlib" | $(CGREP) "REMAPPED/remap-path-prefix-dwarf/src/quux.rs" - # We don't want to find the path that we just remapped anywhere in the DWARF - "$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_parent.rlib" | $(CGREP) -v "$(SRC_DIR_PARENT)" - # No weird duplication of remapped components (see #78479) - "$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_parent.rlib" | $(CGREP) -v "REMAPPED/REMAPPED" diff --git a/tests/run-make/remap-path-prefix-dwarf/rmake.rs b/tests/run-make/remap-path-prefix-dwarf/rmake.rs new file mode 100644 index 00000000000..ede1d615742 --- /dev/null +++ b/tests/run-make/remap-path-prefix-dwarf/rmake.rs @@ -0,0 +1,202 @@ +// This test makes sure that --remap-path-prefix has the expected effects on paths in debuginfo. +// We explicitly switch to a directory that *is* a prefix of the directory our +// source code is contained in. +// It tests several cases, each of them has a detailed description attached to it. +// See https://github.com/rust-lang/rust/pull/96867 + +//@ ignore-windows +// Reason: the remap path prefix is not printed in the dwarf dump. + +use run_make_support::{cwd, is_darwin, llvm_dwarfdump, rust_lib_name, rustc}; + +fn main() { + // The compiler is called with an *ABSOLUTE PATH* as input, and that absolute path *is* within + // the working directory of the compiler. We are remapping the path that contains `src`. + check_dwarf(DwarfTest { + lib_name: "abs_input_inside_working_dir", + input_path: PathType::Absolute, + scope: None, + remap_path_prefix: PrefixType::Regular(format!("{}=REMAPPED", cwd().display())), + dwarf_test: DwarfDump::ContainsSrcPath, + }); + check_dwarf(DwarfTest { + lib_name: "abs_input_inside_working_dir_scope", + input_path: PathType::Absolute, + scope: Some(ScopeType::Object), + remap_path_prefix: PrefixType::Regular(format!("{}=REMAPPED", cwd().display())), + dwarf_test: DwarfDump::ContainsSrcPath, + }); + // The compiler is called with an *ABSOLUTE PATH* as input, and that absolute path is *not* + // within the working directory of the compiler. We are remapping both the path that contains + // `src` and the working directory to the same thing. This setup corresponds to a workaround + // that is needed when trying to remap everything to something that looks like a local + // path. Relative paths are interpreted as relative to the compiler's working directory (e.g. + // in debuginfo). If we also remap the working directory, the compiler strip it from other + // paths so that the final outcome is the desired one again. + check_dwarf(DwarfTest { + lib_name: "abs_input_outside_working_dir", + input_path: PathType::Absolute, + scope: None, + remap_path_prefix: PrefixType::Dual(( + format!("{}=REMAPPED", cwd().display()), + "rmake_out=REMAPPED".to_owned(), + )), + dwarf_test: DwarfDump::ContainsSrcPath, + }); + // The compiler is called with a *RELATIVE PATH* as input. We are remapping the working + // directory of the compiler, which naturally is an implicit prefix of our relative input path. + // Debuginfo will expand the relative path to an absolute path and we expect the working + // directory to be remapped in that expansion. + check_dwarf(DwarfTest { + lib_name: "rel_input_remap_working_dir", + input_path: PathType::Relative, + scope: None, + remap_path_prefix: PrefixType::Regular(format!("{}=REMAPPED", cwd().display())), + dwarf_test: DwarfDump::ContainsSrcPath, + }); + check_dwarf(DwarfTest { + lib_name: "rel_input_remap_working_dir_scope", + input_path: PathType::Relative, + scope: Some(ScopeType::Object), + remap_path_prefix: PrefixType::Regular(format!("{}=REMAPPED", cwd().display())), + dwarf_test: DwarfDump::ContainsSrcPath, + }); + check_dwarf(DwarfTest { + lib_name: "rel_input_remap_working_dir_scope", + input_path: PathType::Relative, + scope: Some(ScopeType::Diagnostics), + remap_path_prefix: PrefixType::Regular(format!("{}=REMAPPED", cwd().display())), + dwarf_test: DwarfDump::AvoidSrcPath, + }); + // The compiler is called with a *RELATIVE PATH* as input. We are remapping a *SUB-DIRECTORY* + // of the compiler's working directory. This test makes sure that that directory is remapped + // even though it won't actually show up in this form in the compiler's SourceMap and instead + // is only constructed on demand during debuginfo generation. + check_dwarf(DwarfTest { + lib_name: "rel_input_remap_working_dir_child", + input_path: PathType::Relative, + scope: None, + remap_path_prefix: PrefixType::Regular(format!("{}=REMAPPED", cwd().join("src").display())), + dwarf_test: DwarfDump::ChildTest, + }); + // The compiler is called with a *RELATIVE PATH* as input. We are remapping a + // *PARENT DIRECTORY* of the compiler's working directory. + check_dwarf(DwarfTest { + lib_name: "rel_input_remap_working_dir_parent", + input_path: PathType::Relative, + scope: None, + remap_path_prefix: PrefixType::Regular(format!( + "{}=REMAPPED", + cwd().parent().unwrap().display() + )), + dwarf_test: DwarfDump::ParentTest, + }); +} + +#[track_caller] +fn check_dwarf(test: DwarfTest) { + let mut rustc = rustc(); + match test.input_path { + PathType::Absolute => rustc.input(cwd().join("src/quux.rs")), + PathType::Relative => rustc.input("src/quux.rs"), + }; + rustc.output(rust_lib_name(test.lib_name)); + rustc.arg("-Cdebuginfo=2"); + if let Some(scope) = test.scope { + match scope { + ScopeType::Object => rustc.arg("-Zremap-path-scope=object"), + ScopeType::Diagnostics => rustc.arg("-Zremap-path-scope=diagnostics"), + }; + if is_darwin() { + rustc.arg("-Csplit-debuginfo=off"); + } + } + match test.remap_path_prefix { + PrefixType::Regular(prefix) => { + // We explicitly switch to a directory that *is* a prefix of the directory our + // source code is contained in. + rustc.arg("--remap-path-prefix"); + rustc.arg(prefix); + } + PrefixType::Dual((prefix1, prefix2)) => { + // We explicitly switch to a directory that is *not* a prefix of the directory our + // source code is contained in. + rustc.arg("--remap-path-prefix"); + rustc.arg(prefix1); + rustc.arg("--remap-path-prefix"); + rustc.arg(prefix2); + } + } + rustc.run(); + match test.dwarf_test { + DwarfDump::ContainsSrcPath => { + llvm_dwarfdump() + .input(rust_lib_name(test.lib_name)) + .run() + // We expect the path to the main source file to be remapped. + .assert_stdout_contains("REMAPPED/src/quux.rs") + // No weird duplication of remapped components (see #78479) + .assert_stdout_not_contains("REMAPPED/REMAPPED"); + } + DwarfDump::AvoidSrcPath => { + llvm_dwarfdump() + .input(rust_lib_name(test.lib_name)) + .run() + .assert_stdout_not_contains("REMAPPED/src/quux.rs") + .assert_stdout_not_contains("REMAPPED/REMAPPED"); + } + DwarfDump::ChildTest => { + llvm_dwarfdump() + .input(rust_lib_name(test.lib_name)) + .run() + // We expect `src/quux.rs` to have been remapped to `REMAPPED/quux.rs`. + .assert_stdout_contains("REMAPPED/quux.rs") + // We don't want to find the path that we just remapped anywhere in the DWARF + .assert_stdout_not_contains(cwd().join("src").to_str().unwrap()) + // No weird duplication of remapped components (see #78479) + .assert_stdout_not_contains("REMAPPED/REMAPPED"); + } + DwarfDump::ParentTest => { + llvm_dwarfdump() + .input(rust_lib_name(test.lib_name)) + .run() + // We expect `src/quux.rs` to have been remapped to + // `REMAPPED/remap-path-prefix-dwarf/src/quux.rs`. + .assert_stdout_contains("REMAPPED/rmake_out/src/quux.rs") + // We don't want to find the path that we just remapped anywhere in the DWARF + .assert_stdout_not_contains(cwd().parent().unwrap().to_str().unwrap()) + // No weird duplication of remapped components (see #78479) + .assert_stdout_not_contains("REMAPPED/REMAPPED"); + } + }; +} + +struct DwarfTest { + lib_name: &'static str, + input_path: PathType, + scope: Option, + remap_path_prefix: PrefixType, + dwarf_test: DwarfDump, +} + +enum PathType { + Absolute, + Relative, +} + +enum ScopeType { + Object, + Diagnostics, +} + +enum DwarfDump { + ContainsSrcPath, + AvoidSrcPath, + ChildTest, + ParentTest, +} + +enum PrefixType { + Regular(String), + Dual((String, String)), +} diff --git a/tests/run-make/remove-dir-all-race/rmake.rs b/tests/run-make/remove-dir-all-race/rmake.rs new file mode 100644 index 00000000000..03c94b76127 --- /dev/null +++ b/tests/run-make/remove-dir-all-race/rmake.rs @@ -0,0 +1,62 @@ +//@ ignore-windows + +// This test attempts to make sure that running `remove_dir_all` +// doesn't result in a NotFound error one of the files it +// is deleting is deleted concurrently. +// +// The windows implementation for `remove_dir_all` is significantly +// more complicated, and has not yet been brought up to par with +// the implementation on other platforms, so this test is marked as +// `ignore-windows` until someone more expirenced with windows can +// sort that out. + +use std::fs::remove_dir_all; +use std::path::Path; +use std::thread; +use std::time::Duration; + +use run_make_support::rfs::{create_dir, write}; +use run_make_support::run_in_tmpdir; + +fn main() { + let mut race_happened = false; + run_in_tmpdir(|| { + for i in 0..150 { + create_dir("outer"); + create_dir("outer/inner"); + write("outer/inner.txt", b"sometext"); + + thread::scope(|scope| { + let t1 = scope.spawn(|| { + thread::sleep(Duration::from_nanos(i)); + remove_dir_all("outer").unwrap(); + }); + + let race_happened_ref = &race_happened; + let t2 = scope.spawn(|| { + let r1 = remove_dir_all("outer/inner"); + let r2 = remove_dir_all("outer/inner.txt"); + if r1.is_ok() && r2.is_err() { + race_happened = true; + } + }); + }); + + assert!(!Path::new("outer").exists()); + + // trying to remove a nonexistant top-level directory should + // still result in an error. + let Err(err) = remove_dir_all("outer") else { + panic!("removing nonexistant dir did not result in an error"); + }; + assert_eq!(err.kind(), std::io::ErrorKind::NotFound); + } + }); + if !race_happened { + eprintln!( + "WARNING: multithreaded deletion never raced, \ + try increasing the number of attempts or \ + adjusting the sleep timing" + ); + } +} diff --git a/tests/run-make/reproducible-build/Makefile b/tests/run-make/reproducible-build/Makefile deleted file mode 100644 index f5d17a234c0..00000000000 --- a/tests/run-make/reproducible-build/Makefile +++ /dev/null @@ -1,140 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -# ignore-musl -# Objects are reproducible but their path is not. - -all: \ - smoke \ - debug \ - opt \ - link_paths \ - remap_paths \ - different_source_dirs_rlib \ - remap_cwd_rlib \ - remap_cwd_to_empty \ - extern_flags - -# TODO: Builds of `bin` crate types are not deterministic with debuginfo=2 on -# Windows. -# See: https://github.com/rust-lang/rust/pull/87320#issuecomment-920105533 -# Issue: https://github.com/rust-lang/rust/issues/88982 -# -# different_source_dirs_bin \ -# remap_cwd_bin \ - -smoke: - rm -rf $(TMPDIR) && mkdir $(TMPDIR) - $(RUSTC) linker.rs -O - $(RUSTC) reproducible-build-aux.rs - $(RUSTC) reproducible-build.rs -C linker=$(call RUN_BINFILE,linker) - $(RUSTC) reproducible-build.rs -C linker=$(call RUN_BINFILE,linker) - diff -u "$(TMPDIR)/linker-arguments1" "$(TMPDIR)/linker-arguments2" - -debug: - rm -rf $(TMPDIR) && mkdir $(TMPDIR) - $(RUSTC) linker.rs -O - $(RUSTC) reproducible-build-aux.rs -g - $(RUSTC) reproducible-build.rs -C linker=$(call RUN_BINFILE,linker) -g - $(RUSTC) reproducible-build.rs -C linker=$(call RUN_BINFILE,linker) -g - diff -u "$(TMPDIR)/linker-arguments1" "$(TMPDIR)/linker-arguments2" - -opt: - rm -rf $(TMPDIR) && mkdir $(TMPDIR) - $(RUSTC) linker.rs -O - $(RUSTC) reproducible-build-aux.rs -O - $(RUSTC) reproducible-build.rs -C linker=$(call RUN_BINFILE,linker) -O - $(RUSTC) reproducible-build.rs -C linker=$(call RUN_BINFILE,linker) -O - diff -u "$(TMPDIR)/linker-arguments1" "$(TMPDIR)/linker-arguments2" - -link_paths: - rm -rf $(TMPDIR) && mkdir $(TMPDIR) - $(RUSTC) reproducible-build-aux.rs - $(RUSTC) reproducible-build.rs --crate-type rlib -L /b - cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfoo.rlib - $(RUSTC) reproducible-build.rs --crate-type rlib -L /a - cmp "$(TMPDIR)/libreproducible_build.rlib" "$(TMPDIR)/libfoo.rlib" || exit 1 - -remap_paths: - rm -rf $(TMPDIR) && mkdir $(TMPDIR) - $(RUSTC) reproducible-build-aux.rs - $(RUSTC) reproducible-build.rs --crate-type rlib --remap-path-prefix=/a=/c - cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfoo.rlib - $(RUSTC) reproducible-build.rs --crate-type rlib --remap-path-prefix=/b=/c - cmp "$(TMPDIR)/libreproducible_build.rlib" "$(TMPDIR)/libfoo.rlib" || exit 1 - -different_source_dirs_bin: - rm -rf $(TMPDIR) && mkdir $(TMPDIR) - $(RUSTC) reproducible-build-aux.rs - mkdir $(TMPDIR)/test - cp reproducible-build.rs $(TMPDIR)/test - $(RUSTC) reproducible-build.rs --crate-type bin --remap-path-prefix=$$PWD=/b - cp $(TMPDIR)/reproducible-build $(TMPDIR)/foo - (cd $(TMPDIR)/test && $(RUSTC) reproducible-build.rs \ - --remap-path-prefix=$(TMPDIR)/test=/b \ - --crate-type bin) - cmp "$(TMPDIR)/reproducible-build" "$(TMPDIR)/foo" || exit 1 - -different_source_dirs_rlib: - rm -rf $(TMPDIR) && mkdir $(TMPDIR) - $(RUSTC) reproducible-build-aux.rs - mkdir $(TMPDIR)/test - cp reproducible-build.rs $(TMPDIR)/test - $(RUSTC) reproducible-build.rs --crate-type rlib --remap-path-prefix=$$PWD=/b - cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfoo.rlib - (cd $(TMPDIR)/test && $(RUSTC) reproducible-build.rs \ - --remap-path-prefix=$(TMPDIR)/test=/b \ - --crate-type rlib) - cmp "$(TMPDIR)/libreproducible_build.rlib" "$(TMPDIR)/libfoo.rlib" || exit 1 - -remap_cwd_bin: - rm -rf $(TMPDIR) && mkdir $(TMPDIR) - $(RUSTC) reproducible-build-aux.rs - mkdir $(TMPDIR)/test - cp reproducible-build.rs $(TMPDIR)/test - $(RUSTC) reproducible-build.rs --crate-type bin -C debuginfo=2 \ - -Z remap-cwd-prefix=. - cp $(TMPDIR)/reproducible-build $(TMPDIR)/first - (cd $(TMPDIR)/test && \ - $(RUSTC) reproducible-build.rs --crate-type bin -C debuginfo=2 \ - -Z remap-cwd-prefix=.) - cmp "$(TMPDIR)/first" "$(TMPDIR)/reproducible-build" || exit 1 - -remap_cwd_rlib: - rm -rf $(TMPDIR) && mkdir $(TMPDIR) - $(RUSTC) reproducible-build-aux.rs - mkdir $(TMPDIR)/test - cp reproducible-build.rs $(TMPDIR)/test - $(RUSTC) reproducible-build.rs --crate-type rlib -C debuginfo=2 \ - -Z remap-cwd-prefix=. - cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfirst.rlib - (cd $(TMPDIR)/test && \ - $(RUSTC) reproducible-build.rs --crate-type rlib -C debuginfo=2 \ - -Z remap-cwd-prefix=.) - cmp "$(TMPDIR)/libfirst.rlib" "$(TMPDIR)/libreproducible_build.rlib" || exit 1 - -remap_cwd_to_empty: - rm -rf $(TMPDIR) && mkdir $(TMPDIR) - $(RUSTC) reproducible-build-aux.rs - mkdir $(TMPDIR)/test - cp reproducible-build.rs $(TMPDIR)/test - $(RUSTC) reproducible-build.rs --crate-type rlib -C debuginfo=2 \ - -Z remap-cwd-prefix= - cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfirst.rlib - (cd $(TMPDIR)/test && \ - $(RUSTC) reproducible-build.rs --crate-type rlib -C debuginfo=2 \ - -Z remap-cwd-prefix=) - cmp "$(TMPDIR)/libfirst.rlib" "$(TMPDIR)/libreproducible_build.rlib" || exit 1 - -extern_flags: - rm -rf $(TMPDIR) && mkdir $(TMPDIR) - $(RUSTC) reproducible-build-aux.rs - $(RUSTC) reproducible-build.rs \ - --extern reproducible_build_aux=$(TMPDIR)/libreproducible_build_aux.rlib \ - --crate-type rlib - cp $(TMPDIR)/libreproducible_build_aux.rlib $(TMPDIR)/libbar.rlib - cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfoo.rlib - $(RUSTC) reproducible-build.rs \ - --extern reproducible_build_aux=$(TMPDIR)/libbar.rlib \ - --crate-type rlib - cmp "$(TMPDIR)/libreproducible_build.rlib" "$(TMPDIR)/libfoo.rlib" || exit 1 diff --git a/tests/run-make/reproducible-build/rmake.rs b/tests/run-make/reproducible-build/rmake.rs new file mode 100644 index 00000000000..34410d224fb --- /dev/null +++ b/tests/run-make/reproducible-build/rmake.rs @@ -0,0 +1,240 @@ +// This test case makes sure that two identical invocations of the compiler +// (i.e. same code base, same compile-flags, same compiler-versions, etc.) +// produce the same output. In the past, symbol names of monomorphized functions +// were not deterministic (which we want to avoid). +// +// The test tries to exercise as many different paths into symbol name +// generation as possible: +// +// - regular functions +// - generic functions +// - methods +// - statics +// - closures +// - enum variant constructors +// - tuple struct constructors +// - drop glue +// - FnOnce adapters +// - Trait object shims +// - Fn Pointer shims +// See https://github.com/rust-lang/rust/pull/32293 +// Tracking Issue: https://github.com/rust-lang/rust/issues/129080 + +use run_make_support::{ + bin_name, cwd, diff, is_darwin, is_windows, rfs, run_in_tmpdir, rust_lib_name, rustc, +}; + +fn main() { + // Smoke tests. Simple flags, build should be reproducible. + eprintln!("smoke_test => None"); + smoke_test(None); + eprintln!("smoke_test => SmokeFlag::Debug"); + smoke_test(Some(SmokeFlag::Debug)); + eprintln!("smoke_test => SmokeFlag::Opt"); + smoke_test(Some(SmokeFlag::Opt)); + + // Builds should be reproducible even through custom library search paths + // or remap path prefixes. + eprintln!("paths_test => PathsFlag::Link"); + paths_test(PathsFlag::Link); + eprintln!("paths_test => PathsFlag::Remap"); + paths_test(PathsFlag::Remap); + + // Builds should be reproducible even if each build is done in a different directory, + // with both --remap-path-prefix and -Z remap-cwd-prefix. + + // FIXME(Oneirical): Building with crate type set to `bin` AND having -Cdebuginfo=2 + // (or `-g`, the shorthand form) enabled will cause reproducibility failures. + // See https://github.com/rust-lang/rust/issues/89911 + + if !is_darwin() && !is_windows() { + // FIXME(Oneirical): Bin builds are not reproducible on non-Linux targets. + eprintln!("diff_dir_test => Bin, Path"); + diff_dir_test(CrateType::Bin, RemapType::Path); + } + + eprintln!("diff_dir_test => Rlib, Path"); + diff_dir_test(CrateType::Rlib, RemapType::Path); + + // FIXME(Oneirical): This specific case would fail on Linux, should -Cdebuginfo=2 + // be added. + // FIXME(Oneirical): Bin builds are not reproducible on non-Linux targets. + // See https://github.com/rust-lang/rust/issues/89911 + if !is_darwin() && !is_windows() { + eprintln!("diff_dir_test => Bin, Cwd false"); + diff_dir_test(CrateType::Bin, RemapType::Cwd { is_empty: false }); + } + + eprintln!("diff_dir_test => Rlib, Cwd false"); + diff_dir_test(CrateType::Rlib, RemapType::Cwd { is_empty: false }); + eprintln!("diff_dir_test => Rlib, Cwd true"); + diff_dir_test(CrateType::Rlib, RemapType::Cwd { is_empty: true }); + + eprintln!("final extern test"); + // Builds should be reproducible when using the --extern flag. + run_in_tmpdir(|| { + rustc().input("reproducible-build-aux.rs").run(); + rustc() + .input("reproducible-build.rs") + .crate_type("rlib") + .extern_("reproducible_build_aux", rust_lib_name("reproducible_build_aux")) + .run(); + rfs::copy(rust_lib_name("reproducible_build"), rust_lib_name("foo")); + rfs::copy(rust_lib_name("reproducible_build_aux"), rust_lib_name("bar")); + rustc() + .input("reproducible-build.rs") + .crate_type("rlib") + .extern_("reproducible_build_aux", rust_lib_name("bar")) + .run(); + assert!(rfs::read(rust_lib_name("foo")) == rfs::read(rust_lib_name("reproducible_build"))) + }); +} + +#[track_caller] +fn smoke_test(flag: Option) { + run_in_tmpdir(|| { + rustc().input("linker.rs").opt().run(); + rustc().input("reproducible-build-aux.rs").run(); + let mut compiler1 = rustc(); + let mut compiler2 = rustc(); + if let Some(flag) = flag { + match flag { + SmokeFlag::Debug => { + compiler1.arg("-g"); + compiler2.arg("-g"); + } + SmokeFlag::Opt => { + compiler1.opt(); + compiler2.opt(); + } + }; + }; + compiler1 + .input("reproducible-build.rs") + .linker(&cwd().join(bin_name("linker")).display().to_string()) + .run(); + compiler2 + .input("reproducible-build.rs") + .linker(&cwd().join(bin_name("linker")).display().to_string()) + .run(); + diff().actual_file("linker-arguments1").expected_file("linker-arguments2").run(); + }); +} + +#[track_caller] +fn paths_test(flag: PathsFlag) { + run_in_tmpdir(|| { + rustc().input("reproducible-build-aux.rs").run(); + let mut compiler1 = rustc(); + let mut compiler2 = rustc(); + match flag { + PathsFlag::Link => { + compiler1.library_search_path("a"); + compiler2.library_search_path("b"); + } + PathsFlag::Remap => { + compiler1.arg("--remap-path-prefix=/a=/c"); + compiler2.arg("--remap-path-prefix=/b=/c"); + } + } + compiler1.input("reproducible-build.rs").crate_type("rlib").run(); + rfs::rename(rust_lib_name("reproducible_build"), rust_lib_name("foo")); + compiler2.input("reproducible-build.rs").crate_type("rlib").run(); + assert!(rfs::read(rust_lib_name("foo")) == rfs::read(rust_lib_name("reproducible_build"))) + }); +} + +#[track_caller] +fn diff_dir_test(crate_type: CrateType, remap_type: RemapType) { + run_in_tmpdir(|| { + let base_dir = cwd(); + rustc().input("reproducible-build-aux.rs").run(); + rfs::create_dir("test"); + rfs::copy("reproducible-build.rs", "test/reproducible-build.rs"); + let mut compiler1 = rustc(); + let mut compiler2 = rustc(); + match crate_type { + CrateType::Bin => { + compiler1.crate_type("bin"); + compiler2.crate_type("bin"); + } + CrateType::Rlib => { + compiler1.crate_type("rlib"); + compiler2.crate_type("rlib"); + } + } + match remap_type { + RemapType::Path => { + compiler1.arg(&format!("--remap-path-prefix={}=/b", cwd().display())); + compiler2 + .arg(format!("--remap-path-prefix={}=/b", base_dir.join("test").display())); + } + RemapType::Cwd { is_empty } => { + // FIXME(Oneirical): Building with crate type set to `bin` AND having -Cdebuginfo=2 + // (or `-g`, the shorthand form) enabled will cause reproducibility failures + // for multiple platforms. + // See https://github.com/rust-lang/rust/issues/89911 + // FIXME(#129117): Windows rlib + `-Cdebuginfo=2` + `-Z remap-cwd-prefix=.` seems + // to be unreproducible. + if !matches!(crate_type, CrateType::Bin) && !is_windows() { + compiler1.arg("-Cdebuginfo=2"); + compiler2.arg("-Cdebuginfo=2"); + } + if is_empty { + compiler1.arg("-Zremap-cwd-prefix="); + compiler2.arg("-Zremap-cwd-prefix="); + } else { + compiler1.arg("-Zremap-cwd-prefix=."); + compiler2.arg("-Zremap-cwd-prefix=."); + } + } + } + compiler1.input("reproducible-build.rs").run(); + match crate_type { + CrateType::Bin => { + rfs::rename(bin_name("reproducible-build"), bin_name("foo")); + } + CrateType::Rlib => { + rfs::rename(rust_lib_name("reproducible_build"), rust_lib_name("foo")); + } + } + std::env::set_current_dir("test").unwrap(); + compiler2 + .input("reproducible-build.rs") + .library_search_path(&base_dir) + .out_dir(&base_dir) + .run(); + std::env::set_current_dir(&base_dir).unwrap(); + match crate_type { + CrateType::Bin => { + assert!(rfs::read(bin_name("reproducible-build")) == rfs::read(bin_name("foo"))); + } + CrateType::Rlib => { + assert!( + rfs::read(rust_lib_name("foo")) + == rfs::read(rust_lib_name("reproducible_build")) + ); + } + } + }); +} + +enum SmokeFlag { + Debug, + Opt, +} + +enum PathsFlag { + Link, + Remap, +} + +enum CrateType { + Bin, + Rlib, +} + +enum RemapType { + Path, + Cwd { is_empty: bool }, +} diff --git a/tests/run-make/rlib-format-packed-bundled-libs/Makefile b/tests/run-make/rlib-format-packed-bundled-libs/Makefile deleted file mode 100644 index f454da67893..00000000000 --- a/tests/run-make/rlib-format-packed-bundled-libs/Makefile +++ /dev/null @@ -1,39 +0,0 @@ -include ../tools.mk - -# ignore-cross-compile - -# Make sure rlib format with -Zpacked_bundled_libs is correct. - -# We're using the llvm-nm instead of the system nm to ensure it is compatible -# with the LLVM bitcode generated by rustc. -# Except on Windows where piping/IO redirection under MSYS2 is wonky with llvm-nm. -ifndef IS_WINDOWS -NM = "$(LLVM_BIN_DIR)"/llvm-nm -else -NM = nm -endif - -all: $(call NATIVE_STATICLIB,native_dep_1) $(call NATIVE_STATICLIB,native_dep_2) $(call NATIVE_STATICLIB,native_dep_3) - $(RUSTC) rust_dep_up.rs --crate-type=rlib -Zpacked_bundled_libs - $(NM) $(TMPDIR)/librust_dep_up.rlib | $(CGREP) -e "U.*native_f2" - $(NM) $(TMPDIR)/librust_dep_up.rlib | $(CGREP) -e "U.*native_f3" - $(NM) $(TMPDIR)/librust_dep_up.rlib | $(CGREP) -e "T.*rust_dep_up" - $(AR) t $(TMPDIR)/librust_dep_up.rlib | $(CGREP) "native_dep_2" - $(AR) t $(TMPDIR)/librust_dep_up.rlib | $(CGREP) "native_dep_3" - $(RUSTC) rust_dep_local.rs --extern rlib=$(TMPDIR)/librust_dep_up.rlib -Zpacked_bundled_libs --crate-type=rlib - $(NM) $(TMPDIR)/librust_dep_local.rlib | $(CGREP) -e "U.*native_f1" - $(NM) $(TMPDIR)/librust_dep_local.rlib | $(CGREP) -e "T.*rust_dep_local" - $(AR) t $(TMPDIR)/librust_dep_local.rlib | $(CGREP) "native_dep_1" - - # Make sure compiler doesn't use files, that it shouldn't know about. - rm $(TMPDIR)/*native_dep_* - - $(RUSTC) main.rs --extern lib=$(TMPDIR)/librust_dep_local.rlib -o $(TMPDIR)/main.exe -Zpacked_bundled_libs --print link-args | $(CGREP) -e "native_dep_1.*native_dep_2.*native_dep_3" - -ifndef IS_MSVC - $(NM) $(TMPDIR)/main.exe | $(CGREP) -e "T.*native_f1" - $(NM) $(TMPDIR)/main.exe | $(CGREP) -e "T.*native_f2" - $(NM) $(TMPDIR)/main.exe | $(CGREP) -e "T.*native_f3" - $(NM) $(TMPDIR)/main.exe | $(CGREP) -e "T.*rust_dep_local" - $(NM) $(TMPDIR)/main.exe | $(CGREP) -e "T.*rust_dep_up" -endif diff --git a/tests/run-make/rlib-format-packed-bundled-libs/rmake.rs b/tests/run-make/rlib-format-packed-bundled-libs/rmake.rs new file mode 100644 index 00000000000..ff0438a6b72 --- /dev/null +++ b/tests/run-make/rlib-format-packed-bundled-libs/rmake.rs @@ -0,0 +1,84 @@ +// `-Z packed_bundled_libs` is an unstable rustc flag that makes the compiler +// only require a native library and no supplementary object files to compile. +// Output files compiled with this flag should still contain all expected symbols - +// that is what this test checks. +// See https://github.com/rust-lang/rust/pull/100101 + +//@ ignore-cross-compile +// Reason: cross-compilation fails to export native symbols + +use run_make_support::{ + bin_name, build_native_static_lib, cwd, filename_contains, is_msvc, llvm_ar, llvm_nm, rfs, + rust_lib_name, rustc, shallow_find_files, +}; + +fn main() { + build_native_static_lib("native_dep_1"); + build_native_static_lib("native_dep_2"); + build_native_static_lib("native_dep_3"); + rustc().input("rust_dep_up.rs").crate_type("rlib").arg("-Zpacked_bundled_libs").run(); + llvm_nm() + .input(rust_lib_name("rust_dep_up")) + .run() + .assert_stdout_contains_regex("U.*native_f2"); + llvm_nm() + .input(rust_lib_name("rust_dep_up")) + .run() + .assert_stdout_contains_regex("U.*native_f3"); + llvm_nm() + .input(rust_lib_name("rust_dep_up")) + .run() + .assert_stdout_contains_regex("T.*rust_dep_up"); + llvm_ar() + .table_of_contents() + .arg(rust_lib_name("rust_dep_up")) + .run() + .assert_stdout_contains("native_dep_2"); + llvm_ar() + .table_of_contents() + .arg(rust_lib_name("rust_dep_up")) + .run() + .assert_stdout_contains("native_dep_3"); + rustc() + .input("rust_dep_local.rs") + .extern_("rlib", rust_lib_name("rust_dep_up")) + .arg("-Zpacked_bundled_libs") + .crate_type("rlib") + .run(); + llvm_nm() + .input(rust_lib_name("rust_dep_local")) + .run() + .assert_stdout_contains_regex("U.*native_f1"); + llvm_nm() + .input(rust_lib_name("rust_dep_local")) + .run() + .assert_stdout_contains_regex("T.*rust_dep_local"); + llvm_ar() + .table_of_contents() + .arg(rust_lib_name("rust_dep_local")) + .run() + .assert_stdout_contains("native_dep_1"); + + // Ensure the compiler will not use files it should not know about. + for file in shallow_find_files(cwd(), |path| filename_contains(path, "native_dep_")) { + rfs::remove_file(file); + } + + rustc() + .input("main.rs") + .extern_("lib", rust_lib_name("rust_dep_local")) + .output(bin_name("main")) + .arg("-Zpacked_bundled_libs") + .print("link-args") + .run() + .assert_stdout_contains_regex("native_dep_1.*native_dep_2.*native_dep_3"); + + // The binary "main" will not contain any symbols on MSVC. + if !is_msvc() { + llvm_nm().input(bin_name("main")).run().assert_stdout_contains_regex("T.*native_f1"); + llvm_nm().input(bin_name("main")).run().assert_stdout_contains_regex("T.*native_f2"); + llvm_nm().input(bin_name("main")).run().assert_stdout_contains_regex("T.*native_f3"); + llvm_nm().input(bin_name("main")).run().assert_stdout_contains_regex("T.*rust_dep_local"); + llvm_nm().input(bin_name("main")).run().assert_stdout_contains_regex("T.*rust_dep_up"); + } +} diff --git a/tests/run-make/rust-lld-compress-debug-sections/rmake.rs b/tests/run-make/rust-lld-compress-debug-sections/rmake.rs deleted file mode 100644 index ea4997fab80..00000000000 --- a/tests/run-make/rust-lld-compress-debug-sections/rmake.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Checks the `compress-debug-sections` option on rust-lld. - -//@ needs-rust-lld -//@ only-linux -//@ ignore-cross-compile - -// FIXME: This test isn't comprehensive and isn't covering all possible combinations. - -use run_make_support::{assert_contains, llvm_readobj, run_in_tmpdir, rustc}; - -fn check_compression(compression: &str, to_find: &str) { - run_in_tmpdir(|| { - let out = rustc() - .arg("-Zlinker-features=+lld") - .arg("-Clink-self-contained=+linker") - .arg("-Zunstable-options") - .arg("-Cdebuginfo=full") - .link_arg(&format!("-Wl,--compress-debug-sections={compression}")) - .input("main.rs") - .run_unchecked(); - let stderr = out.stderr_utf8(); - if stderr.is_empty() { - llvm_readobj().arg("-t").arg("main").run().assert_stdout_contains(to_find); - } else { - assert_contains( - stderr, - format!( - "LLVM was not built with LLVM_ENABLE_{to_find} \ - or did not find {compression} at build time" - ), - ); - } - }); -} - -fn main() { - check_compression("zlib", "ZLIB"); - check_compression("zstd", "ZSTD"); -} diff --git a/tests/run-make/rustdoc-determinism/rmake.rs b/tests/run-make/rustdoc-determinism/rmake.rs index aa8090174d9..ce088508178 100644 --- a/tests/run-make/rustdoc-determinism/rmake.rs +++ b/tests/run-make/rustdoc-determinism/rmake.rs @@ -7,12 +7,12 @@ use run_make_support::{diff, rustdoc}; fn main() { let foo_first = Path::new("foo_first"); - rustdoc().input("foo.rs").output(&foo_first).run(); - rustdoc().input("bar.rs").output(&foo_first).run(); + rustdoc().input("foo.rs").out_dir(&foo_first).run(); + rustdoc().input("bar.rs").out_dir(&foo_first).run(); let bar_first = Path::new("bar_first"); - rustdoc().input("bar.rs").output(&bar_first).run(); - rustdoc().input("foo.rs").output(&bar_first).run(); + rustdoc().input("bar.rs").out_dir(&bar_first).run(); + rustdoc().input("foo.rs").out_dir(&bar_first).run(); diff() .expected_file(foo_first.join("search-index.js")) diff --git a/tests/run-make/rustdoc-io-error/rmake.rs b/tests/run-make/rustdoc-io-error/rmake.rs index a5fae36e733..31441d7ebc5 100644 --- a/tests/run-make/rustdoc-io-error/rmake.rs +++ b/tests/run-make/rustdoc-io-error/rmake.rs @@ -25,7 +25,7 @@ fn main() { permissions.set_readonly(true); rfs::set_permissions(&out_dir, permissions); - let output = rustdoc().input("foo.rs").output(&out_dir).env("RUST_BACKTRACE", "1").run_fail(); + let output = rustdoc().input("foo.rs").out_dir(&out_dir).env("RUST_BACKTRACE", "1").run_fail(); rfs::set_permissions(&out_dir, original_permissions); diff --git a/tests/run-make/rustdoc-map-file/rmake.rs b/tests/run-make/rustdoc-map-file/rmake.rs index 08f9595ef9f..d7e3510fe31 100644 --- a/tests/run-make/rustdoc-map-file/rmake.rs +++ b/tests/run-make/rustdoc-map-file/rmake.rs @@ -1,13 +1,54 @@ -use run_make_support::{python_command, rustdoc}; +// This test ensures that all items from `foo` are correctly generated into the `redirect-map.json` +// file with `--generate-redirect-map` rustdoc option. + +use std::path::Path; + +use run_make_support::rfs::read_to_string; +use run_make_support::{path, rustdoc, serde_json}; fn main() { let out_dir = "out"; + let crate_name = "foo"; rustdoc() .input("foo.rs") + .crate_name(crate_name) .arg("-Zunstable-options") .arg("--generate-redirect-map") - .output(&out_dir) + .out_dir(&out_dir) .run(); - // FIXME (GuillaumeGomez): Port the python script to Rust as well. - python_command().arg("validate_json.py").arg(&out_dir).run(); + + let generated = read_to_string(path(out_dir).join(crate_name).join("redirect-map.json")); + let expected = read_to_string("expected.json"); + let generated: serde_json::Value = + serde_json::from_str(&generated).expect("failed to parse JSON"); + let expected: serde_json::Value = + serde_json::from_str(&expected).expect("failed to parse JSON"); + let expected = expected.as_object().unwrap(); + + let mut differences = Vec::new(); + for (key, expected_value) in expected.iter() { + match generated.get(key) { + Some(value) => { + if expected_value != value { + differences.push(format!( + "values for key `{key}` don't match: `{expected_value:?}` != `{value:?}`" + )); + } + } + None => differences.push(format!("missing key `{key}`")), + } + } + for (key, data) in generated.as_object().unwrap().iter() { + if !expected.contains_key(key) { + differences.push(format!("Extra data not expected: key: `{key}`, data: `{data}`")); + } + } + + if !differences.is_empty() { + eprintln!("Found differences in JSON files:"); + for diff in differences { + eprintln!("=> {diff}"); + } + panic!("Found differences in JSON files"); + } } diff --git a/tests/run-make/rustdoc-map-file/validate_json.py b/tests/run-make/rustdoc-map-file/validate_json.py deleted file mode 100755 index 912dea3791b..00000000000 --- a/tests/run-make/rustdoc-map-file/validate_json.py +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env python - -import os -import sys -import json - - -def find_redirect_map_file(folder, errors): - for root, _dirs, files in os.walk(folder): - for name in files: - if not name.endswith("redirect-map.json"): - continue - with open(os.path.join(root, name)) as f: - data = json.load(f) - with open("expected.json") as f: - expected = json.load(f) - for key in expected: - if expected[key] != data.get(key): - errors.append("Expected `{}` for key `{}`, found: `{}`".format( - expected[key], key, data.get(key))) - else: - del data[key] - for key in data: - errors.append("Extra data not expected: key: `{}`, data: `{}`".format( - key, data[key])) - return True - return False - - -if len(sys.argv) != 2: - print("Expected doc directory to check!") - sys.exit(1) - -errors = [] -if not find_redirect_map_file(sys.argv[1], errors): - print("Didn't find the map file in `{}`...".format(sys.argv[1])) - sys.exit(1) -for err in errors: - print("=> {}".format(err)) -if len(errors) != 0: - sys.exit(1) diff --git a/tests/run-make/rustdoc-output-path/rmake.rs b/tests/run-make/rustdoc-output-path/rmake.rs index 3c1ccd3a069..181239eac4d 100644 --- a/tests/run-make/rustdoc-output-path/rmake.rs +++ b/tests/run-make/rustdoc-output-path/rmake.rs @@ -6,6 +6,6 @@ use run_make_support::rustdoc; fn main() { let out_dir = Path::new("foo/bar/doc"); - rustdoc().input("foo.rs").output(&out_dir).run(); + rustdoc().input("foo.rs").out_dir(&out_dir).run(); assert!(out_dir.exists()); } diff --git a/tests/run-make/rustdoc-output-stdout/foo.rs b/tests/run-make/rustdoc-output-stdout/foo.rs new file mode 100644 index 00000000000..4a835673a59 --- /dev/null +++ b/tests/run-make/rustdoc-output-stdout/foo.rs @@ -0,0 +1 @@ +pub struct Foo; diff --git a/tests/run-make/rustdoc-output-stdout/rmake.rs b/tests/run-make/rustdoc-output-stdout/rmake.rs new file mode 100644 index 00000000000..dbc9892f3f5 --- /dev/null +++ b/tests/run-make/rustdoc-output-stdout/rmake.rs @@ -0,0 +1,25 @@ +// This test verifies that rustdoc `-o -` prints JSON on stdout and doesn't generate +// a JSON file. + +use std::path::PathBuf; + +use run_make_support::path_helpers::{cwd, has_extension, read_dir_entries_recursive}; +use run_make_support::rustdoc; + +fn main() { + // First we check that we generate the JSON in the stdout. + rustdoc() + .input("foo.rs") + .out_dir("-") + .arg("-Zunstable-options") + .output_format("json") + .run() + .assert_stdout_contains("{\""); + + // Then we check it didn't generate any JSON file. + read_dir_entries_recursive(cwd(), |path| { + if path.is_file() && has_extension(path, "json") { + panic!("Found a JSON file {path:?}"); + } + }); +} diff --git a/tests/run-make/rustdoc-scrape-examples-macros/rmake.rs b/tests/run-make/rustdoc-scrape-examples-macros/rmake.rs index b77df7adc8d..546a0685b4e 100644 --- a/tests/run-make/rustdoc-scrape-examples-macros/rmake.rs +++ b/tests/run-make/rustdoc-scrape-examples-macros/rmake.rs @@ -35,7 +35,7 @@ fn main() { .input("examples/ex.rs") .crate_name("ex") .crate_type("bin") - .output(&out_dir) + .out_dir(&out_dir) .extern_(crate_name, rust_lib_name(crate_name)) .extern_(proc_crate_name, dylib_name.trim()) .arg("-Zunstable-options") @@ -49,7 +49,7 @@ fn main() { .input("src/lib.rs") .crate_name(crate_name) .crate_type("lib") - .output(&out_dir) + .out_dir(&out_dir) .arg("-Zunstable-options") .arg("--with-examples") .arg(&ex_dir) diff --git a/tests/run-make/rustdoc-scrape-examples-remap/scrape.rs b/tests/run-make/rustdoc-scrape-examples-remap/scrape.rs index eca07043b55..c4d7814c3c8 100644 --- a/tests/run-make/rustdoc-scrape-examples-remap/scrape.rs +++ b/tests/run-make/rustdoc-scrape-examples-remap/scrape.rs @@ -20,7 +20,7 @@ pub fn scrape(extra_args: &[&str]) { .input(&dep) .crate_name(&dep_stem) .crate_type("bin") - .output(&out_dir) + .out_dir(&out_dir) .extern_(crate_name, format!("lib{crate_name}.rmeta")) .arg("-Zunstable-options") .arg("--scrape-examples-output-path") @@ -35,7 +35,7 @@ pub fn scrape(extra_args: &[&str]) { let mut rustdoc = rustdoc(); rustdoc .input("src/lib.rs") - .output(&out_dir) + .out_dir(&out_dir) .crate_name(crate_name) .crate_type("lib") .arg("-Zunstable-options"); diff --git a/tests/run-make/rustdoc-target-spec-json-path/rmake.rs b/tests/run-make/rustdoc-target-spec-json-path/rmake.rs index 3246fc56506..fe9587f5022 100644 --- a/tests/run-make/rustdoc-target-spec-json-path/rmake.rs +++ b/tests/run-make/rustdoc-target-spec-json-path/rmake.rs @@ -7,7 +7,7 @@ fn main() { rustc().crate_type("lib").input("dummy_core.rs").target("target.json").run(); rustdoc() .input("my_crate.rs") - .output(out_dir) + .out_dir(out_dir) .library_search_path(cwd()) .target("target.json") .run(); diff --git a/tests/run-make/rustdoc-themes/rmake.rs b/tests/run-make/rustdoc-themes/rmake.rs index 8a961beb9f7..4577e47d47e 100644 --- a/tests/run-make/rustdoc-themes/rmake.rs +++ b/tests/run-make/rustdoc-themes/rmake.rs @@ -27,6 +27,6 @@ fn main() { rfs::create_dir_all(&out_dir); rfs::write(&test_css, test_content); - rustdoc().output(&out_dir).input("foo.rs").arg("--theme").arg(&test_css).run(); + rustdoc().out_dir(&out_dir).input("foo.rs").arg("--theme").arg(&test_css).run(); htmldocck().arg(out_dir).arg("foo.rs").run(); } diff --git a/tests/run-make/rustdoc-with-out-dir-option/rmake.rs b/tests/run-make/rustdoc-with-out-dir-option/rmake.rs index ded89c9ae79..a82a1965a9c 100644 --- a/tests/run-make/rustdoc-with-out-dir-option/rmake.rs +++ b/tests/run-make/rustdoc-with-out-dir-option/rmake.rs @@ -2,6 +2,6 @@ use run_make_support::{htmldocck, rustdoc}; fn main() { let out_dir = "rustdoc"; - rustdoc().input("src/lib.rs").crate_name("foobar").crate_type("lib").output(&out_dir).run(); + rustdoc().input("src/lib.rs").crate_name("foobar").crate_type("lib").out_dir(&out_dir).run(); htmldocck().arg(out_dir).arg("src/lib.rs").run(); } diff --git a/tests/run-make/staticlib-thin-archive/bin.rs b/tests/run-make/staticlib-thin-archive/bin.rs new file mode 100644 index 00000000000..97a2751f20b --- /dev/null +++ b/tests/run-make/staticlib-thin-archive/bin.rs @@ -0,0 +1,5 @@ +fn main() { + unsafe { + rust_lib::simple_fn(); + } +} diff --git a/tests/run-make/staticlib-thin-archive/rmake.rs b/tests/run-make/staticlib-thin-archive/rmake.rs new file mode 100644 index 00000000000..955c50da201 --- /dev/null +++ b/tests/run-make/staticlib-thin-archive/rmake.rs @@ -0,0 +1,23 @@ +// Regression test for https://github.com/rust-lang/rust/issues/107407 which +// checks that rustc can read thin archive. Before the object crate added thin +// archive support rustc would add emit object files to the staticlib and after +// the object crate added thin archive support it would previously crash the +// compiler due to a missing special case for thin archive members. +use run_make_support::{llvm_ar, path, rfs, rust_lib_name, rustc, static_lib_name}; + +fn main() { + rfs::create_dir("archive"); + + // Build a thin archive + rustc().input("simple_obj.rs").emit("obj").output("archive/simple_obj.o").run(); + llvm_ar() + .obj_to_thin_ar() + .output_input(path("archive").join(static_lib_name("thin_archive")), "archive/simple_obj.o") + .run(); + + // Build an rlib which includes the members of this thin archive + rustc().input("rust_lib.rs").library_search_path("archive").run(); + + // Build a binary which requires a symbol from the thin archive + rustc().input("bin.rs").extern_("rust_lib", rust_lib_name("rust_lib")).run(); +} diff --git a/tests/run-make/staticlib-thin-archive/rust_lib.rs b/tests/run-make/staticlib-thin-archive/rust_lib.rs new file mode 100644 index 00000000000..c76b0f25433 --- /dev/null +++ b/tests/run-make/staticlib-thin-archive/rust_lib.rs @@ -0,0 +1,6 @@ +#![crate_type = "rlib"] + +#[link(name = "thin_archive", kind = "static")] +extern "C" { + pub fn simple_fn(); +} diff --git a/tests/run-make/staticlib-thin-archive/simple_obj.rs b/tests/run-make/staticlib-thin-archive/simple_obj.rs new file mode 100644 index 00000000000..a120c9b3e67 --- /dev/null +++ b/tests/run-make/staticlib-thin-archive/simple_obj.rs @@ -0,0 +1,4 @@ +#![crate_type = "staticlib"] + +#[no_mangle] +extern "C" fn simple_fn() {} diff --git a/tests/run-make/sysroot-crates-are-unstable/Makefile b/tests/run-make/sysroot-crates-are-unstable/Makefile deleted file mode 100644 index 1e267fb9576..00000000000 --- a/tests/run-make/sysroot-crates-are-unstable/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -all: - '$(PYTHON)' test.py diff --git a/tests/run-make/sysroot-crates-are-unstable/rmake.rs b/tests/run-make/sysroot-crates-are-unstable/rmake.rs new file mode 100644 index 00000000000..2240d87237b --- /dev/null +++ b/tests/run-make/sysroot-crates-are-unstable/rmake.rs @@ -0,0 +1,102 @@ +// Check that crates in the sysroot are treated as unstable, unless they are +// on a list of known-stable sysroot crates. + +use std::path::{Path, PathBuf}; +use std::str; + +use run_make_support::{rfs, rustc, target}; + +fn is_stable_crate(name: &str) -> bool { + matches!(name, "std" | "alloc" | "core" | "proc_macro") +} + +fn main() { + for cr in get_unstable_sysroot_crates() { + check_crate_is_unstable(&cr); + } + println!("Done"); +} + +#[derive(Debug)] +struct Crate { + name: String, + path: PathBuf, +} + +fn check_crate_is_unstable(cr: &Crate) { + let Crate { name, path } = cr; + + print!("- Verifying that sysroot crate '{name}' is an unstable crate ..."); + + // Trying to use this crate from a user program should fail. + let output = rustc() + .crate_type("rlib") + .target(target()) + .extern_(name, path) + .input("-") + .stdin(format!("extern crate {name};")) + .run_fail(); + + // Make sure it failed for the intended reason, not some other reason. + // (The actual feature required varies between crates.) + output.assert_stderr_contains("use of unstable library feature"); + + println!(" OK"); +} + +fn get_unstable_sysroot_crates() -> Vec { + let sysroot = PathBuf::from(rustc().print("sysroot").run().stdout_utf8().trim()); + let sysroot_libs_dir = sysroot.join("lib").join("rustlib").join(target()).join("lib"); + println!("Sysroot libs dir: {sysroot_libs_dir:?}"); + + // Generate a list of all library crates in the sysroot. + let sysroot_crates = get_all_crates_in_dir(&sysroot_libs_dir); + println!( + "Found {} sysroot crates: {:?}", + sysroot_crates.len(), + sysroot_crates.iter().map(|cr| &cr.name).collect::>() + ); + + // Self-check: If we didn't find `core`, we probably checked the wrong directory. + assert!( + sysroot_crates.iter().any(|cr| cr.name == "core"), + "Couldn't find `core` in {sysroot_libs_dir:?}" + ); + + let unstable_sysroot_crates = + sysroot_crates.into_iter().filter(|cr| !is_stable_crate(&cr.name)).collect::>(); + // Self-check: There should be at least one unstable crate in the directory. + assert!( + !unstable_sysroot_crates.is_empty(), + "Couldn't find any unstable crates in {sysroot_libs_dir:?}" + ); + unstable_sysroot_crates +} + +fn get_all_crates_in_dir(libs_dir: &Path) -> Vec { + let mut libs = vec![]; + rfs::read_dir_entries(libs_dir, |path| { + if !path.is_file() { + return; + } + if let Some(name) = crate_name_from_path(path) { + libs.push(Crate { name, path: path.to_owned() }); + } + }); + libs.sort_by(|a, b| a.name.cmp(&b.name)); + libs +} + +/// Treat a file as a crate if its name begins with `lib` and ends with `.rlib`. +/// The crate name is the part before the first hyphen (if any). +fn crate_name_from_path(path: &Path) -> Option { + let name = path + .file_name()? + .to_str()? + .strip_prefix("lib")? + .strip_suffix(".rlib")? + .split('-') + .next() + .expect("split always yields at least one string"); + Some(name.to_owned()) +} diff --git a/tests/run-make/sysroot-crates-are-unstable/test.py b/tests/run-make/sysroot-crates-are-unstable/test.py deleted file mode 100644 index 45cfdd195b4..00000000000 --- a/tests/run-make/sysroot-crates-are-unstable/test.py +++ /dev/null @@ -1,75 +0,0 @@ -import sys -import os -from os import listdir -from os.path import isfile, join -from subprocess import PIPE, Popen - - -# This is n list of files which are stable crates or simply are not crates, -# we don't check for the instability of these crates as they're all stable! -STABLE_CRATES = ['std', 'alloc', 'core', 'proc_macro', - 'rsbegin.o', 'rsend.o', 'dllcrt2.o', 'crt2.o', 'clang_rt'] - - -def convert_to_string(s): - if s.__class__.__name__ == 'bytes': - return s.decode('utf-8') - return s - - -def set_ld_lib_path(): - var = os.environ.get("LD_LIB_PATH_ENVVAR") - rpath = os.environ.get("HOST_RPATH_DIR") - if var and rpath: - path = os.environ.get(var) - if path: - os.environ[var] = rpath + os.pathsep + path - else: - os.environ[var] = rpath - - -def exec_command(command, to_input=None): - child = None - if to_input is None: - child = Popen(command, stdout=PIPE, stderr=PIPE) - else: - child = Popen(command, stdout=PIPE, stderr=PIPE, stdin=PIPE) - stdout, stderr = child.communicate(input=to_input) - return (convert_to_string(stdout), convert_to_string(stderr)) - - -def check_lib(lib): - if lib['name'] in STABLE_CRATES: - return True - print('verifying if {} is an unstable crate'.format(lib['name'])) - stdout, stderr = exec_command([os.environ['RUSTC'], '-', '--crate-type', 'rlib', - '--target', os.environ['TARGET'], - '--extern', '{}={}'.format(lib['name'], lib['path'])], - to_input=('extern crate {};'.format(lib['name'])).encode('utf-8')) - if 'use of unstable library feature' not in '{}{}'.format(stdout, stderr): - print('crate {} "{}" is not unstable'.format(lib['name'], lib['path'])) - print('{}{}'.format(stdout, stderr)) - print('') - return False - return True - -# Generate a list of all crates in the sysroot. To do this we list all files in -# rustc's sysroot, look at the filename, strip everything after the `-`, and -# strip the leading `lib` (if present) -def get_all_libs(dir_path): - return [{ 'path': join(dir_path, f), 'name': f[3:].split('-')[0] } - for f in listdir(dir_path) - if isfile(join(dir_path, f)) and f.endswith('.rlib') and f not in STABLE_CRATES] - - -set_ld_lib_path() -sysroot = exec_command([os.environ['RUSTC'], '--print', 'sysroot'])[0].replace('\n', '') -assert sysroot, "Could not read the rustc sysroot!" -libs = get_all_libs(join(sysroot, 'lib/rustlib/{}/lib'.format(os.environ['TARGET']))) - -ret = 0 -for lib in libs: - if not check_lib(lib): - # We continue so users can see all the not unstable crates. - ret = 1 -sys.exit(ret) diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/Makefile b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/Makefile deleted file mode 100644 index 3c88ec34f43..00000000000 --- a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -include ../tools.mk - -#only-x86_64-fortanix-unknown-sgx - -# For cargo setting -export RUSTC := $(RUSTC_ORIGINAL) -export LD_LIBRARY_PATH := $(HOST_RPATH_DIR) -# We need to be outside of 'src' dir in order to run cargo -export WORK_DIR := $(TMPDIR) -export TEST_DIR := $(shell pwd) - -## clean up unused env variables which might cause harm. -unexport RUSTC_LINKER -unexport RUSTC_BOOTSTRAP -unexport RUST_BUILD_STAGE -unexport RUST_TEST_THREADS -unexport RUST_TEST_TMPDIR -unexport AR -unexport CC -unexport CXX - -all: - bash script.sh diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/rmake.rs b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/rmake.rs new file mode 100644 index 00000000000..130781a4293 --- /dev/null +++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/rmake.rs @@ -0,0 +1,96 @@ +// ignore-tidy-linelength +// Reason: intel.com link + +// This security test checks that the disassembled form of certain symbols +// is "hardened" - that means, the assembly instructions match a pattern that +// mitigate potential Load Value Injection vulnerabilities. +// To do so, a test crate is compiled, and certain symbols are found, disassembled +// and checked one by one. +// See https://github.com/rust-lang/rust/pull/77008 + +// On load value injection: +// https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/technical-documentation/load-value-injection.html + +//@ only-x86_64-fortanix-unknown-sgx + +use run_make_support::{cmd, cwd, llvm_filecheck, llvm_objdump, regex, set_current_dir, target}; + +fn main() { + let main_dir = cwd(); + set_current_dir("enclave"); + // HACK(eddyb) sets `RUSTC_BOOTSTRAP=1` so Cargo can accept nightly features. + // These come from the top-level Rust workspace, that this crate is not a + // member of, but Cargo tries to load the workspace `Cargo.toml` anyway. + cmd("cargo") + .env("RUSTC_BOOTSTRAP", "1") + .arg("-v") + .arg("run") + .arg("--target") + .arg(target()) + .run(); + set_current_dir(&main_dir); + // Rust has various ways of adding code to a binary: + // - Rust code + // - Inline assembly + // - Global assembly + // - C/C++ code compiled as part of Rust crates + // For those different kinds, we do have very small code examples that should be + // mitigated in some way. Mostly we check that ret instructions should no longer be present. + check("unw_getcontext", "unw_getcontext.checks"); + check("__libunwind_Registers_x86_64_jumpto", "jumpto.checks"); + + check("std::io::stdio::_print::[[:alnum:]]+", "print.with_frame_pointers.checks"); + + check("rust_plus_one_global_asm", "rust_plus_one_global_asm.checks"); + + check("cc_plus_one_c", "cc_plus_one_c.checks"); + check("cc_plus_one_c_asm", "cc_plus_one_c_asm.checks"); + check("cc_plus_one_cxx", "cc_plus_one_cxx.checks"); + check("cc_plus_one_cxx_asm", "cc_plus_one_cxx_asm.checks"); + check("cc_plus_one_asm", "cc_plus_one_asm.checks"); + + check("cmake_plus_one_c", "cmake_plus_one_c.checks"); + check("cmake_plus_one_c_asm", "cmake_plus_one_c_asm.checks"); + check("cmake_plus_one_c_global_asm", "cmake_plus_one_c_global_asm.checks"); + check("cmake_plus_one_cxx", "cmake_plus_one_cxx.checks"); + check("cmake_plus_one_cxx_asm", "cmake_plus_one_cxx_asm.checks"); + check("cmake_plus_one_cxx_global_asm", "cmake_plus_one_cxx_global_asm.checks"); + check("cmake_plus_one_asm", "cmake_plus_one_asm.checks"); +} + +fn check(func_re: &str, mut checks: &str) { + let dump = llvm_objdump() + .input("enclave/target/x86_64-fortanix-unknown-sgx/debug/enclave") + .args(&["--syms", "--demangle"]) + .run() + .stdout_utf8(); + let re = regex::Regex::new(&format!("[[:blank:]]+{func_re}")).unwrap(); + let func = re.find_iter(&dump).map(|m| m.as_str().trim()).collect::>().join(","); + assert!(!func.is_empty()); + let dump = llvm_objdump() + .input("enclave/target/x86_64-fortanix-unknown-sgx/debug/enclave") + .args(&["--demangle", &format!("--disassemble-symbols={func}")]) + .run() + .stdout_utf8(); + let dump = dump.as_bytes(); + + // Unique case, must succeed at one of two possible tests. + // This is because frame pointers are optional, and them being enabled requires + // an additional `popq` in the pattern checking file. + if func_re == "std::io::stdio::_print::[[:alnum:]]+" { + let output = llvm_filecheck().stdin(&dump).patterns(checks).run_unchecked(); + if !output.status().success() { + checks = "print.without_frame_pointers.checks"; + llvm_filecheck().stdin(&dump).patterns(checks).run(); + } + } else { + llvm_filecheck().stdin(&dump).patterns(checks).run(); + } + if !["rust_plus_one_global_asm", "cmake_plus_one_c_global_asm", "cmake_plus_one_cxx_global_asm"] + .contains(&func_re) + { + // The assembler cannot avoid explicit `ret` instructions. Sequences + // of `shlq $0x0, (%rsp); lfence; retq` are used instead. + llvm_filecheck().args(&["--implicit-check-not", "ret"]).stdin(dump).patterns(checks).run(); + } +} diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh deleted file mode 100644 index a7c4ae13ecb..00000000000 --- a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh +++ /dev/null @@ -1,69 +0,0 @@ -#!/bin/bash -set -exuo pipefail - -function build { - CRATE=enclave - - mkdir -p "${WORK_DIR}" - pushd "${WORK_DIR}" - rm -rf "${CRATE}" - cp -a "${TEST_DIR}"/enclave . - pushd $CRATE - echo "${WORK_DIR}" - # HACK(eddyb) sets `RUSTC_BOOTSTRAP=1` so Cargo can accept nightly features. - # These come from the top-level Rust workspace, that this crate is not a - # member of, but Cargo tries to load the workspace `Cargo.toml` anyway. - env RUSTC_BOOTSTRAP=1 - cargo -v run --target "${TARGET}" - popd - popd -} - -function check { - local func_re="$1" - local checks="${TEST_DIR}/$2" - local asm="" - local objdump="${LLVM_BIN_DIR}/llvm-objdump" - local filecheck="${LLVM_BIN_DIR}/FileCheck" - local enclave=${WORK_DIR}/enclave/target/x86_64-fortanix-unknown-sgx/debug/enclave - - asm=$(mktemp) - func="$(${objdump} --syms --demangle "${enclave}" | \ - grep --only-matching -E "[[:blank:]]+${func_re}\$" | \ - sed -e 's/^[[:space:]]*//' )" - ${objdump} --disassemble-symbols="${func}" --demangle \ - "${enclave}" > "${asm}" - ${filecheck} --input-file "${asm}" "${checks}" - - if [ "${func_re}" != "rust_plus_one_global_asm" ] && - [ "${func_re}" != "cmake_plus_one_c_global_asm" ] && - [ "${func_re}" != "cmake_plus_one_cxx_global_asm" ]; then - # The assembler cannot avoid explicit `ret` instructions. Sequences - # of `shlq $0x0, (%rsp); lfence; retq` are used instead. - # https://www.intel.com/content/www/us/en/developer/articles/technical/ - # software-security-guidance/technical-documentation/load-value-injection.html - ${filecheck} --implicit-check-not ret --input-file "${asm}" "${checks}" - fi -} - -build - -check "unw_getcontext" unw_getcontext.checks -check "__libunwind_Registers_x86_64_jumpto" jumpto.checks -check 'std::io::stdio::_print::[[:alnum:]]+' print.with_frame_pointers.checks || - check 'std::io::stdio::_print::[[:alnum:]]+' print.without_frame_pointers.checks -check rust_plus_one_global_asm rust_plus_one_global_asm.checks - -check cc_plus_one_c cc_plus_one_c.checks -check cc_plus_one_c_asm cc_plus_one_c_asm.checks -check cc_plus_one_cxx cc_plus_one_cxx.checks -check cc_plus_one_cxx_asm cc_plus_one_cxx_asm.checks -check cc_plus_one_asm cc_plus_one_asm.checks - -check cmake_plus_one_c cmake_plus_one_c.checks -check cmake_plus_one_c_asm cmake_plus_one_c_asm.checks -check cmake_plus_one_c_global_asm cmake_plus_one_c_global_asm.checks -check cmake_plus_one_cxx cmake_plus_one_cxx.checks -check cmake_plus_one_cxx_asm cmake_plus_one_cxx_asm.checks -check cmake_plus_one_cxx_global_asm cmake_plus_one_cxx_global_asm.checks -check cmake_plus_one_asm cmake_plus_one_asm.checks diff --git a/tests/rustdoc-gui/target.goml b/tests/rustdoc-gui/target.goml index 82bd34ed274..92846f8e01d 100644 --- a/tests/rustdoc-gui/target.goml +++ b/tests/rustdoc-gui/target.goml @@ -11,7 +11,7 @@ define-function: ( [theme, background, border], block { call-function: ("switch-theme", {"theme": |theme|}) - assert-css: ("#method\.a_method:target", { + wait-for-css: ("#method\.a_method:target", { "background-color": |background|, "border-right": "3px solid " + |border|, }) diff --git a/tests/rustdoc-js-std/exact-case.js b/tests/rustdoc-js-std/exact-case.js new file mode 100644 index 00000000000..d9faff22fff --- /dev/null +++ b/tests/rustdoc-js-std/exact-case.js @@ -0,0 +1,7 @@ +const EXPECTED = { + 'query': 'Copy', + 'others': [ + { 'path': 'std::marker', 'name': 'Copy' }, + { 'path': 'std::fs', 'name': 'copy' }, + ], +} diff --git a/tests/rustdoc-json/impl-trait-precise-capturing.rs b/tests/rustdoc-json/impl-trait-precise-capturing.rs index f9fee788ffe..0c116a10290 100644 --- a/tests/rustdoc-json/impl-trait-precise-capturing.rs +++ b/tests/rustdoc-json/impl-trait-precise-capturing.rs @@ -1,5 +1,3 @@ -#![feature(precise_capturing)] - //@ is "$.index[*][?(@.name=='hello')].inner.function.decl.output.impl_trait[1].use[0]" \"\'a\" //@ is "$.index[*][?(@.name=='hello')].inner.function.decl.output.impl_trait[1].use[1]" \"T\" //@ is "$.index[*][?(@.name=='hello')].inner.function.decl.output.impl_trait[1].use[2]" \"N\" diff --git a/tests/rustdoc-ui/2024-doctests-checks.rs b/tests/rustdoc-ui/2024-doctests-checks.rs new file mode 100644 index 00000000000..464cf5b200d --- /dev/null +++ b/tests/rustdoc-ui/2024-doctests-checks.rs @@ -0,0 +1,27 @@ +//@ check-pass +//@ compile-flags: --test --test-args=--test-threads=1 -Zunstable-options --edition 2024 +//@ normalize-stdout-test: "tests/rustdoc-ui" -> "$$DIR" +//@ normalize-stdout-test: "finished in \d+\.\d+s" -> "finished in $$TIME" +//@ normalize-stdout-test: ".rs:\d+:\d+" -> ".rs:$$LINE:$$COL" + +/// ``` +/// let x = 12; +/// ``` +/// +/// This one should not be a merged doctest (because of `$crate`). The output +/// will confirm it by displaying both merged and standalone doctest passes. +/// +/// ``` +/// macro_rules! bla { +/// () => {{ +/// $crate::foo(); +/// }} +/// } +/// +/// fn foo() {} +/// +/// fn main() { +/// bla!(); +/// } +/// ``` +pub struct Foo; diff --git a/tests/rustdoc-ui/2024-doctests-checks.stdout b/tests/rustdoc-ui/2024-doctests-checks.stdout new file mode 100644 index 00000000000..d1064084a85 --- /dev/null +++ b/tests/rustdoc-ui/2024-doctests-checks.stdout @@ -0,0 +1,12 @@ + +running 1 test +test $DIR/2024-doctests-checks.rs - Foo (line 7) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + + +running 1 test +test $DIR/2024-doctests-checks.rs - Foo (line 14) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/tests/rustdoc-ui/2024-doctests-crate-attribute.rs b/tests/rustdoc-ui/2024-doctests-crate-attribute.rs new file mode 100644 index 00000000000..4984fdfe194 --- /dev/null +++ b/tests/rustdoc-ui/2024-doctests-crate-attribute.rs @@ -0,0 +1,22 @@ +//@ check-pass +//@ compile-flags: --test --test-args=--test-threads=1 -Zunstable-options --edition 2024 +//@ normalize-stdout-test: "tests/rustdoc-ui" -> "$$DIR" +//@ normalize-stdout-test: "finished in \d+\.\d+s" -> "finished in $$TIME" +//@ normalize-stdout-test: ".rs:\d+:\d+" -> ".rs:$$LINE:$$COL" + +/// This doctest is used to ensure that if a crate attribute is present, +/// it will not be part of the merged doctests. +/// +/// ``` +/// #![doc(html_playground_url = "foo")] +/// +/// pub struct Bar; +/// ``` +/// +/// This one will allow us to confirm that the doctest above will be a +/// standalone one (there will be two separate doctests passes). +/// +/// ``` +/// let x = 12; +/// ``` +pub struct Foo; diff --git a/tests/rustdoc-ui/2024-doctests-crate-attribute.stdout b/tests/rustdoc-ui/2024-doctests-crate-attribute.stdout new file mode 100644 index 00000000000..29702ce8929 --- /dev/null +++ b/tests/rustdoc-ui/2024-doctests-crate-attribute.stdout @@ -0,0 +1,12 @@ + +running 1 test +test $DIR/2024-doctests-crate-attribute.rs - Foo (line 19) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + + +running 1 test +test $DIR/2024-doctests-crate-attribute.rs - Foo (line 10) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/tests/rustdoc-ui/doctest/failed-doctest-should-panic-2021.rs b/tests/rustdoc-ui/doctest/failed-doctest-should-panic-2021.rs new file mode 100644 index 00000000000..4fe513b4066 --- /dev/null +++ b/tests/rustdoc-ui/doctest/failed-doctest-should-panic-2021.rs @@ -0,0 +1,12 @@ +// FIXME: if/when the output of the test harness can be tested on its own, this test should be +// adapted to use that, and that normalize line can go away + +//@ compile-flags:--test --edition 2021 +//@ normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR" +//@ normalize-stdout-test: "finished in \d+\.\d+s" -> "finished in $$TIME" +//@ failure-status: 101 + +/// ```should_panic +/// println!("Hello, world!"); +/// ``` +pub struct Foo; diff --git a/tests/rustdoc-ui/doctest/failed-doctest-should-panic-2021.stdout b/tests/rustdoc-ui/doctest/failed-doctest-should-panic-2021.stdout new file mode 100644 index 00000000000..63d987de8a9 --- /dev/null +++ b/tests/rustdoc-ui/doctest/failed-doctest-should-panic-2021.stdout @@ -0,0 +1,14 @@ + +running 1 test +test $DIR/failed-doctest-should-panic-2021.rs - Foo (line 9) ... FAILED + +failures: + +---- $DIR/failed-doctest-should-panic-2021.rs - Foo (line 9) stdout ---- +Test executable succeeded, but it's marked `should_panic`. + +failures: + $DIR/failed-doctest-should-panic-2021.rs - Foo (line 9) + +test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/tests/rustdoc-ui/doctest/failed-doctest-should-panic.rs b/tests/rustdoc-ui/doctest/failed-doctest-should-panic.rs index b24687993e5..4018e37105f 100644 --- a/tests/rustdoc-ui/doctest/failed-doctest-should-panic.rs +++ b/tests/rustdoc-ui/doctest/failed-doctest-should-panic.rs @@ -1,7 +1,7 @@ // FIXME: if/when the output of the test harness can be tested on its own, this test should be // adapted to use that, and that normalize line can go away -//@ compile-flags:--test +//@ compile-flags:--test -Z unstable-options --edition 2024 //@ normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR" //@ normalize-stdout-test: "finished in \d+\.\d+s" -> "finished in $$TIME" //@ failure-status: 101 diff --git a/tests/rustdoc-ui/doctest/failed-doctest-should-panic.stdout b/tests/rustdoc-ui/doctest/failed-doctest-should-panic.stdout index 57a20092a5d..cb3456e087e 100644 --- a/tests/rustdoc-ui/doctest/failed-doctest-should-panic.stdout +++ b/tests/rustdoc-ui/doctest/failed-doctest-should-panic.stdout @@ -1,11 +1,11 @@ running 1 test -test $DIR/failed-doctest-should-panic.rs - Foo (line 9) ... FAILED +test $DIR/failed-doctest-should-panic.rs - Foo (line 9) - should panic ... FAILED failures: ---- $DIR/failed-doctest-should-panic.rs - Foo (line 9) stdout ---- -Test executable succeeded, but it's marked `should_panic`. +note: test did not panic as expected failures: $DIR/failed-doctest-should-panic.rs - Foo (line 9) diff --git a/tests/rustdoc-ui/doctest/merged-ignore-no_run.rs b/tests/rustdoc-ui/doctest/merged-ignore-no_run.rs new file mode 100644 index 00000000000..4c21d542951 --- /dev/null +++ b/tests/rustdoc-ui/doctest/merged-ignore-no_run.rs @@ -0,0 +1,14 @@ +//@ compile-flags:--test --test-args=--test-threads=1 -Zunstable-options --edition 2024 +//@ normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR" +//@ normalize-stdout-test: "finished in \d+\.\d+s" -> "finished in $$TIME" +//@ check-pass + +/// ```ignore (test) +/// let x = 12; +/// ``` +pub fn ignored() {} + +/// ```no_run +/// panic!("blob"); +/// ``` +pub fn no_run() {} diff --git a/tests/rustdoc-ui/doctest/merged-ignore-no_run.stdout b/tests/rustdoc-ui/doctest/merged-ignore-no_run.stdout new file mode 100644 index 00000000000..f2cb1e7e72f --- /dev/null +++ b/tests/rustdoc-ui/doctest/merged-ignore-no_run.stdout @@ -0,0 +1,7 @@ + +running 2 tests +test $DIR/merged-ignore-no_run.rs - ignored (line 6) ... ignored +test $DIR/merged-ignore-no_run.rs - no_run (line 11) - compile ... ok + +test result: ok. 1 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/tests/rustdoc-ui/doctest/wrong-ast-2024.rs b/tests/rustdoc-ui/doctest/wrong-ast-2024.rs new file mode 100644 index 00000000000..7b4fa8fd2c9 --- /dev/null +++ b/tests/rustdoc-ui/doctest/wrong-ast-2024.rs @@ -0,0 +1,20 @@ +//@ compile-flags:--test --test-args=--test-threads=1 -Zunstable-options --edition 2024 +//@ normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR" +//@ normalize-stdout-test: "finished in \d+\.\d+s" -> "finished in $$TIME" +//@ normalize-stdout-test: ".rs:\d+:\d+" -> ".rs:$$LINE:$$COL" +//@ failure-status: 101 + +/// ``` +/// /* plop +/// ``` +pub fn one() {} + +/// ``` +/// } mod __doctest_1 { fn main() { +/// ``` +pub fn two() {} + +/// ```should_panic +/// panic!() +/// ``` +pub fn three() {} diff --git a/tests/rustdoc-ui/doctest/wrong-ast-2024.stdout b/tests/rustdoc-ui/doctest/wrong-ast-2024.stdout new file mode 100644 index 00000000000..22c8ce468fd --- /dev/null +++ b/tests/rustdoc-ui/doctest/wrong-ast-2024.stdout @@ -0,0 +1,41 @@ + +running 1 test +test $DIR/wrong-ast-2024.rs - three (line 17) - should panic ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + + +running 2 tests +test $DIR/wrong-ast-2024.rs - one (line 7) ... FAILED +test $DIR/wrong-ast-2024.rs - two (line 12) ... FAILED + +failures: + +---- $DIR/wrong-ast-2024.rs - one (line 7) stdout ---- +error[E0758]: unterminated block comment + --> $DIR/wrong-ast-2024.rs:$LINE:$COL + | +LL | /* plop + | ^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0758`. +Couldn't compile the test. +---- $DIR/wrong-ast-2024.rs - two (line 12) stdout ---- +error: unexpected closing delimiter: `}` + --> $DIR/wrong-ast-2024.rs:$LINE:$COL + | +LL | } mod __doctest_1 { fn main() { + | ^ unexpected closing delimiter + +error: aborting due to 1 previous error + +Couldn't compile the test. + +failures: + $DIR/wrong-ast-2024.rs - one (line 7) + $DIR/wrong-ast-2024.rs - two (line 12) + +test result: FAILED. 0 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/tests/rustdoc-ui/doctest/wrong-ast.rs b/tests/rustdoc-ui/doctest/wrong-ast.rs new file mode 100644 index 00000000000..92286b33dcf --- /dev/null +++ b/tests/rustdoc-ui/doctest/wrong-ast.rs @@ -0,0 +1,19 @@ +//@ compile-flags:--test --test-args=--test-threads=1 +//@ normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR" +//@ normalize-stdout-test: "finished in \d+\.\d+s" -> "finished in $$TIME" +//@ failure-status: 101 + +/// ``` +/// /* plop +/// ``` +pub fn one() {} + +/// ``` +/// } mod __doctest_1 { fn main() { +/// ``` +pub fn two() {} + +/// ```should_panic +/// panic!() +/// ``` +pub fn three() {} diff --git a/tests/rustdoc-ui/doctest/wrong-ast.stdout b/tests/rustdoc-ui/doctest/wrong-ast.stdout new file mode 100644 index 00000000000..15494706c16 --- /dev/null +++ b/tests/rustdoc-ui/doctest/wrong-ast.stdout @@ -0,0 +1,36 @@ + +running 3 tests +test $DIR/wrong-ast.rs - one (line 6) ... FAILED +test $DIR/wrong-ast.rs - three (line 16) ... ok +test $DIR/wrong-ast.rs - two (line 11) ... FAILED + +failures: + +---- $DIR/wrong-ast.rs - one (line 6) stdout ---- +error[E0758]: unterminated block comment + --> $DIR/wrong-ast.rs:7:1 + | +LL | /* plop + | ^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0758`. +Couldn't compile the test. +---- $DIR/wrong-ast.rs - two (line 11) stdout ---- +error: unexpected closing delimiter: `}` + --> $DIR/wrong-ast.rs:12:1 + | +LL | } mod __doctest_1 { fn main() { + | ^ unexpected closing delimiter + +error: aborting due to 1 previous error + +Couldn't compile the test. + +failures: + $DIR/wrong-ast.rs - one (line 6) + $DIR/wrong-ast.rs - two (line 11) + +test result: FAILED. 1 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/tests/rustdoc-ui/generate-link-to-definition/generate-link-to-definition-opt.rs b/tests/rustdoc-ui/generate-link-to-definition/generate-link-to-definition-opt.rs index f11b94bb036..babdbd0a692 100644 --- a/tests/rustdoc-ui/generate-link-to-definition/generate-link-to-definition-opt.rs +++ b/tests/rustdoc-ui/generate-link-to-definition/generate-link-to-definition-opt.rs @@ -2,5 +2,6 @@ // option can only be used with HTML generation. //@ compile-flags: -Zunstable-options --generate-link-to-definition --output-format json +//@ check-pass pub fn f() {} diff --git a/tests/rustdoc-ui/generate-link-to-definition/generate-link-to-definition-opt.stderr b/tests/rustdoc-ui/generate-link-to-definition/generate-link-to-definition-opt.stderr index 4c8c607e7da..62b0e3ce408 100644 --- a/tests/rustdoc-ui/generate-link-to-definition/generate-link-to-definition-opt.stderr +++ b/tests/rustdoc-ui/generate-link-to-definition/generate-link-to-definition-opt.stderr @@ -1,2 +1,4 @@ -error: --generate-link-to-definition option can only be used with HTML output format +warning: `--generate-link-to-definition` option can only be used with HTML output format + | + = note: `--generate-link-to-definition` option will be ignored diff --git a/tests/rustdoc-ui/generate-link-to-definition/generate-link-to-definition-opt2.rs b/tests/rustdoc-ui/generate-link-to-definition/generate-link-to-definition-opt2.rs deleted file mode 100644 index 71852205979..00000000000 --- a/tests/rustdoc-ui/generate-link-to-definition/generate-link-to-definition-opt2.rs +++ /dev/null @@ -1,6 +0,0 @@ -// This test purpose is to check that the "--generate-link-to-definition" -// option can only be used with HTML generation. - -//@ compile-flags: -Zunstable-options --generate-link-to-definition --show-coverage - -pub fn f() {} diff --git a/tests/rustdoc-ui/generate-link-to-definition/generate-link-to-definition-opt2.stderr b/tests/rustdoc-ui/generate-link-to-definition/generate-link-to-definition-opt2.stderr deleted file mode 100644 index 4c8c607e7da..00000000000 --- a/tests/rustdoc-ui/generate-link-to-definition/generate-link-to-definition-opt2.stderr +++ /dev/null @@ -1,2 +0,0 @@ -error: --generate-link-to-definition option can only be used with HTML output format - diff --git a/tests/rustdoc-ui/unportable-markdown.rs b/tests/rustdoc-ui/unportable-markdown.rs index 8035e680f3c..105fc1e59d5 100644 --- a/tests/rustdoc-ui/unportable-markdown.rs +++ b/tests/rustdoc-ui/unportable-markdown.rs @@ -19,7 +19,6 @@ pub struct GfmFootnotes; /// /// /// test [^foo][^bar] -//~^ ERROR unportable markdown /// /// [^foo]: test /// [^bar]: test2 diff --git a/tests/rustdoc-ui/unportable-markdown.stderr b/tests/rustdoc-ui/unportable-markdown.stderr index b524aca25ae..952ae4bb6ee 100644 --- a/tests/rustdoc-ui/unportable-markdown.stderr +++ b/tests/rustdoc-ui/unportable-markdown.stderr @@ -1,31 +1,15 @@ error: unportable markdown - --> $DIR/unportable-markdown.rs:21:10 - | -LL | /// test [^foo][^bar] - | ^^^^^^ - | - = help: confusing footnote reference and link -note: the lint level is defined here - --> $DIR/unportable-markdown.rs:8:9 - | -LL | #![deny(rustdoc::unportable_markdown)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: if it should not be a footnote, escape it - | -LL | /// test \[^foo][^bar] - | + -help: if the footnote is intended, add a space - | -LL | /// test [^foo] [^bar] - | + - -error: unportable markdown - --> $DIR/unportable-markdown.rs:49:5 + --> $DIR/unportable-markdown.rs:48:5 | LL | /// >bar | ^ | = help: confusing block quote with no space after the `>` marker +note: the lint level is defined here + --> $DIR/unportable-markdown.rs:8:9 + | +LL | #![deny(rustdoc::unportable_markdown)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if the quote is intended, add a space | LL | /// > bar @@ -35,5 +19,5 @@ help: if it should not be a quote, escape it LL | /// \>bar | + -error: aborting due to 2 previous errors +error: aborting due to 1 previous error diff --git a/tests/rustdoc/anchors.no_type_anchor2.html b/tests/rustdoc/anchors.no_type_anchor2.html index 71e93990e29..9127104ded4 100644 --- a/tests/rustdoc/anchors.no_type_anchor2.html +++ b/tests/rustdoc/anchors.no_type_anchor2.html @@ -1 +1 @@ -

    pub type Y = u32

    \ No newline at end of file +
    source

    pub type Y = u32

    \ No newline at end of file diff --git a/tests/rustdoc/assoc-type-source-link.rs b/tests/rustdoc/assoc-type-source-link.rs new file mode 100644 index 00000000000..34b156b9649 --- /dev/null +++ b/tests/rustdoc/assoc-type-source-link.rs @@ -0,0 +1,26 @@ +// This test ensures that the source links are generated for impl associated types. + +#![crate_name = "foo"] +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +//@ has 'foo/struct.Bar.html' +pub struct Bar; + +impl Bar { + //@ has - '//*[@id="implementations-list"]//*[@id="associatedtype.Y"]/a' 'source' + //@ has - '//*[@id="implementations-list"]//*[@id="associatedtype.Y"]/a/@href' \ + // '../src/foo/assoc-type-source-link.rs.html#14' + pub type Y = u8; +} + +pub trait Foo { + type Z; +} + +impl Foo for Bar { + //@ has - '//*[@id="trait-implementations-list"]//*[@id="associatedtype.Z"]/a' 'source' + //@ has - '//*[@id="trait-implementations-list"]//*[@id="associatedtype.Z"]/a/@href' \ + // '../src/foo/assoc-type-source-link.rs.html#25' + type Z = u8; +} diff --git a/tests/rustdoc/doc-hidden-crate.rs b/tests/rustdoc/doc-hidden-crate.rs new file mode 100644 index 00000000000..dac557107a9 --- /dev/null +++ b/tests/rustdoc/doc-hidden-crate.rs @@ -0,0 +1,27 @@ +// Regression test for . +// `doc(hidden)` should still be able to hide extern crates, only the local crates +// cannot be hidden because we still need to generate its `index.html` file. + +#![crate_name = "foo"] +#![doc(hidden)] + +//@ has 'foo/index.html' +// First we check that the page contains the crate name (`foo`). +//@ has - '//*' 'foo' +// But doesn't contain any of the other items. +//@ !has - '//*' 'other' +//@ !has - '//*' 'marker' +//@ !has - '//*' 'PhantomData' + +#[doc(inline)] +pub use std as other; + +#[doc(inline)] +pub use std::marker; + +#[doc(inline)] +pub use std::marker::PhantomData; + +//@ !has - '//*' 'myself' +#[doc(inline)] +pub use crate as myself; diff --git a/tests/rustdoc/impl-trait-precise-capturing.rs b/tests/rustdoc/impl-trait-precise-capturing.rs index a964a1f8518..3ec8c578013 100644 --- a/tests/rustdoc/impl-trait-precise-capturing.rs +++ b/tests/rustdoc/impl-trait-precise-capturing.rs @@ -1,7 +1,6 @@ //@ aux-build:precise-capturing.rs #![crate_name = "foo"] -#![feature(precise_capturing)] extern crate precise_capturing; diff --git a/tests/rustdoc/primitive-tuple-variadic.rs b/tests/rustdoc/primitive-tuple-variadic.rs index 4b2fb786a89..b15e996f929 100644 --- a/tests/rustdoc/primitive-tuple-variadic.rs +++ b/tests/rustdoc/primitive-tuple-variadic.rs @@ -16,3 +16,20 @@ pub trait Bar {} //@ has - '//section[@id="impl-Bar-for-(U,)"]/h3' 'impl Bar for (U₁, U₂, …, Uₙ)' #[doc(fake_variadic)] impl Bar for (U,) {} + +pub trait Baz { fn baz(&self) -> T { todo!() } } + +//@ has foo/trait.Baz.html +//@ has - '//section[@id="impl-Baz%3C(T,)%3E-for-%5BT;+1%5D"]/h3' 'impl Baz<(T₁, T₂, …, Tₙ)> for [T; N]' +#[doc(fake_variadic)] +impl Baz<(T,)> for [T; 1] {} + +//@ has foo/trait.Baz.html +//@ has - '//section[@id="impl-Baz%3C%5BT;+1%5D%3E-for-(T,)"]/h3' 'impl Baz<[T; N]> for (T₁, T₂, …, Tₙ)' +#[doc(fake_variadic)] +impl Baz<[T; 1]> for (T,) {} + +//@ has foo/trait.Baz.html +//@ has - '//section[@id="impl-Baz%3CT%3E-for-(T,)"]/h3' 'impl Baz for (T₁, T₂, …, Tₙ)' +#[doc(fake_variadic)] +impl Baz for (T,) {} diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.rs b/tests/ui-fulldeps/internal-lints/diagnostics.rs index 5fcff74064a..442f9d72c3f 100644 --- a/tests/ui-fulldeps/internal-lints/diagnostics.rs +++ b/tests/ui-fulldeps/internal-lints/diagnostics.rs @@ -117,4 +117,11 @@ pub fn skipped_because_of_annotation<'a>(dcx: DiagCtxtHandle<'a>) { fn f(_x: impl Into, _y: impl Into) {} fn g() { f(crate::fluent_generated::no_crate_example, crate::fluent_generated::no_crate_example); + f("untranslatable diagnostic", crate::fluent_generated::no_crate_example); + //~^ ERROR diagnostics should be created using translatable messages + f(crate::fluent_generated::no_crate_example, "untranslatable diagnostic"); + //~^ ERROR diagnostics should be created using translatable messages + f("untranslatable diagnostic", "untranslatable diagnostic"); + //~^ ERROR diagnostics should be created using translatable messages + //~^^ ERROR diagnostics should be created using translatable messages } diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.stderr b/tests/ui-fulldeps/internal-lints/diagnostics.stderr index 669324ce5d4..36dd3cf4be7 100644 --- a/tests/ui-fulldeps/internal-lints/diagnostics.stderr +++ b/tests/ui-fulldeps/internal-lints/diagnostics.stderr @@ -1,8 +1,8 @@ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:43:9 + --> $DIR/diagnostics.rs:43:31 | LL | Diag::new(dcx, level, "untranslatable diagnostic") - | ^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here --> $DIR/diagnostics.rs:7:9 @@ -11,16 +11,16 @@ LL | #![deny(rustc::untranslatable_diagnostic)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:64:14 + --> $DIR/diagnostics.rs:64:19 | LL | diag.note("untranslatable diagnostic"); - | ^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:85:14 + --> $DIR/diagnostics.rs:85:19 | LL | diag.note("untranslatable diagnostic"); - | ^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostics should only be created in `Diagnostic`/`Subdiagnostic`/`LintDiagnostic` impls --> $DIR/diagnostics.rs:99:21 @@ -41,10 +41,34 @@ LL | let _diag = dcx.struct_err("untranslatable diagnostic"); | ^^^^^^^^^^ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:102:21 + --> $DIR/diagnostics.rs:102:32 | LL | let _diag = dcx.struct_err("untranslatable diagnostic"); - | ^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 6 previous errors +error: diagnostics should be created using translatable messages + --> $DIR/diagnostics.rs:120:7 + | +LL | f("untranslatable diagnostic", crate::fluent_generated::no_crate_example); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: diagnostics should be created using translatable messages + --> $DIR/diagnostics.rs:122:50 + | +LL | f(crate::fluent_generated::no_crate_example, "untranslatable diagnostic"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: diagnostics should be created using translatable messages + --> $DIR/diagnostics.rs:124:7 + | +LL | f("untranslatable diagnostic", "untranslatable diagnostic"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: diagnostics should be created using translatable messages + --> $DIR/diagnostics.rs:124:36 + | +LL | f("untranslatable diagnostic", "untranslatable diagnostic"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 10 previous errors diff --git a/tests/ui-fulldeps/stable-mir/check_instance.rs b/tests/ui-fulldeps/stable-mir/check_instance.rs index 5e3f2557566..5449c09d35a 100644 --- a/tests/ui-fulldeps/stable-mir/check_instance.rs +++ b/tests/ui-fulldeps/stable-mir/check_instance.rs @@ -17,12 +17,14 @@ extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use mir::{mono::Instance, TerminatorKind::*}; +use std::io::Write; +use std::ops::ControlFlow; + +use mir::mono::Instance; +use mir::TerminatorKind::*; use rustc_smir::rustc_internal; use stable_mir::ty::{RigidTy, TyKind}; use stable_mir::*; -use std::io::Write; -use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; @@ -33,7 +35,7 @@ fn test_stable_mir() -> ControlFlow<()> { // Get all items and split generic vs monomorphic items. let (generic, mono): (Vec<_>, Vec<_>) = items.into_iter().partition(|item| item.requires_monomorphization()); - assert_eq!(mono.len(), 3, "Expected 3 mono functions"); + assert_eq!(mono.len(), 4, "Expected 3 mono functions"); assert_eq!(generic.len(), 2, "Expected 2 generic functions"); // For all monomorphic items, get the correspondent instances. diff --git a/tests/ui/abi/c-zst.other-linux.stderr b/tests/ui/abi/c-zst.other-linux.stderr new file mode 100644 index 00000000000..5a656e6ea66 --- /dev/null +++ b/tests/ui/abi/c-zst.other-linux.stderr @@ -0,0 +1,67 @@ +error: fn_abi_of(pass_zst) = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: (), + layout: Layout { + size: Size(0 bytes), + align: AbiAndPrefAlign { + abi: $SOME_ALIGN, + pref: $SOME_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + }, + }, + mode: Ignore, + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: (), + layout: Layout { + size: Size(0 bytes), + align: AbiAndPrefAlign { + abi: $SOME_ALIGN, + pref: $SOME_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + }, + }, + mode: Ignore, + }, + c_variadic: false, + fixed_count: 1, + conv: C, + can_unwind: false, + } + --> $DIR/c-zst.rs:27:1 + | +LL | extern "C" fn pass_zst(_: ()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/abi/c-zst.other.stderr b/tests/ui/abi/c-zst.other.stderr new file mode 100644 index 00000000000..5a656e6ea66 --- /dev/null +++ b/tests/ui/abi/c-zst.other.stderr @@ -0,0 +1,67 @@ +error: fn_abi_of(pass_zst) = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: (), + layout: Layout { + size: Size(0 bytes), + align: AbiAndPrefAlign { + abi: $SOME_ALIGN, + pref: $SOME_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + }, + }, + mode: Ignore, + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: (), + layout: Layout { + size: Size(0 bytes), + align: AbiAndPrefAlign { + abi: $SOME_ALIGN, + pref: $SOME_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + }, + }, + mode: Ignore, + }, + c_variadic: false, + fixed_count: 1, + conv: C, + can_unwind: false, + } + --> $DIR/c-zst.rs:27:1 + | +LL | extern "C" fn pass_zst(_: ()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/abi/c-zst.powerpc-linux.stderr b/tests/ui/abi/c-zst.powerpc-linux.stderr new file mode 100644 index 00000000000..ba9738050d8 --- /dev/null +++ b/tests/ui/abi/c-zst.powerpc-linux.stderr @@ -0,0 +1,78 @@ +error: fn_abi_of(pass_zst) = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: (), + layout: Layout { + size: Size(0 bytes), + align: AbiAndPrefAlign { + abi: $SOME_ALIGN, + pref: $SOME_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + }, + }, + mode: Indirect { + attrs: ArgAttributes { + regular: NoAlias | NoCapture | NonNull | NoUndef, + arg_ext: None, + pointee_size: Size(0 bytes), + pointee_align: Some( + Align(1 bytes), + ), + }, + meta_attrs: None, + on_stack: false, + }, + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: (), + layout: Layout { + size: Size(0 bytes), + align: AbiAndPrefAlign { + abi: $SOME_ALIGN, + pref: $SOME_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + }, + }, + mode: Ignore, + }, + c_variadic: false, + fixed_count: 1, + conv: C, + can_unwind: false, + } + --> $DIR/c-zst.rs:27:1 + | +LL | extern "C" fn pass_zst(_: ()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/abi/c-zst.rs b/tests/ui/abi/c-zst.rs new file mode 100644 index 00000000000..0cfd653b37e --- /dev/null +++ b/tests/ui/abi/c-zst.rs @@ -0,0 +1,27 @@ +//@ revisions: other other-linux x86_64-pc-windows-gnu s390x-linux sparc64-linux powerpc-linux +//@ normalize-stderr-test: "(abi|pref|unadjusted_abi_align): Align\([1-8] bytes\)" -> "$1: $$SOME_ALIGN" +// ZSTs are only not ignored when the target_env is "gnu", "musl" or "uclibc". However, Rust does +// not currently support any other target_env on these architectures. + +// Ignore the ZST revisions +//@[other] ignore-x86_64-pc-windows-gnu +//@[other] ignore-linux +//@[other-linux] only-linux +//@[other-linux] ignore-s390x +//@[other-linux] ignore-sparc64 +//@[other-linux] ignore-powerpc + +// Pass the ZST indirectly revisions +//@[x86_64-pc-windows-gnu] only-x86_64-pc-windows-gnu +//@[s390x-linux] only-s390x +//@[s390x-linux] only-linux +//@[sparc64-linux] only-sparc64 +//@[sparc64-linux] only-linux +//@[powerpc-linux] only-powerpc +//@[powerpc-linux] only-linux + +#![feature(rustc_attrs)] +#![crate_type = "lib"] + +#[rustc_abi(debug)] +extern "C" fn pass_zst(_: ()) {} //~ ERROR: fn_abi diff --git a/tests/ui/abi/c-zst.s390x-linux.stderr b/tests/ui/abi/c-zst.s390x-linux.stderr new file mode 100644 index 00000000000..ba9738050d8 --- /dev/null +++ b/tests/ui/abi/c-zst.s390x-linux.stderr @@ -0,0 +1,78 @@ +error: fn_abi_of(pass_zst) = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: (), + layout: Layout { + size: Size(0 bytes), + align: AbiAndPrefAlign { + abi: $SOME_ALIGN, + pref: $SOME_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + }, + }, + mode: Indirect { + attrs: ArgAttributes { + regular: NoAlias | NoCapture | NonNull | NoUndef, + arg_ext: None, + pointee_size: Size(0 bytes), + pointee_align: Some( + Align(1 bytes), + ), + }, + meta_attrs: None, + on_stack: false, + }, + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: (), + layout: Layout { + size: Size(0 bytes), + align: AbiAndPrefAlign { + abi: $SOME_ALIGN, + pref: $SOME_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + }, + }, + mode: Ignore, + }, + c_variadic: false, + fixed_count: 1, + conv: C, + can_unwind: false, + } + --> $DIR/c-zst.rs:27:1 + | +LL | extern "C" fn pass_zst(_: ()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/abi/c-zst.sparc64-linux.stderr b/tests/ui/abi/c-zst.sparc64-linux.stderr new file mode 100644 index 00000000000..ba9738050d8 --- /dev/null +++ b/tests/ui/abi/c-zst.sparc64-linux.stderr @@ -0,0 +1,78 @@ +error: fn_abi_of(pass_zst) = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: (), + layout: Layout { + size: Size(0 bytes), + align: AbiAndPrefAlign { + abi: $SOME_ALIGN, + pref: $SOME_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + }, + }, + mode: Indirect { + attrs: ArgAttributes { + regular: NoAlias | NoCapture | NonNull | NoUndef, + arg_ext: None, + pointee_size: Size(0 bytes), + pointee_align: Some( + Align(1 bytes), + ), + }, + meta_attrs: None, + on_stack: false, + }, + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: (), + layout: Layout { + size: Size(0 bytes), + align: AbiAndPrefAlign { + abi: $SOME_ALIGN, + pref: $SOME_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + }, + }, + mode: Ignore, + }, + c_variadic: false, + fixed_count: 1, + conv: C, + can_unwind: false, + } + --> $DIR/c-zst.rs:27:1 + | +LL | extern "C" fn pass_zst(_: ()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr new file mode 100644 index 00000000000..ba9738050d8 --- /dev/null +++ b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr @@ -0,0 +1,78 @@ +error: fn_abi_of(pass_zst) = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: (), + layout: Layout { + size: Size(0 bytes), + align: AbiAndPrefAlign { + abi: $SOME_ALIGN, + pref: $SOME_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + }, + }, + mode: Indirect { + attrs: ArgAttributes { + regular: NoAlias | NoCapture | NonNull | NoUndef, + arg_ext: None, + pointee_size: Size(0 bytes), + pointee_align: Some( + Align(1 bytes), + ), + }, + meta_attrs: None, + on_stack: false, + }, + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: (), + layout: Layout { + size: Size(0 bytes), + align: AbiAndPrefAlign { + abi: $SOME_ALIGN, + pref: $SOME_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + }, + }, + mode: Ignore, + }, + c_variadic: false, + fixed_count: 1, + conv: C, + can_unwind: false, + } + --> $DIR/c-zst.rs:27:1 + | +LL | extern "C" fn pass_zst(_: ()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs index ca78604edd8..d37e793d989 100644 --- a/tests/ui/abi/compatibility.rs +++ b/tests/ui/abi/compatibility.rs @@ -40,9 +40,10 @@ //@[loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu //@[loongarch64] needs-llvm-components: loongarch //@[loongarch64] min-llvm-version: 18 -//@ revisions: wasm -//@[wasm] compile-flags: --target wasm32-unknown-unknown -//@[wasm] needs-llvm-components: webassembly +//FIXME: wasm is disabled due to . +//FIXME @ revisions: wasm +//FIXME @[wasm] compile-flags: --target wasm32-unknown-unknown +//FIXME @[wasm] needs-llvm-components: webassembly //@ revisions: wasip1 //@[wasip1] compile-flags: --target wasm32-wasip1 //@[wasip1] needs-llvm-components: webassembly diff --git a/tests/ui/abi/shadow-call-stack-without-fixed-x18.rs b/tests/ui/abi/shadow-call-stack-without-fixed-x18.rs new file mode 100644 index 00000000000..d758c903087 --- /dev/null +++ b/tests/ui/abi/shadow-call-stack-without-fixed-x18.rs @@ -0,0 +1,15 @@ +//@ compile-flags: --target aarch64-unknown-none -Zsanitizer=shadow-call-stack +//@ error-pattern: shadow-call-stack sanitizer is not supported for this target +//@ dont-check-compiler-stderr +//@ needs-llvm-components: aarch64 + +#![allow(internal_features)] +#![crate_type = "rlib"] +#![feature(no_core, lang_items)] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +#[no_mangle] +pub fn foo() {} diff --git a/tests/ui/abi/sysv64-zst.rs b/tests/ui/abi/sysv64-zst.rs new file mode 100644 index 00000000000..6f4497e77a1 --- /dev/null +++ b/tests/ui/abi/sysv64-zst.rs @@ -0,0 +1,8 @@ +//@ only-x86_64 +//@ normalize-stderr-test: "(abi|pref|unadjusted_abi_align): Align\([1-8] bytes\)" -> "$1: $$SOME_ALIGN" + +#![feature(rustc_attrs)] +#![crate_type = "lib"] + +#[rustc_abi(debug)] +extern "sysv64" fn pass_zst(_: ()) {} //~ ERROR: fn_abi diff --git a/tests/ui/abi/sysv64-zst.stderr b/tests/ui/abi/sysv64-zst.stderr new file mode 100644 index 00000000000..8b0b84dfa06 --- /dev/null +++ b/tests/ui/abi/sysv64-zst.stderr @@ -0,0 +1,67 @@ +error: fn_abi_of(pass_zst) = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: (), + layout: Layout { + size: Size(0 bytes), + align: AbiAndPrefAlign { + abi: $SOME_ALIGN, + pref: $SOME_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + }, + }, + mode: Ignore, + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: (), + layout: Layout { + size: Size(0 bytes), + align: AbiAndPrefAlign { + abi: $SOME_ALIGN, + pref: $SOME_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + }, + }, + mode: Ignore, + }, + c_variadic: false, + fixed_count: 1, + conv: X86_64SysV, + can_unwind: false, + } + --> $DIR/sysv64-zst.rs:8:1 + | +LL | extern "sysv64" fn pass_zst(_: ()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/abi/win64-zst.other.stderr b/tests/ui/abi/win64-zst.other.stderr new file mode 100644 index 00000000000..15db141cb57 --- /dev/null +++ b/tests/ui/abi/win64-zst.other.stderr @@ -0,0 +1,67 @@ +error: fn_abi_of(pass_zst) = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: (), + layout: Layout { + size: Size(0 bytes), + align: AbiAndPrefAlign { + abi: $SOME_ALIGN, + pref: $SOME_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + }, + }, + mode: Ignore, + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: (), + layout: Layout { + size: Size(0 bytes), + align: AbiAndPrefAlign { + abi: $SOME_ALIGN, + pref: $SOME_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + }, + }, + mode: Ignore, + }, + c_variadic: false, + fixed_count: 1, + conv: X86_64Win64, + can_unwind: false, + } + --> $DIR/win64-zst.rs:11:1 + | +LL | extern "win64" fn pass_zst(_: ()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/abi/win64-zst.rs b/tests/ui/abi/win64-zst.rs new file mode 100644 index 00000000000..cae32795e16 --- /dev/null +++ b/tests/ui/abi/win64-zst.rs @@ -0,0 +1,11 @@ +//@ only-x86_64 +//@ revisions: other windows-gnu +//@ normalize-stderr-test: "(abi|pref|unadjusted_abi_align): Align\([1-8] bytes\)" -> "$1: $$SOME_ALIGN" +//@[other] ignore-windows-gnu +//@[windows-gnu] only-windows-gnu + +#![feature(rustc_attrs)] +#![crate_type = "lib"] + +#[rustc_abi(debug)] +extern "win64" fn pass_zst(_: ()) {} //~ ERROR: fn_abi diff --git a/tests/ui/abi/win64-zst.windows-gnu.stderr b/tests/ui/abi/win64-zst.windows-gnu.stderr new file mode 100644 index 00000000000..7773e0aa2b5 --- /dev/null +++ b/tests/ui/abi/win64-zst.windows-gnu.stderr @@ -0,0 +1,78 @@ +error: fn_abi_of(pass_zst) = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: (), + layout: Layout { + size: Size(0 bytes), + align: AbiAndPrefAlign { + abi: $SOME_ALIGN, + pref: $SOME_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + }, + }, + mode: Indirect { + attrs: ArgAttributes { + regular: NoAlias | NoCapture | NonNull | NoUndef, + arg_ext: None, + pointee_size: Size(0 bytes), + pointee_align: Some( + Align(1 bytes), + ), + }, + meta_attrs: None, + on_stack: false, + }, + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: (), + layout: Layout { + size: Size(0 bytes), + align: AbiAndPrefAlign { + abi: $SOME_ALIGN, + pref: $SOME_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + }, + }, + mode: Ignore, + }, + c_variadic: false, + fixed_count: 1, + conv: X86_64Win64, + can_unwind: false, + } + --> $DIR/win64-zst.rs:11:1 + | +LL | extern "win64" fn pass_zst(_: ()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/asm/aarch64/bad-reg.rs b/tests/ui/asm/aarch64/bad-reg.rs index 1e54b6505db..b99e5fe4b9e 100644 --- a/tests/ui/asm/aarch64/bad-reg.rs +++ b/tests/ui/asm/aarch64/bad-reg.rs @@ -1,8 +1,6 @@ //@ only-aarch64 //@ compile-flags: -C target-feature=+neon -#![feature(asm_const)] - use std::arch::asm; fn main() { diff --git a/tests/ui/asm/aarch64/bad-reg.stderr b/tests/ui/asm/aarch64/bad-reg.stderr index 717a788caf6..370752ad0f1 100644 --- a/tests/ui/asm/aarch64/bad-reg.stderr +++ b/tests/ui/asm/aarch64/bad-reg.stderr @@ -1,17 +1,17 @@ error: invalid register class `foo`: unknown register class - --> $DIR/bad-reg.rs:14:20 + --> $DIR/bad-reg.rs:12:20 | LL | asm!("{}", in(foo) foo); | ^^^^^^^^^^^ error: invalid register `foo`: unknown register - --> $DIR/bad-reg.rs:16:18 + --> $DIR/bad-reg.rs:14:18 | LL | asm!("", in("foo") foo); | ^^^^^^^^^^^^^ error: invalid asm template modifier for this register class - --> $DIR/bad-reg.rs:18:15 + --> $DIR/bad-reg.rs:16:15 | LL | asm!("{:z}", in(reg) foo); | ^^^^ ----------- argument @@ -21,7 +21,7 @@ LL | asm!("{:z}", in(reg) foo); = note: the `reg` register class supports the following template modifiers: `w`, `x` error: invalid asm template modifier for this register class - --> $DIR/bad-reg.rs:20:15 + --> $DIR/bad-reg.rs:18:15 | LL | asm!("{:r}", in(vreg) foo); | ^^^^ ------------ argument @@ -31,7 +31,7 @@ LL | asm!("{:r}", in(vreg) foo); = note: the `vreg` register class supports the following template modifiers: `b`, `h`, `s`, `d`, `q`, `v` error: invalid asm template modifier for this register class - --> $DIR/bad-reg.rs:22:15 + --> $DIR/bad-reg.rs:20:15 | LL | asm!("{:r}", in(vreg_low16) foo); | ^^^^ ------------------ argument @@ -41,7 +41,7 @@ LL | asm!("{:r}", in(vreg_low16) foo); = note: the `vreg_low16` register class supports the following template modifiers: `b`, `h`, `s`, `d`, `q`, `v` error: asm template modifiers are not allowed for `const` arguments - --> $DIR/bad-reg.rs:24:15 + --> $DIR/bad-reg.rs:22:15 | LL | asm!("{:a}", const 0); | ^^^^ ------- argument @@ -49,7 +49,7 @@ LL | asm!("{:a}", const 0); | template modifier error: asm template modifiers are not allowed for `sym` arguments - --> $DIR/bad-reg.rs:26:15 + --> $DIR/bad-reg.rs:24:15 | LL | asm!("{:a}", sym main); | ^^^^ -------- argument @@ -57,49 +57,49 @@ LL | asm!("{:a}", sym main); | template modifier error: invalid register `x29`: the frame pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:28:18 + --> $DIR/bad-reg.rs:26:18 | LL | asm!("", in("x29") foo); | ^^^^^^^^^^^^^ error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:30:18 + --> $DIR/bad-reg.rs:28:18 | LL | asm!("", in("sp") foo); | ^^^^^^^^^^^^ error: invalid register `xzr`: the zero register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:32:18 + --> $DIR/bad-reg.rs:30:18 | LL | asm!("", in("xzr") foo); | ^^^^^^^^^^^^^ error: invalid register `x19`: x19 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:34:18 + --> $DIR/bad-reg.rs:32:18 | LL | asm!("", in("x19") foo); | ^^^^^^^^^^^^^ error: register class `preg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:37:18 + --> $DIR/bad-reg.rs:35:18 | LL | asm!("", in("p0") foo); | ^^^^^^^^^^^^ error: register class `preg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:41:20 + --> $DIR/bad-reg.rs:39:20 | LL | asm!("{}", in(preg) foo); | ^^^^^^^^^^^^ error: register class `preg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:44:20 + --> $DIR/bad-reg.rs:42:20 | LL | asm!("{}", out(preg) _); | ^^^^^^^^^^^ error: register `w0` conflicts with register `x0` - --> $DIR/bad-reg.rs:50:32 + --> $DIR/bad-reg.rs:48:32 | LL | asm!("", in("x0") foo, in("w0") bar); | ------------ ^^^^^^^^^^^^ register `w0` @@ -107,7 +107,7 @@ LL | asm!("", in("x0") foo, in("w0") bar); | register `x0` error: register `x0` conflicts with register `x0` - --> $DIR/bad-reg.rs:52:32 + --> $DIR/bad-reg.rs:50:32 | LL | asm!("", in("x0") foo, out("x0") bar); | ------------ ^^^^^^^^^^^^^ register `x0` @@ -115,13 +115,13 @@ LL | asm!("", in("x0") foo, out("x0") bar); | register `x0` | help: use `lateout` instead of `out` to avoid conflict - --> $DIR/bad-reg.rs:52:18 + --> $DIR/bad-reg.rs:50:18 | LL | asm!("", in("x0") foo, out("x0") bar); | ^^^^^^^^^^^^ error: register `q0` conflicts with register `v0` - --> $DIR/bad-reg.rs:55:32 + --> $DIR/bad-reg.rs:53:32 | LL | asm!("", in("v0") foo, in("q0") bar); | ------------ ^^^^^^^^^^^^ register `q0` @@ -129,7 +129,7 @@ LL | asm!("", in("v0") foo, in("q0") bar); | register `v0` error: register `q0` conflicts with register `v0` - --> $DIR/bad-reg.rs:57:32 + --> $DIR/bad-reg.rs:55:32 | LL | asm!("", in("v0") foo, out("q0") bar); | ------------ ^^^^^^^^^^^^^ register `q0` @@ -137,13 +137,13 @@ LL | asm!("", in("v0") foo, out("q0") bar); | register `v0` | help: use `lateout` instead of `out` to avoid conflict - --> $DIR/bad-reg.rs:57:18 + --> $DIR/bad-reg.rs:55:18 | LL | asm!("", in("v0") foo, out("q0") bar); | ^^^^^^^^^^^^ error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:37:27 + --> $DIR/bad-reg.rs:35:27 | LL | asm!("", in("p0") foo); | ^^^ @@ -151,7 +151,7 @@ LL | asm!("", in("p0") foo); = note: register class `preg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:41:29 + --> $DIR/bad-reg.rs:39:29 | LL | asm!("{}", in(preg) foo); | ^^^ diff --git a/tests/ui/asm/aarch64/const.rs b/tests/ui/asm/aarch64/const.rs index a1fadb2115b..3eab5138d7d 100644 --- a/tests/ui/asm/aarch64/const.rs +++ b/tests/ui/asm/aarch64/const.rs @@ -2,8 +2,6 @@ //@ run-pass //@ needs-asm-support -#![feature(asm_const)] - use std::arch::{asm, global_asm}; fn const_generic() -> usize { diff --git a/tests/ui/asm/aarch64/parse-error.rs b/tests/ui/asm/aarch64/parse-error.rs index ac73bbf99c9..aa731c35dda 100644 --- a/tests/ui/asm/aarch64/parse-error.rs +++ b/tests/ui/asm/aarch64/parse-error.rs @@ -1,7 +1,5 @@ //@ only-aarch64 -#![feature(asm_const)] - use std::arch::{asm, global_asm}; fn main() { diff --git a/tests/ui/asm/aarch64/parse-error.stderr b/tests/ui/asm/aarch64/parse-error.stderr index e2c798c798e..7b273282ee6 100644 --- a/tests/ui/asm/aarch64/parse-error.stderr +++ b/tests/ui/asm/aarch64/parse-error.stderr @@ -1,107 +1,107 @@ error: requires at least a template string argument - --> $DIR/parse-error.rs:11:9 + --> $DIR/parse-error.rs:9:9 | LL | asm!(); | ^^^^^^ error: asm template must be a string literal - --> $DIR/parse-error.rs:13:14 + --> $DIR/parse-error.rs:11:14 | LL | asm!(foo); | ^^^ error: expected token: `,` - --> $DIR/parse-error.rs:15:19 + --> $DIR/parse-error.rs:13:19 | LL | asm!("{}" foo); | ^^^ expected `,` error: expected operand, clobber_abi, options, or additional template string - --> $DIR/parse-error.rs:17:20 + --> $DIR/parse-error.rs:15:20 | LL | asm!("{}", foo); | ^^^ expected operand, clobber_abi, options, or additional template string error: expected `(`, found `foo` - --> $DIR/parse-error.rs:19:23 + --> $DIR/parse-error.rs:17:23 | LL | asm!("{}", in foo); | ^^^ expected `(` error: expected `)`, found `foo` - --> $DIR/parse-error.rs:21:27 + --> $DIR/parse-error.rs:19:27 | LL | asm!("{}", in(reg foo)); | ^^^ expected `)` error: expected expression, found end of macro arguments - --> $DIR/parse-error.rs:23:27 + --> $DIR/parse-error.rs:21:27 | LL | asm!("{}", in(reg)); | ^ expected expression error: expected register class or explicit register - --> $DIR/parse-error.rs:25:26 + --> $DIR/parse-error.rs:23:26 | LL | asm!("{}", inout(=) foo => bar); | ^ error: expected expression, found end of macro arguments - --> $DIR/parse-error.rs:27:37 + --> $DIR/parse-error.rs:25:37 | LL | asm!("{}", inout(reg) foo =>); | ^ expected expression error: expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `=>` - --> $DIR/parse-error.rs:29:32 + --> $DIR/parse-error.rs:27:32 | LL | asm!("{}", in(reg) foo => bar); | ^^ expected one of 7 possible tokens error: expected a path for argument to `sym` - --> $DIR/parse-error.rs:31:24 + --> $DIR/parse-error.rs:29:24 | LL | asm!("{}", sym foo + bar); | ^^^^^^^^^ error: expected one of `)`, `att_syntax`, `may_unwind`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo` - --> $DIR/parse-error.rs:33:26 + --> $DIR/parse-error.rs:31:26 | LL | asm!("", options(foo)); | ^^^ expected one of 10 possible tokens error: expected one of `)` or `,`, found `foo` - --> $DIR/parse-error.rs:35:32 + --> $DIR/parse-error.rs:33:32 | LL | asm!("", options(nomem foo)); | ^^^ expected one of `)` or `,` error: expected one of `)`, `att_syntax`, `may_unwind`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo` - --> $DIR/parse-error.rs:37:33 + --> $DIR/parse-error.rs:35:33 | LL | asm!("", options(nomem, foo)); | ^^^ expected one of 10 possible tokens error: expected string literal - --> $DIR/parse-error.rs:41:30 + --> $DIR/parse-error.rs:39:30 | LL | asm!("", clobber_abi(foo)); | ^^^ not a string literal error: expected one of `)` or `,`, found `foo` - --> $DIR/parse-error.rs:43:34 + --> $DIR/parse-error.rs:41:34 | LL | asm!("", clobber_abi("C" foo)); | ^^^ expected one of `)` or `,` error: expected string literal - --> $DIR/parse-error.rs:45:35 + --> $DIR/parse-error.rs:43:35 | LL | asm!("", clobber_abi("C", foo)); | ^^^ not a string literal error: duplicate argument named `a` - --> $DIR/parse-error.rs:52:36 + --> $DIR/parse-error.rs:50:36 | LL | asm!("{a}", a = const foo, a = const bar); | ------------- ^^^^^^^^^^^^^ duplicate argument @@ -109,7 +109,7 @@ LL | asm!("{a}", a = const foo, a = const bar); | previously here error: argument never used - --> $DIR/parse-error.rs:52:36 + --> $DIR/parse-error.rs:50:36 | LL | asm!("{a}", a = const foo, a = const bar); | ^^^^^^^^^^^^^ argument never used @@ -117,13 +117,13 @@ LL | asm!("{a}", a = const foo, a = const bar); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"` error: explicit register arguments cannot have names - --> $DIR/parse-error.rs:57:18 + --> $DIR/parse-error.rs:55:18 | LL | asm!("", a = in("x0") foo); | ^^^^^^^^^^^^^^^^ error: positional arguments cannot follow named arguments or explicit register arguments - --> $DIR/parse-error.rs:63:35 + --> $DIR/parse-error.rs:61:35 | LL | asm!("{1}", in("x0") foo, const bar); | ------------ ^^^^^^^^^ positional argument @@ -131,19 +131,19 @@ LL | asm!("{1}", in("x0") foo, const bar); | explicit register argument error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `label`, `lateout`, `options`, `out`, or `sym`, found `""` - --> $DIR/parse-error.rs:66:29 + --> $DIR/parse-error.rs:64:29 | LL | asm!("", options(), ""); | ^^ expected one of 10 possible tokens error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `label`, `lateout`, `options`, `out`, or `sym`, found `"{}"` - --> $DIR/parse-error.rs:68:33 + --> $DIR/parse-error.rs:66:33 | LL | asm!("{}", in(reg) foo, "{}", out(reg) foo); | ^^^^ expected one of 10 possible tokens error: asm template must be a string literal - --> $DIR/parse-error.rs:70:14 + --> $DIR/parse-error.rs:68:14 | LL | asm!(format!("{{{}}}", 0), in(reg) foo); | ^^^^^^^^^^^^^^^^^^^^ @@ -151,7 +151,7 @@ LL | asm!(format!("{{{}}}", 0), in(reg) foo); = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) error: asm template must be a string literal - --> $DIR/parse-error.rs:72:21 + --> $DIR/parse-error.rs:70:21 | LL | asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar); | ^^^^^^^^^^^^^^^^^^^^ @@ -159,127 +159,127 @@ LL | asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar); = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) error: _ cannot be used for input operands - --> $DIR/parse-error.rs:74:28 + --> $DIR/parse-error.rs:72:28 | LL | asm!("{}", in(reg) _); | ^ error: _ cannot be used for input operands - --> $DIR/parse-error.rs:76:31 + --> $DIR/parse-error.rs:74:31 | LL | asm!("{}", inout(reg) _); | ^ error: _ cannot be used for input operands - --> $DIR/parse-error.rs:78:35 + --> $DIR/parse-error.rs:76:35 | LL | asm!("{}", inlateout(reg) _); | ^ error: requires at least a template string argument - --> $DIR/parse-error.rs:85:1 + --> $DIR/parse-error.rs:83:1 | LL | global_asm!(); | ^^^^^^^^^^^^^ error: asm template must be a string literal - --> $DIR/parse-error.rs:87:13 + --> $DIR/parse-error.rs:85:13 | LL | global_asm!(FOO); | ^^^ error: expected token: `,` - --> $DIR/parse-error.rs:89:18 + --> $DIR/parse-error.rs:87:18 | LL | global_asm!("{}" FOO); | ^^^ expected `,` error: expected operand, options, or additional template string - --> $DIR/parse-error.rs:91:19 + --> $DIR/parse-error.rs:89:19 | LL | global_asm!("{}", FOO); | ^^^ expected operand, options, or additional template string error: expected expression, found end of macro arguments - --> $DIR/parse-error.rs:93:24 + --> $DIR/parse-error.rs:91:24 | LL | global_asm!("{}", const); | ^ expected expression error: expected one of `,`, `.`, `?`, or an operator, found `FOO` - --> $DIR/parse-error.rs:95:30 + --> $DIR/parse-error.rs:93:30 | LL | global_asm!("{}", const(reg) FOO); | ^^^ expected one of `,`, `.`, `?`, or an operator error: expected one of `)`, `att_syntax`, or `raw`, found `FOO` - --> $DIR/parse-error.rs:97:25 + --> $DIR/parse-error.rs:95:25 | LL | global_asm!("", options(FOO)); | ^^^ expected one of `)`, `att_syntax`, or `raw` error: the `nomem` option cannot be used with `global_asm!` - --> $DIR/parse-error.rs:99:25 + --> $DIR/parse-error.rs:97:25 | LL | global_asm!("", options(nomem FOO)); | ^^^^^ the `nomem` option is not meaningful for global-scoped inline assembly error: expected one of `)` or `,`, found `FOO` - --> $DIR/parse-error.rs:99:31 + --> $DIR/parse-error.rs:97:31 | LL | global_asm!("", options(nomem FOO)); | ^^^ expected one of `)` or `,` error: the `nomem` option cannot be used with `global_asm!` - --> $DIR/parse-error.rs:102:25 + --> $DIR/parse-error.rs:100:25 | LL | global_asm!("", options(nomem, FOO)); | ^^^^^ the `nomem` option is not meaningful for global-scoped inline assembly error: expected one of `)`, `att_syntax`, or `raw`, found `FOO` - --> $DIR/parse-error.rs:102:32 + --> $DIR/parse-error.rs:100:32 | LL | global_asm!("", options(nomem, FOO)); | ^^^ expected one of `)`, `att_syntax`, or `raw` error: expected string literal - --> $DIR/parse-error.rs:106:29 + --> $DIR/parse-error.rs:104:29 | LL | global_asm!("", clobber_abi(FOO)); | ^^^ not a string literal error: expected one of `)` or `,`, found `FOO` - --> $DIR/parse-error.rs:108:33 + --> $DIR/parse-error.rs:106:33 | LL | global_asm!("", clobber_abi("C" FOO)); | ^^^ expected one of `)` or `,` error: expected string literal - --> $DIR/parse-error.rs:110:34 + --> $DIR/parse-error.rs:108:34 | LL | global_asm!("", clobber_abi("C", FOO)); | ^^^ not a string literal error: `clobber_abi` cannot be used with `global_asm!` - --> $DIR/parse-error.rs:112:19 + --> $DIR/parse-error.rs:110:19 | LL | global_asm!("{}", clobber_abi("C"), const FOO); | ^^^^^^^^^^^^^^^^ error: `clobber_abi` cannot be used with `global_asm!` - --> $DIR/parse-error.rs:114:28 + --> $DIR/parse-error.rs:112:28 | LL | global_asm!("", options(), clobber_abi("C")); | ^^^^^^^^^^^^^^^^ error: `clobber_abi` cannot be used with `global_asm!` - --> $DIR/parse-error.rs:116:30 + --> $DIR/parse-error.rs:114:30 | LL | global_asm!("{}", options(), clobber_abi("C"), const FOO); | ^^^^^^^^^^^^^^^^ error: duplicate argument named `a` - --> $DIR/parse-error.rs:118:35 + --> $DIR/parse-error.rs:116:35 | LL | global_asm!("{a}", a = const FOO, a = const BAR); | ------------- ^^^^^^^^^^^^^ duplicate argument @@ -287,7 +287,7 @@ LL | global_asm!("{a}", a = const FOO, a = const BAR); | previously here error: argument never used - --> $DIR/parse-error.rs:118:35 + --> $DIR/parse-error.rs:116:35 | LL | global_asm!("{a}", a = const FOO, a = const BAR); | ^^^^^^^^^^^^^ argument never used @@ -295,19 +295,19 @@ LL | global_asm!("{a}", a = const FOO, a = const BAR); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"` error: expected one of `clobber_abi`, `const`, `options`, or `sym`, found `""` - --> $DIR/parse-error.rs:121:28 + --> $DIR/parse-error.rs:119:28 | LL | global_asm!("", options(), ""); | ^^ expected one of `clobber_abi`, `const`, `options`, or `sym` error: expected one of `clobber_abi`, `const`, `options`, or `sym`, found `"{}"` - --> $DIR/parse-error.rs:123:30 + --> $DIR/parse-error.rs:121:30 | LL | global_asm!("{}", const FOO, "{}", const FOO); | ^^^^ expected one of `clobber_abi`, `const`, `options`, or `sym` error: asm template must be a string literal - --> $DIR/parse-error.rs:125:13 + --> $DIR/parse-error.rs:123:13 | LL | global_asm!(format!("{{{}}}", 0), const FOO); | ^^^^^^^^^^^^^^^^^^^^ @@ -315,7 +315,7 @@ LL | global_asm!(format!("{{{}}}", 0), const FOO); = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) error: asm template must be a string literal - --> $DIR/parse-error.rs:127:20 + --> $DIR/parse-error.rs:125:20 | LL | global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR); | ^^^^^^^^^^^^^^^^^^^^ @@ -323,7 +323,7 @@ LL | global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR); = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:39:37 + --> $DIR/parse-error.rs:37:37 | LL | asm!("{}", options(), const foo); | ^^^ non-constant value @@ -334,7 +334,7 @@ LL | const foo: /* Type */ = 0; | ~~~~~ ++++++++++++ error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:47:44 + --> $DIR/parse-error.rs:45:44 | LL | asm!("{}", clobber_abi("C"), const foo); | ^^^ non-constant value @@ -345,7 +345,7 @@ LL | const foo: /* Type */ = 0; | ~~~~~ ++++++++++++ error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:50:55 + --> $DIR/parse-error.rs:48:55 | LL | asm!("{}", options(), clobber_abi("C"), const foo); | ^^^ non-constant value @@ -356,7 +356,7 @@ LL | const foo: /* Type */ = 0; | ~~~~~ ++++++++++++ error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:52:31 + --> $DIR/parse-error.rs:50:31 | LL | asm!("{a}", a = const foo, a = const bar); | ^^^ non-constant value @@ -367,7 +367,7 @@ LL | const foo: /* Type */ = 0; | ~~~~~ ++++++++++++ error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:52:46 + --> $DIR/parse-error.rs:50:46 | LL | asm!("{a}", a = const foo, a = const bar); | ^^^ non-constant value @@ -377,6 +377,17 @@ help: consider using `const` instead of `let` LL | const bar: /* Type */ = 0; | ~~~~~ ++++++++++++ +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/parse-error.rs:57:45 + | +LL | asm!("{a}", in("x0") foo, a = const bar); + | ^^^ non-constant value + | +help: consider using `const` instead of `let` + | +LL | const bar: /* Type */ = 0; + | ~~~~~ ++++++++++++ + error[E0435]: attempt to use a non-constant value in a constant --> $DIR/parse-error.rs:59:45 | @@ -389,18 +400,7 @@ LL | const bar: /* Type */ = 0; | ~~~~~ ++++++++++++ error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:61:45 - | -LL | asm!("{a}", in("x0") foo, a = const bar); - | ^^^ non-constant value - | -help: consider using `const` instead of `let` - | -LL | const bar: /* Type */ = 0; - | ~~~~~ ++++++++++++ - -error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:63:41 + --> $DIR/parse-error.rs:61:41 | LL | asm!("{1}", in("x0") foo, const bar); | ^^^ non-constant value diff --git a/tests/ui/asm/aarch64/type-check-3.rs b/tests/ui/asm/aarch64/type-check-3.rs index 3fc8e506069..b64473f98c0 100644 --- a/tests/ui/asm/aarch64/type-check-3.rs +++ b/tests/ui/asm/aarch64/type-check-3.rs @@ -1,7 +1,7 @@ //@ only-aarch64 //@ compile-flags: -C target-feature=+neon -#![feature(repr_simd, asm_const)] +#![feature(repr_simd)] use std::arch::aarch64::float64x2_t; use std::arch::{asm, global_asm}; diff --git a/tests/ui/asm/aarch64/type-check-3.stderr b/tests/ui/asm/aarch64/type-check-3.stderr index 9e37bb4c203..9d84d2666b3 100644 --- a/tests/ui/asm/aarch64/type-check-3.stderr +++ b/tests/ui/asm/aarch64/type-check-3.stderr @@ -95,7 +95,7 @@ error: type `i128` cannot be used with this register class LL | asm!("{}", in(reg) 0i128); | ^^^^^ | - = note: register class `reg` supports these types: i8, i16, i32, i64, f32, f64 + = note: register class `reg` supports these types: i8, i16, i32, i64, f16, f32, f64 error: type `float64x2_t` cannot be used with this register class --> $DIR/type-check-3.rs:75:28 @@ -103,7 +103,7 @@ error: type `float64x2_t` cannot be used with this register class LL | asm!("{}", in(reg) f64x2); | ^^^^^ | - = note: register class `reg` supports these types: i8, i16, i32, i64, f32, f64 + = note: register class `reg` supports these types: i8, i16, i32, i64, f16, f32, f64 error: type `Simd256bit` cannot be used with this register class --> $DIR/type-check-3.rs:77:29 @@ -111,7 +111,7 @@ error: type `Simd256bit` cannot be used with this register class LL | asm!("{}", in(vreg) f64x4); | ^^^^^ | - = note: register class `vreg` supports these types: i8, i16, i32, i64, f32, f64, i8x8, i16x4, i32x2, i64x1, f32x2, f64x1, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2 + = note: register class `vreg` supports these types: i8, i16, i32, i64, f16, f32, f64, f128, i8x8, i16x4, i32x2, i64x1, f16x4, f32x2, f64x1, i8x16, i16x8, i32x4, i64x2, f16x8, f32x4, f64x2 error: incompatible types for asm inout argument --> $DIR/type-check-3.rs:88:33 diff --git a/tests/ui/asm/aarch64/type-check-4.rs b/tests/ui/asm/aarch64/type-check-4.rs index f00b4d4c46f..41eb9de5669 100644 --- a/tests/ui/asm/aarch64/type-check-4.rs +++ b/tests/ui/asm/aarch64/type-check-4.rs @@ -1,7 +1,7 @@ //@ only-aarch64 //@ compile-flags: -C target-feature=+neon -#![feature(repr_simd, asm_const)] +#![feature(repr_simd)] use std::arch::aarch64::float64x2_t; use std::arch::{asm, global_asm}; @@ -10,8 +10,7 @@ use std::arch::{asm, global_asm}; #[derive(Copy, Clone)] struct Simd256bit(f64, f64, f64, f64); -fn main() { -} +fn main() {} // Constants must be... constant diff --git a/tests/ui/asm/aarch64/type-check-4.stderr b/tests/ui/asm/aarch64/type-check-4.stderr index 3e675f69e84..89eb8467cde 100644 --- a/tests/ui/asm/aarch64/type-check-4.stderr +++ b/tests/ui/asm/aarch64/type-check-4.stderr @@ -1,5 +1,5 @@ error[E0658]: referencing statics in constants is unstable - --> $DIR/type-check-4.rs:25:25 + --> $DIR/type-check-4.rs:24:25 | LL | global_asm!("{}", const S); | ^ @@ -11,7 +11,7 @@ LL | global_asm!("{}", const S); = help: to fix this, the value can be extracted to a `const` and then used. error[E0658]: referencing statics in constants is unstable - --> $DIR/type-check-4.rs:28:35 + --> $DIR/type-check-4.rs:27:35 | LL | global_asm!("{}", const const_foo(S)); | ^ @@ -23,7 +23,7 @@ LL | global_asm!("{}", const const_foo(S)); = help: to fix this, the value can be extracted to a `const` and then used. error[E0658]: referencing statics in constants is unstable - --> $DIR/type-check-4.rs:31:35 + --> $DIR/type-check-4.rs:30:35 | LL | global_asm!("{}", const const_bar(S)); | ^ diff --git a/tests/ui/asm/aarch64/type-f16.rs b/tests/ui/asm/aarch64/type-f16.rs new file mode 100644 index 00000000000..e62d8130c93 --- /dev/null +++ b/tests/ui/asm/aarch64/type-f16.rs @@ -0,0 +1,25 @@ +//@ only-aarch64 +//@ run-pass +//@ needs-asm-support + +#![feature(f16)] + +use std::arch::asm; + +#[inline(never)] +pub fn f32_to_f16_asm(a: f32) -> f16 { + let ret: f16; + unsafe { + asm!( + "fcvt {ret:h}, {a:s}", + a = in(vreg) a, + ret = lateout(vreg) ret, + options(nomem, nostack), + ); + } + ret +} + +fn main() { + assert_eq!(f32_to_f16_asm(1.0 as f32), 1.0); +} diff --git a/tests/ui/asm/bad-template.rs b/tests/ui/asm/bad-template.rs index 41a906e32a4..6b00905a393 100644 --- a/tests/ui/asm/bad-template.rs +++ b/tests/ui/asm/bad-template.rs @@ -6,7 +6,7 @@ //@ [x86_64] needs-llvm-components: x86 //@ [aarch64] needs-llvm-components: aarch64 -#![feature(no_core, lang_items, rustc_attrs, asm_const)] +#![feature(no_core, lang_items, rustc_attrs)] #![no_core] #[rustc_builtin_macro] diff --git a/tests/ui/asm/const-error.rs b/tests/ui/asm/const-error.rs index f2cead399b6..40d0590c33e 100644 --- a/tests/ui/asm/const-error.rs +++ b/tests/ui/asm/const-error.rs @@ -1,15 +1,15 @@ //@ only-x86_64 //@ needs-asm-support -#![feature(asm_const)] - // Test to make sure that we emit const errors eagerly for inline asm use std::arch::asm; fn test() { - unsafe { asm!("/* {} */", const 1 / 0); } - //~^ ERROR evaluation of + unsafe { + asm!("/* {} */", const 1 / 0); + //~^ ERROR evaluation of + } } fn main() {} diff --git a/tests/ui/asm/const-error.stderr b/tests/ui/asm/const-error.stderr index fe311832177..02e54457e89 100644 --- a/tests/ui/asm/const-error.stderr +++ b/tests/ui/asm/const-error.stderr @@ -1,8 +1,8 @@ error[E0080]: evaluation of `test::::{constant#0}` failed - --> $DIR/const-error.rs:11:37 + --> $DIR/const-error.rs:10:32 | -LL | unsafe { asm!("/* {} */", const 1 / 0); } - | ^^^^^ attempt to divide `1_i32` by zero +LL | asm!("/* {} */", const 1 / 0); + | ^^^^^ attempt to divide `1_i32` by zero error: aborting due to 1 previous error diff --git a/tests/ui/asm/fail-const-eval-issue-121099.rs b/tests/ui/asm/fail-const-eval-issue-121099.rs index bed6fc9b39f..36d00b1e5d2 100644 --- a/tests/ui/asm/fail-const-eval-issue-121099.rs +++ b/tests/ui/asm/fail-const-eval-issue-121099.rs @@ -1,6 +1,5 @@ //@ build-fail //@ needs-asm-support -#![feature(asm_const)] use std::arch::global_asm; diff --git a/tests/ui/asm/fail-const-eval-issue-121099.stderr b/tests/ui/asm/fail-const-eval-issue-121099.stderr index 51d283218d2..5d86c3a5f7b 100644 --- a/tests/ui/asm/fail-const-eval-issue-121099.stderr +++ b/tests/ui/asm/fail-const-eval-issue-121099.stderr @@ -1,11 +1,11 @@ error[E0080]: evaluation of constant value failed - --> $DIR/fail-const-eval-issue-121099.rs:9:31 + --> $DIR/fail-const-eval-issue-121099.rs:8:31 | LL | global_asm!("/* {} */", const 1 << 500); | ^^^^^^^^ attempt to shift left by `500_i32`, which would overflow error[E0080]: evaluation of constant value failed - --> $DIR/fail-const-eval-issue-121099.rs:11:31 + --> $DIR/fail-const-eval-issue-121099.rs:10:31 | LL | global_asm!("/* {} */", const 1 / 0); | ^^^^^ attempt to divide `1_i32` by zero diff --git a/tests/ui/asm/generic-const.rs b/tests/ui/asm/generic-const.rs index 133d093d200..3b69a4e86e3 100644 --- a/tests/ui/asm/generic-const.rs +++ b/tests/ui/asm/generic-const.rs @@ -1,8 +1,6 @@ //@ needs-asm-support //@ build-pass -#![feature(asm_const)] - use std::arch::asm; fn foofoo() {} diff --git a/tests/ui/asm/invalid-const-operand.rs b/tests/ui/asm/invalid-const-operand.rs index eff335ff6aa..a688f5042db 100644 --- a/tests/ui/asm/invalid-const-operand.rs +++ b/tests/ui/asm/invalid-const-operand.rs @@ -2,8 +2,6 @@ //@ ignore-nvptx64 //@ ignore-spirv -#![feature(asm_const)] - use std::arch::{asm, global_asm}; // Const operands must be integers and must be constants. diff --git a/tests/ui/asm/invalid-const-operand.stderr b/tests/ui/asm/invalid-const-operand.stderr index a6d742b53c2..bda4b0355b7 100644 --- a/tests/ui/asm/invalid-const-operand.stderr +++ b/tests/ui/asm/invalid-const-operand.stderr @@ -1,5 +1,5 @@ error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/invalid-const-operand.rs:42:26 + --> $DIR/invalid-const-operand.rs:40:26 | LL | asm!("{}", const x); | ^ non-constant value @@ -10,7 +10,7 @@ LL | const x: /* Type */ = 0; | ~~~~~ ++++++++++++ error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/invalid-const-operand.rs:45:36 + --> $DIR/invalid-const-operand.rs:43:36 | LL | asm!("{}", const const_foo(x)); | ^ non-constant value @@ -21,7 +21,7 @@ LL | const x: /* Type */ = 0; | ~~~~~ ++++++++++++ error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/invalid-const-operand.rs:48:36 + --> $DIR/invalid-const-operand.rs:46:36 | LL | asm!("{}", const const_bar(x)); | ^ non-constant value @@ -32,7 +32,7 @@ LL | const x: /* Type */ = 0; | ~~~~~ ++++++++++++ error: invalid type for `const` operand - --> $DIR/invalid-const-operand.rs:14:19 + --> $DIR/invalid-const-operand.rs:12:19 | LL | global_asm!("{}", const 0f32); | ^^^^^^---- @@ -42,7 +42,7 @@ LL | global_asm!("{}", const 0f32); = help: `const` operands must be of an integer type error: invalid type for `const` operand - --> $DIR/invalid-const-operand.rs:16:19 + --> $DIR/invalid-const-operand.rs:14:19 | LL | global_asm!("{}", const 0 as *mut u8); | ^^^^^^------------ @@ -52,7 +52,7 @@ LL | global_asm!("{}", const 0 as *mut u8); = help: `const` operands must be of an integer type error: invalid type for `const` operand - --> $DIR/invalid-const-operand.rs:26:20 + --> $DIR/invalid-const-operand.rs:24:20 | LL | asm!("{}", const 0f32); | ^^^^^^---- @@ -62,7 +62,7 @@ LL | asm!("{}", const 0f32); = help: `const` operands must be of an integer type error: invalid type for `const` operand - --> $DIR/invalid-const-operand.rs:28:20 + --> $DIR/invalid-const-operand.rs:26:20 | LL | asm!("{}", const 0 as *mut u8); | ^^^^^^------------ @@ -72,7 +72,7 @@ LL | asm!("{}", const 0 as *mut u8); = help: `const` operands must be of an integer type error: invalid type for `const` operand - --> $DIR/invalid-const-operand.rs:30:20 + --> $DIR/invalid-const-operand.rs:28:20 | LL | asm!("{}", const &0); | ^^^^^^-- diff --git a/tests/ui/asm/naked-functions.rs b/tests/ui/asm/naked-functions.rs index cb1e5c325c2..116a84506c5 100644 --- a/tests/ui/asm/naked-functions.rs +++ b/tests/ui/asm/naked-functions.rs @@ -3,7 +3,7 @@ //@ ignore-spirv #![feature(naked_functions)] -#![feature(asm_const, asm_unwind, linkage)] +#![feature(asm_unwind, linkage)] #![crate_type = "lib"] use std::arch::asm; diff --git a/tests/ui/asm/naked-with-invalid-repr-attr.rs b/tests/ui/asm/naked-with-invalid-repr-attr.rs new file mode 100644 index 00000000000..687fe1ad73d --- /dev/null +++ b/tests/ui/asm/naked-with-invalid-repr-attr.rs @@ -0,0 +1,48 @@ +//@ needs-asm-support +#![feature(naked_functions)] +#![feature(fn_align)] +#![crate_type = "lib"] +use std::arch::asm; + +#[repr(C)] +//~^ ERROR attribute should be applied to a struct, enum, or union [E0517] +#[naked] +extern "C" fn example1() { + //~^ NOTE not a struct, enum, or union + unsafe { asm!("", options(noreturn)) } +} + +#[repr(transparent)] +//~^ ERROR attribute should be applied to a struct, enum, or union [E0517] +#[naked] +extern "C" fn example2() { + //~^ NOTE not a struct, enum, or union + unsafe { asm!("", options(noreturn)) } +} + +#[repr(align(16), C)] +//~^ ERROR attribute should be applied to a struct, enum, or union [E0517] +#[naked] +extern "C" fn example3() { + //~^ NOTE not a struct, enum, or union + unsafe { asm!("", options(noreturn)) } +} + +// note: two errors because of packed and C +#[repr(C, packed)] +//~^ ERROR attribute should be applied to a struct or union [E0517] +//~| ERROR attribute should be applied to a struct, enum, or union [E0517] +#[naked] +extern "C" fn example4() { + //~^ NOTE not a struct, enum, or union + //~| NOTE not a struct or union + unsafe { asm!("", options(noreturn)) } +} + +#[repr(u8)] +//~^ ERROR attribute should be applied to an enum [E0517] +#[naked] +extern "C" fn example5() { + //~^ NOTE not an enum + unsafe { asm!("", options(noreturn)) } +} diff --git a/tests/ui/asm/naked-with-invalid-repr-attr.stderr b/tests/ui/asm/naked-with-invalid-repr-attr.stderr new file mode 100644 index 00000000000..3740f17a9dc --- /dev/null +++ b/tests/ui/asm/naked-with-invalid-repr-attr.stderr @@ -0,0 +1,77 @@ +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/naked-with-invalid-repr-attr.rs:7:8 + | +LL | #[repr(C)] + | ^ +... +LL | / extern "C" fn example1() { +LL | | +LL | | unsafe { asm!("", options(noreturn)) } +LL | | } + | |_- not a struct, enum, or union + +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/naked-with-invalid-repr-attr.rs:15:8 + | +LL | #[repr(transparent)] + | ^^^^^^^^^^^ +... +LL | / extern "C" fn example2() { +LL | | +LL | | unsafe { asm!("", options(noreturn)) } +LL | | } + | |_- not a struct, enum, or union + +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/naked-with-invalid-repr-attr.rs:23:19 + | +LL | #[repr(align(16), C)] + | ^ +... +LL | / extern "C" fn example3() { +LL | | +LL | | unsafe { asm!("", options(noreturn)) } +LL | | } + | |_- not a struct, enum, or union + +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/naked-with-invalid-repr-attr.rs:32:8 + | +LL | #[repr(C, packed)] + | ^ +... +LL | / extern "C" fn example4() { +LL | | +LL | | +LL | | unsafe { asm!("", options(noreturn)) } +LL | | } + | |_- not a struct, enum, or union + +error[E0517]: attribute should be applied to a struct or union + --> $DIR/naked-with-invalid-repr-attr.rs:32:11 + | +LL | #[repr(C, packed)] + | ^^^^^^ +... +LL | / extern "C" fn example4() { +LL | | +LL | | +LL | | unsafe { asm!("", options(noreturn)) } +LL | | } + | |_- not a struct or union + +error[E0517]: attribute should be applied to an enum + --> $DIR/naked-with-invalid-repr-attr.rs:42:8 + | +LL | #[repr(u8)] + | ^^ +... +LL | / extern "C" fn example5() { +LL | | +LL | | unsafe { asm!("", options(noreturn)) } +LL | | } + | |_- not an enum + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0517`. diff --git a/tests/ui/asm/named-asm-labels.rs b/tests/ui/asm/named-asm-labels.rs index d2ca6fe8808..043aab9029d 100644 --- a/tests/ui/asm/named-asm-labels.rs +++ b/tests/ui/asm/named-asm-labels.rs @@ -10,7 +10,7 @@ // which causes less readable LLVM errors and in the worst cases causes ICEs // or segfaults based on system dependent behavior and codegen flags. -#![feature(naked_functions, asm_const)] +#![feature(naked_functions)] use std::arch::{asm, global_asm}; @@ -128,6 +128,7 @@ fn main() { // Tests usage of colons in non-label positions asm!(":lo12:FOO"); // this is apparently valid aarch64 + // is there an example that is valid x86 for this test? asm!(":bbb nop"); @@ -176,7 +177,8 @@ fn main() { // label or LTO can cause labels to break #[naked] pub extern "C" fn foo() -> i32 { - unsafe { asm!(".Lfoo: mov rax, {}; ret;", "nop", const 1, options(noreturn)) } //~ ERROR avoid using named labels + unsafe { asm!(".Lfoo: mov rax, {}; ret;", "nop", const 1, options(noreturn)) } + //~^ ERROR avoid using named labels } // Make sure that non-naked attributes *do* still let the lint happen diff --git a/tests/ui/asm/named-asm-labels.stderr b/tests/ui/asm/named-asm-labels.stderr index 20b7d64f9e7..e5e177fb8b8 100644 --- a/tests/ui/asm/named-asm-labels.stderr +++ b/tests/ui/asm/named-asm-labels.stderr @@ -328,7 +328,7 @@ LL | ab: nop // ab: does foo = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:143:19 + --> $DIR/named-asm-labels.rs:144:19 | LL | asm!("test_{}: nop", in(reg) 10); | ^^^^^^^ @@ -338,7 +338,7 @@ LL | asm!("test_{}: nop", in(reg) 10); = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:145:15 + --> $DIR/named-asm-labels.rs:146:15 | LL | asm!("test_{}: nop", const 10); | ^^^^^^^ @@ -348,7 +348,7 @@ LL | asm!("test_{}: nop", const 10); = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:146:15 + --> $DIR/named-asm-labels.rs:147:15 | LL | asm!("test_{}: nop", sym main); | ^^^^^^^ @@ -358,7 +358,7 @@ LL | asm!("test_{}: nop", sym main); = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:147:15 + --> $DIR/named-asm-labels.rs:148:15 | LL | asm!("{}_test: nop", const 10); | ^^^^^^^ @@ -368,7 +368,7 @@ LL | asm!("{}_test: nop", const 10); = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:148:15 + --> $DIR/named-asm-labels.rs:149:15 | LL | asm!("test_{}_test: nop", const 10); | ^^^^^^^^^^^^ @@ -378,7 +378,7 @@ LL | asm!("test_{}_test: nop", const 10); = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:149:15 + --> $DIR/named-asm-labels.rs:150:15 | LL | asm!("{}: nop", const 10); | ^^ @@ -388,7 +388,7 @@ LL | asm!("{}: nop", const 10); = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:151:15 + --> $DIR/named-asm-labels.rs:152:15 | LL | asm!("{uwu}: nop", uwu = const 10); | ^^^^^ @@ -398,7 +398,7 @@ LL | asm!("{uwu}: nop", uwu = const 10); = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:152:15 + --> $DIR/named-asm-labels.rs:153:15 | LL | asm!("{0}: nop", const 10); | ^^^ @@ -408,7 +408,7 @@ LL | asm!("{0}: nop", const 10); = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:153:15 + --> $DIR/named-asm-labels.rs:154:15 | LL | asm!("{1}: nop", "/* {0} */", const 10, const 20); | ^^^ @@ -418,7 +418,7 @@ LL | asm!("{1}: nop", "/* {0} */", const 10, const 20); = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:156:14 + --> $DIR/named-asm-labels.rs:157:14 | LL | asm!(include_str!("named-asm-labels.s")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -428,7 +428,7 @@ LL | asm!(include_str!("named-asm-labels.s")); = note: the label may be declared in the expansion of a macro error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:156:14 + --> $DIR/named-asm-labels.rs:157:14 | LL | asm!(include_str!("named-asm-labels.s")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -439,7 +439,7 @@ LL | asm!(include_str!("named-asm-labels.s")); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:156:14 + --> $DIR/named-asm-labels.rs:157:14 | LL | asm!(include_str!("named-asm-labels.s")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -450,7 +450,7 @@ LL | asm!(include_str!("named-asm-labels.s")); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:156:14 + --> $DIR/named-asm-labels.rs:157:14 | LL | asm!(include_str!("named-asm-labels.s")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -461,7 +461,7 @@ LL | asm!(include_str!("named-asm-labels.s")); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:170:19 + --> $DIR/named-asm-labels.rs:171:19 | LL | asm!("warned: nop"); | ^^^^^^ @@ -469,13 +469,13 @@ LL | asm!("warned: nop"); = help: only local labels of the form `:` should be used in inline asm = note: see the asm section of Rust By Example for more information note: the lint level is defined here - --> $DIR/named-asm-labels.rs:168:16 + --> $DIR/named-asm-labels.rs:169:16 | LL | #[warn(named_asm_labels)] | ^^^^^^^^^^^^^^^^ error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:179:20 + --> $DIR/named-asm-labels.rs:180:20 | LL | unsafe { asm!(".Lfoo: mov rax, {}; ret;", "nop", const 1, options(noreturn)) } | ^^^^^ @@ -484,7 +484,7 @@ LL | unsafe { asm!(".Lfoo: mov rax, {}; ret;", "nop", const 1, options(noret = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:185:20 + --> $DIR/named-asm-labels.rs:187:20 | LL | unsafe { asm!(".Lbar: mov rax, {}; ret;", "nop", const 1, options(noreturn)) } | ^^^^^ @@ -493,7 +493,7 @@ LL | unsafe { asm!(".Lbar: mov rax, {}; ret;", "nop", const 1, options(noret = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:193:20 + --> $DIR/named-asm-labels.rs:195:20 | LL | unsafe { asm!(".Laaa: nop; ret;", options(noreturn)) } | ^^^^^ @@ -502,7 +502,7 @@ LL | unsafe { asm!(".Laaa: nop; ret;", options(noreturn)) } = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:203:24 + --> $DIR/named-asm-labels.rs:205:24 | LL | unsafe { asm!(".Lbbb: nop; ret;", options(noreturn)) } | ^^^^^ @@ -511,7 +511,7 @@ LL | unsafe { asm!(".Lbbb: nop; ret;", options(noreturn)) } = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:212:15 + --> $DIR/named-asm-labels.rs:214:15 | LL | asm!("closure1: nop"); | ^^^^^^^^ @@ -520,7 +520,7 @@ LL | asm!("closure1: nop"); = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:216:15 + --> $DIR/named-asm-labels.rs:218:15 | LL | asm!("closure2: nop"); | ^^^^^^^^ @@ -529,7 +529,7 @@ LL | asm!("closure2: nop"); = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:226:19 + --> $DIR/named-asm-labels.rs:228:19 | LL | asm!("closure3: nop"); | ^^^^^^^^ diff --git a/tests/ui/asm/parse-error.rs b/tests/ui/asm/parse-error.rs index 16ae0282864..4d7b522f5fc 100644 --- a/tests/ui/asm/parse-error.rs +++ b/tests/ui/asm/parse-error.rs @@ -1,7 +1,5 @@ //@ needs-asm-support -#![feature(asm_const)] - use std::arch::{asm, global_asm}; fn main() { diff --git a/tests/ui/asm/parse-error.stderr b/tests/ui/asm/parse-error.stderr index f5f8d537d86..6d0e629b937 100644 --- a/tests/ui/asm/parse-error.stderr +++ b/tests/ui/asm/parse-error.stderr @@ -1,167 +1,167 @@ error: requires at least a template string argument - --> $DIR/parse-error.rs:11:9 + --> $DIR/parse-error.rs:9:9 | LL | asm!(); | ^^^^^^ error: asm template must be a string literal - --> $DIR/parse-error.rs:13:14 + --> $DIR/parse-error.rs:11:14 | LL | asm!(foo); | ^^^ error: expected token: `,` - --> $DIR/parse-error.rs:15:19 + --> $DIR/parse-error.rs:13:19 | LL | asm!("{}" foo); | ^^^ expected `,` error: expected operand, clobber_abi, options, or additional template string - --> $DIR/parse-error.rs:17:20 + --> $DIR/parse-error.rs:15:20 | LL | asm!("{}", foo); | ^^^ expected operand, clobber_abi, options, or additional template string error: expected `(`, found `foo` - --> $DIR/parse-error.rs:19:23 + --> $DIR/parse-error.rs:17:23 | LL | asm!("{}", in foo); | ^^^ expected `(` error: expected `)`, found `foo` - --> $DIR/parse-error.rs:21:27 + --> $DIR/parse-error.rs:19:27 | LL | asm!("{}", in(reg foo)); | ^^^ expected `)` error: expected expression, found end of macro arguments - --> $DIR/parse-error.rs:23:27 + --> $DIR/parse-error.rs:21:27 | LL | asm!("{}", in(reg)); | ^ expected expression error: expected register class or explicit register - --> $DIR/parse-error.rs:25:26 + --> $DIR/parse-error.rs:23:26 | LL | asm!("{}", inout(=) foo => bar); | ^ error: expected expression, found end of macro arguments - --> $DIR/parse-error.rs:27:37 + --> $DIR/parse-error.rs:25:37 | LL | asm!("{}", inout(reg) foo =>); | ^ expected expression error: expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `=>` - --> $DIR/parse-error.rs:29:32 + --> $DIR/parse-error.rs:27:32 | LL | asm!("{}", in(reg) foo => bar); | ^^ expected one of 7 possible tokens error: expected a path for argument to `sym` - --> $DIR/parse-error.rs:31:24 + --> $DIR/parse-error.rs:29:24 | LL | asm!("{}", sym foo + bar); | ^^^^^^^^^ error: expected one of `)`, `att_syntax`, `may_unwind`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo` - --> $DIR/parse-error.rs:33:26 + --> $DIR/parse-error.rs:31:26 | LL | asm!("", options(foo)); | ^^^ expected one of 10 possible tokens error: expected one of `)` or `,`, found `foo` - --> $DIR/parse-error.rs:35:32 + --> $DIR/parse-error.rs:33:32 | LL | asm!("", options(nomem foo)); | ^^^ expected one of `)` or `,` error: expected one of `)`, `att_syntax`, `may_unwind`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo` - --> $DIR/parse-error.rs:37:33 + --> $DIR/parse-error.rs:35:33 | LL | asm!("", options(nomem, foo)); | ^^^ expected one of 10 possible tokens error: at least one abi must be provided as an argument to `clobber_abi` - --> $DIR/parse-error.rs:44:30 + --> $DIR/parse-error.rs:42:30 | LL | asm!("", clobber_abi()); | ^ error: expected string literal - --> $DIR/parse-error.rs:46:30 + --> $DIR/parse-error.rs:44:30 | LL | asm!("", clobber_abi(foo)); | ^^^ not a string literal error: expected one of `)` or `,`, found `foo` - --> $DIR/parse-error.rs:48:34 + --> $DIR/parse-error.rs:46:34 | LL | asm!("", clobber_abi("C" foo)); | ^^^ expected one of `)` or `,` error: expected string literal - --> $DIR/parse-error.rs:50:35 + --> $DIR/parse-error.rs:48:35 | LL | asm!("", clobber_abi("C", foo)); | ^^^ not a string literal error: expected string literal - --> $DIR/parse-error.rs:52:30 + --> $DIR/parse-error.rs:50:30 | LL | asm!("", clobber_abi(1)); | ^ not a string literal error: expected string literal - --> $DIR/parse-error.rs:54:30 + --> $DIR/parse-error.rs:52:30 | LL | asm!("", clobber_abi(())); | ^ not a string literal error: expected string literal - --> $DIR/parse-error.rs:56:30 + --> $DIR/parse-error.rs:54:30 | LL | asm!("", clobber_abi(uwu)); | ^^^ not a string literal error: expected string literal - --> $DIR/parse-error.rs:58:30 + --> $DIR/parse-error.rs:56:30 | LL | asm!("", clobber_abi({})); | ^ not a string literal error: expected string literal - --> $DIR/parse-error.rs:60:30 + --> $DIR/parse-error.rs:58:30 | LL | asm!("", clobber_abi(loop {})); | ^^^^ not a string literal error: expected string literal - --> $DIR/parse-error.rs:62:30 + --> $DIR/parse-error.rs:60:30 | LL | asm!("", clobber_abi(if)); | ^^ not a string literal error: expected string literal - --> $DIR/parse-error.rs:64:30 + --> $DIR/parse-error.rs:62:30 | LL | asm!("", clobber_abi(do)); | ^^ not a string literal error: expected string literal - --> $DIR/parse-error.rs:66:30 + --> $DIR/parse-error.rs:64:30 | LL | asm!("", clobber_abi(<)); | ^ not a string literal error: expected string literal - --> $DIR/parse-error.rs:68:30 + --> $DIR/parse-error.rs:66:30 | LL | asm!("", clobber_abi(.)); | ^ not a string literal error: duplicate argument named `a` - --> $DIR/parse-error.rs:76:36 + --> $DIR/parse-error.rs:74:36 | LL | asm!("{a}", a = const foo, a = const bar); | ------------- ^^^^^^^^^^^^^ duplicate argument @@ -169,7 +169,7 @@ LL | asm!("{a}", a = const foo, a = const bar); | previously here error: argument never used - --> $DIR/parse-error.rs:76:36 + --> $DIR/parse-error.rs:74:36 | LL | asm!("{a}", a = const foo, a = const bar); | ^^^^^^^^^^^^^ argument never used @@ -177,19 +177,19 @@ LL | asm!("{a}", a = const foo, a = const bar); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"` error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `label`, `lateout`, `options`, `out`, or `sym`, found `""` - --> $DIR/parse-error.rs:82:29 + --> $DIR/parse-error.rs:80:29 | LL | asm!("", options(), ""); | ^^ expected one of 10 possible tokens error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `label`, `lateout`, `options`, `out`, or `sym`, found `"{}"` - --> $DIR/parse-error.rs:84:33 + --> $DIR/parse-error.rs:82:33 | LL | asm!("{}", in(reg) foo, "{}", out(reg) foo); | ^^^^ expected one of 10 possible tokens error: asm template must be a string literal - --> $DIR/parse-error.rs:86:14 + --> $DIR/parse-error.rs:84:14 | LL | asm!(format!("{{{}}}", 0), in(reg) foo); | ^^^^^^^^^^^^^^^^^^^^ @@ -197,7 +197,7 @@ LL | asm!(format!("{{{}}}", 0), in(reg) foo); = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) error: asm template must be a string literal - --> $DIR/parse-error.rs:88:21 + --> $DIR/parse-error.rs:86:21 | LL | asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar); | ^^^^^^^^^^^^^^^^^^^^ @@ -205,139 +205,139 @@ LL | asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar); = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) error: _ cannot be used for input operands - --> $DIR/parse-error.rs:90:28 + --> $DIR/parse-error.rs:88:28 | LL | asm!("{}", in(reg) _); | ^ error: _ cannot be used for input operands - --> $DIR/parse-error.rs:92:31 + --> $DIR/parse-error.rs:90:31 | LL | asm!("{}", inout(reg) _); | ^ error: _ cannot be used for input operands - --> $DIR/parse-error.rs:94:35 + --> $DIR/parse-error.rs:92:35 | LL | asm!("{}", inlateout(reg) _); | ^ error: requires at least a template string argument - --> $DIR/parse-error.rs:101:1 + --> $DIR/parse-error.rs:99:1 | LL | global_asm!(); | ^^^^^^^^^^^^^ error: asm template must be a string literal - --> $DIR/parse-error.rs:103:13 + --> $DIR/parse-error.rs:101:13 | LL | global_asm!(FOO); | ^^^ error: expected token: `,` - --> $DIR/parse-error.rs:105:18 + --> $DIR/parse-error.rs:103:18 | LL | global_asm!("{}" FOO); | ^^^ expected `,` error: expected operand, options, or additional template string - --> $DIR/parse-error.rs:107:19 + --> $DIR/parse-error.rs:105:19 | LL | global_asm!("{}", FOO); | ^^^ expected operand, options, or additional template string error: expected expression, found end of macro arguments - --> $DIR/parse-error.rs:109:24 + --> $DIR/parse-error.rs:107:24 | LL | global_asm!("{}", const); | ^ expected expression error: expected one of `,`, `.`, `?`, or an operator, found `FOO` - --> $DIR/parse-error.rs:111:30 + --> $DIR/parse-error.rs:109:30 | LL | global_asm!("{}", const(reg) FOO); | ^^^ expected one of `,`, `.`, `?`, or an operator error: expected one of `)`, `att_syntax`, or `raw`, found `FOO` - --> $DIR/parse-error.rs:113:25 + --> $DIR/parse-error.rs:111:25 | LL | global_asm!("", options(FOO)); | ^^^ expected one of `)`, `att_syntax`, or `raw` error: expected one of `)`, `att_syntax`, or `raw`, found `FOO` - --> $DIR/parse-error.rs:115:25 + --> $DIR/parse-error.rs:113:25 | LL | global_asm!("", options(FOO,)); | ^^^ expected one of `)`, `att_syntax`, or `raw` error: the `nomem` option cannot be used with `global_asm!` - --> $DIR/parse-error.rs:117:25 + --> $DIR/parse-error.rs:115:25 | LL | global_asm!("", options(nomem FOO)); | ^^^^^ the `nomem` option is not meaningful for global-scoped inline assembly error: expected one of `)` or `,`, found `FOO` - --> $DIR/parse-error.rs:117:31 + --> $DIR/parse-error.rs:115:31 | LL | global_asm!("", options(nomem FOO)); | ^^^ expected one of `)` or `,` error: the `nomem` option cannot be used with `global_asm!` - --> $DIR/parse-error.rs:120:25 + --> $DIR/parse-error.rs:118:25 | LL | global_asm!("", options(nomem, FOO)); | ^^^^^ the `nomem` option is not meaningful for global-scoped inline assembly error: expected one of `)`, `att_syntax`, or `raw`, found `FOO` - --> $DIR/parse-error.rs:120:32 + --> $DIR/parse-error.rs:118:32 | LL | global_asm!("", options(nomem, FOO)); | ^^^ expected one of `)`, `att_syntax`, or `raw` error: expected string literal - --> $DIR/parse-error.rs:124:29 + --> $DIR/parse-error.rs:122:29 | LL | global_asm!("", clobber_abi(FOO)); | ^^^ not a string literal error: expected one of `)` or `,`, found `FOO` - --> $DIR/parse-error.rs:126:33 + --> $DIR/parse-error.rs:124:33 | LL | global_asm!("", clobber_abi("C" FOO)); | ^^^ expected one of `)` or `,` error: expected string literal - --> $DIR/parse-error.rs:128:34 + --> $DIR/parse-error.rs:126:34 | LL | global_asm!("", clobber_abi("C", FOO)); | ^^^ not a string literal error: `clobber_abi` cannot be used with `global_asm!` - --> $DIR/parse-error.rs:130:19 + --> $DIR/parse-error.rs:128:19 | LL | global_asm!("{}", clobber_abi("C"), const FOO); | ^^^^^^^^^^^^^^^^ error: `clobber_abi` cannot be used with `global_asm!` - --> $DIR/parse-error.rs:132:28 + --> $DIR/parse-error.rs:130:28 | LL | global_asm!("", options(), clobber_abi("C")); | ^^^^^^^^^^^^^^^^ error: `clobber_abi` cannot be used with `global_asm!` - --> $DIR/parse-error.rs:134:30 + --> $DIR/parse-error.rs:132:30 | LL | global_asm!("{}", options(), clobber_abi("C"), const FOO); | ^^^^^^^^^^^^^^^^ error: `clobber_abi` cannot be used with `global_asm!` - --> $DIR/parse-error.rs:136:17 + --> $DIR/parse-error.rs:134:17 | LL | global_asm!("", clobber_abi("C"), clobber_abi("C")); | ^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ error: duplicate argument named `a` - --> $DIR/parse-error.rs:138:35 + --> $DIR/parse-error.rs:136:35 | LL | global_asm!("{a}", a = const FOO, a = const BAR); | ------------- ^^^^^^^^^^^^^ duplicate argument @@ -345,7 +345,7 @@ LL | global_asm!("{a}", a = const FOO, a = const BAR); | previously here error: argument never used - --> $DIR/parse-error.rs:138:35 + --> $DIR/parse-error.rs:136:35 | LL | global_asm!("{a}", a = const FOO, a = const BAR); | ^^^^^^^^^^^^^ argument never used @@ -353,19 +353,19 @@ LL | global_asm!("{a}", a = const FOO, a = const BAR); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"` error: expected one of `clobber_abi`, `const`, `options`, or `sym`, found `""` - --> $DIR/parse-error.rs:141:28 + --> $DIR/parse-error.rs:139:28 | LL | global_asm!("", options(), ""); | ^^ expected one of `clobber_abi`, `const`, `options`, or `sym` error: expected one of `clobber_abi`, `const`, `options`, or `sym`, found `"{}"` - --> $DIR/parse-error.rs:143:30 + --> $DIR/parse-error.rs:141:30 | LL | global_asm!("{}", const FOO, "{}", const FOO); | ^^^^ expected one of `clobber_abi`, `const`, `options`, or `sym` error: asm template must be a string literal - --> $DIR/parse-error.rs:145:13 + --> $DIR/parse-error.rs:143:13 | LL | global_asm!(format!("{{{}}}", 0), const FOO); | ^^^^^^^^^^^^^^^^^^^^ @@ -373,7 +373,7 @@ LL | global_asm!(format!("{{{}}}", 0), const FOO); = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) error: asm template must be a string literal - --> $DIR/parse-error.rs:147:20 + --> $DIR/parse-error.rs:145:20 | LL | global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR); | ^^^^^^^^^^^^^^^^^^^^ @@ -381,43 +381,43 @@ LL | global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR); = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) error: the `in` operand cannot be used with `global_asm!` - --> $DIR/parse-error.rs:150:19 + --> $DIR/parse-error.rs:148:19 | LL | global_asm!("{}", in(reg)); | ^^ the `in` operand is not meaningful for global-scoped inline assembly, remove it error: the `out` operand cannot be used with `global_asm!` - --> $DIR/parse-error.rs:152:19 + --> $DIR/parse-error.rs:150:19 | LL | global_asm!("{}", out(reg)); | ^^^ the `out` operand is not meaningful for global-scoped inline assembly, remove it error: the `lateout` operand cannot be used with `global_asm!` - --> $DIR/parse-error.rs:154:19 + --> $DIR/parse-error.rs:152:19 | LL | global_asm!("{}", lateout(reg)); | ^^^^^^^ the `lateout` operand is not meaningful for global-scoped inline assembly, remove it error: the `inout` operand cannot be used with `global_asm!` - --> $DIR/parse-error.rs:156:19 + --> $DIR/parse-error.rs:154:19 | LL | global_asm!("{}", inout(reg)); | ^^^^^ the `inout` operand is not meaningful for global-scoped inline assembly, remove it error: the `inlateout` operand cannot be used with `global_asm!` - --> $DIR/parse-error.rs:158:19 + --> $DIR/parse-error.rs:156:19 | LL | global_asm!("{}", inlateout(reg)); | ^^^^^^^^^ the `inlateout` operand is not meaningful for global-scoped inline assembly, remove it error: the `label` operand cannot be used with `global_asm!` - --> $DIR/parse-error.rs:160:19 + --> $DIR/parse-error.rs:158:19 | LL | global_asm!("{}", label(reg)); | ^^^^^ the `label` operand is not meaningful for global-scoped inline assembly, remove it error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:39:37 + --> $DIR/parse-error.rs:37:37 | LL | asm!("{}", options(), const foo); | ^^^ non-constant value @@ -428,7 +428,7 @@ LL | const foo: /* Type */ = 0; | ~~~~~ ++++++++++++ error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:71:44 + --> $DIR/parse-error.rs:69:44 | LL | asm!("{}", clobber_abi("C"), const foo); | ^^^ non-constant value @@ -439,7 +439,7 @@ LL | const foo: /* Type */ = 0; | ~~~~~ ++++++++++++ error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:74:55 + --> $DIR/parse-error.rs:72:55 | LL | asm!("{}", options(), clobber_abi("C"), const foo); | ^^^ non-constant value @@ -450,7 +450,7 @@ LL | const foo: /* Type */ = 0; | ~~~~~ ++++++++++++ error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:76:31 + --> $DIR/parse-error.rs:74:31 | LL | asm!("{a}", a = const foo, a = const bar); | ^^^ non-constant value @@ -461,7 +461,7 @@ LL | const foo: /* Type */ = 0; | ~~~~~ ++++++++++++ error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:76:46 + --> $DIR/parse-error.rs:74:46 | LL | asm!("{a}", a = const foo, a = const bar); | ^^^ non-constant value diff --git a/tests/ui/asm/type-check-1.rs b/tests/ui/asm/type-check-1.rs index 22669dce280..4dc30fb5838 100644 --- a/tests/ui/asm/type-check-1.rs +++ b/tests/ui/asm/type-check-1.rs @@ -2,8 +2,6 @@ //@ ignore-nvptx64 //@ ignore-spirv -#![feature(asm_const)] - use std::arch::{asm, global_asm}; fn main() { diff --git a/tests/ui/asm/type-check-1.stderr b/tests/ui/asm/type-check-1.stderr index d47e6ae1d2a..aa9eed2fce6 100644 --- a/tests/ui/asm/type-check-1.stderr +++ b/tests/ui/asm/type-check-1.stderr @@ -1,17 +1,17 @@ error: invalid asm output - --> $DIR/type-check-1.rs:14:29 + --> $DIR/type-check-1.rs:12:29 | LL | asm!("{}", out(reg) 1 + 2); | ^^^^^ cannot assign to this expression error: invalid asm output - --> $DIR/type-check-1.rs:16:31 + --> $DIR/type-check-1.rs:14:31 | LL | asm!("{}", inout(reg) 1 + 2); | ^^^^^ cannot assign to this expression error[E0277]: the size for values of type `[u64]` cannot be known at compilation time - --> $DIR/type-check-1.rs:22:28 + --> $DIR/type-check-1.rs:20:28 | LL | asm!("{}", in(reg) v[..]); | ^^^^^ doesn't have a size known at compile-time @@ -20,7 +20,7 @@ LL | asm!("{}", in(reg) v[..]); = note: all inline asm arguments must have a statically known size error[E0277]: the size for values of type `[u64]` cannot be known at compilation time - --> $DIR/type-check-1.rs:25:29 + --> $DIR/type-check-1.rs:23:29 | LL | asm!("{}", out(reg) v[..]); | ^^^^^ doesn't have a size known at compile-time @@ -29,7 +29,7 @@ LL | asm!("{}", out(reg) v[..]); = note: all inline asm arguments must have a statically known size error[E0277]: the size for values of type `[u64]` cannot be known at compilation time - --> $DIR/type-check-1.rs:28:31 + --> $DIR/type-check-1.rs:26:31 | LL | asm!("{}", inout(reg) v[..]); | ^^^^^ doesn't have a size known at compile-time @@ -38,7 +38,7 @@ LL | asm!("{}", inout(reg) v[..]); = note: all inline asm arguments must have a statically known size error: cannot use value of type `[u64]` for inline assembly - --> $DIR/type-check-1.rs:22:28 + --> $DIR/type-check-1.rs:20:28 | LL | asm!("{}", in(reg) v[..]); | ^^^^^ @@ -46,7 +46,7 @@ LL | asm!("{}", in(reg) v[..]); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `[u64]` for inline assembly - --> $DIR/type-check-1.rs:25:29 + --> $DIR/type-check-1.rs:23:29 | LL | asm!("{}", out(reg) v[..]); | ^^^^^ @@ -54,7 +54,7 @@ LL | asm!("{}", out(reg) v[..]); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `[u64]` for inline assembly - --> $DIR/type-check-1.rs:28:31 + --> $DIR/type-check-1.rs:26:31 | LL | asm!("{}", inout(reg) v[..]); | ^^^^^ diff --git a/tests/ui/asm/x86_64/bad-reg.rs b/tests/ui/asm/x86_64/bad-reg.rs index d41c46d57bb..2a189a91c5a 100644 --- a/tests/ui/asm/x86_64/bad-reg.rs +++ b/tests/ui/asm/x86_64/bad-reg.rs @@ -1,8 +1,6 @@ //@ only-x86_64 //@ compile-flags: -C target-feature=+avx2 -#![feature(asm_const)] - use std::arch::asm; fn main() { diff --git a/tests/ui/asm/x86_64/bad-reg.stderr b/tests/ui/asm/x86_64/bad-reg.stderr index 8017008e97d..3df1f7b2208 100644 --- a/tests/ui/asm/x86_64/bad-reg.stderr +++ b/tests/ui/asm/x86_64/bad-reg.stderr @@ -1,17 +1,17 @@ error: invalid register class `foo`: unknown register class - --> $DIR/bad-reg.rs:14:20 + --> $DIR/bad-reg.rs:12:20 | LL | asm!("{}", in(foo) foo); | ^^^^^^^^^^^ error: invalid register `foo`: unknown register - --> $DIR/bad-reg.rs:16:18 + --> $DIR/bad-reg.rs:14:18 | LL | asm!("", in("foo") foo); | ^^^^^^^^^^^^^ error: invalid asm template modifier for this register class - --> $DIR/bad-reg.rs:18:15 + --> $DIR/bad-reg.rs:16:15 | LL | asm!("{:z}", in(reg) foo); | ^^^^ ----------- argument @@ -21,7 +21,7 @@ LL | asm!("{:z}", in(reg) foo); = note: the `reg` register class supports the following template modifiers: `l`, `x`, `e`, `r` error: invalid asm template modifier for this register class - --> $DIR/bad-reg.rs:20:15 + --> $DIR/bad-reg.rs:18:15 | LL | asm!("{:r}", in(xmm_reg) foo); | ^^^^ --------------- argument @@ -31,7 +31,7 @@ LL | asm!("{:r}", in(xmm_reg) foo); = note: the `xmm_reg` register class supports the following template modifiers: `x`, `y`, `z` error: asm template modifiers are not allowed for `const` arguments - --> $DIR/bad-reg.rs:22:15 + --> $DIR/bad-reg.rs:20:15 | LL | asm!("{:a}", const 0); | ^^^^ ------- argument @@ -39,7 +39,7 @@ LL | asm!("{:a}", const 0); | template modifier error: asm template modifiers are not allowed for `sym` arguments - --> $DIR/bad-reg.rs:24:15 + --> $DIR/bad-reg.rs:22:15 | LL | asm!("{:a}", sym main); | ^^^^ -------- argument @@ -47,67 +47,67 @@ LL | asm!("{:a}", sym main); | template modifier error: invalid register `ebp`: the frame pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:26:18 + --> $DIR/bad-reg.rs:24:18 | LL | asm!("", in("ebp") foo); | ^^^^^^^^^^^^^ error: invalid register `rsp`: the stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:28:18 + --> $DIR/bad-reg.rs:26:18 | LL | asm!("", in("rsp") foo); | ^^^^^^^^^^^^^ error: invalid register `ip`: the instruction pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:30:18 + --> $DIR/bad-reg.rs:28:18 | LL | asm!("", in("ip") foo); | ^^^^^^^^^^^^ error: register class `x87_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:33:18 + --> $DIR/bad-reg.rs:31:18 | LL | asm!("", in("st(2)") foo); | ^^^^^^^^^^^^^^^ error: register class `mmx_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:36:18 + --> $DIR/bad-reg.rs:34:18 | LL | asm!("", in("mm0") foo); | ^^^^^^^^^^^^^ error: register class `kreg0` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:39:18 + --> $DIR/bad-reg.rs:37:18 | LL | asm!("", in("k0") foo); | ^^^^^^^^^^^^ error: register class `x87_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:44:20 + --> $DIR/bad-reg.rs:42:20 | LL | asm!("{}", in(x87_reg) foo); | ^^^^^^^^^^^^^^^ error: register class `mmx_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:47:20 + --> $DIR/bad-reg.rs:45:20 | LL | asm!("{}", in(mmx_reg) foo); | ^^^^^^^^^^^^^^^ error: register class `x87_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:50:20 + --> $DIR/bad-reg.rs:48:20 | LL | asm!("{}", out(x87_reg) _); | ^^^^^^^^^^^^^^ error: register class `mmx_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:52:20 + --> $DIR/bad-reg.rs:50:20 | LL | asm!("{}", out(mmx_reg) _); | ^^^^^^^^^^^^^^ error: register `al` conflicts with register `eax` - --> $DIR/bad-reg.rs:58:33 + --> $DIR/bad-reg.rs:56:33 | LL | asm!("", in("eax") foo, in("al") bar); | ------------- ^^^^^^^^^^^^ register `al` @@ -115,7 +115,7 @@ LL | asm!("", in("eax") foo, in("al") bar); | register `eax` error: register `rax` conflicts with register `rax` - --> $DIR/bad-reg.rs:61:33 + --> $DIR/bad-reg.rs:59:33 | LL | asm!("", in("rax") foo, out("rax") bar); | ------------- ^^^^^^^^^^^^^^ register `rax` @@ -123,13 +123,13 @@ LL | asm!("", in("rax") foo, out("rax") bar); | register `rax` | help: use `lateout` instead of `out` to avoid conflict - --> $DIR/bad-reg.rs:61:18 + --> $DIR/bad-reg.rs:59:18 | LL | asm!("", in("rax") foo, out("rax") bar); | ^^^^^^^^^^^^^ error: register `ymm0` conflicts with register `xmm0` - --> $DIR/bad-reg.rs:66:34 + --> $DIR/bad-reg.rs:64:34 | LL | asm!("", in("xmm0") foo, in("ymm0") bar); | -------------- ^^^^^^^^^^^^^^ register `ymm0` @@ -137,7 +137,7 @@ LL | asm!("", in("xmm0") foo, in("ymm0") bar); | register `xmm0` error: register `ymm0` conflicts with register `xmm0` - --> $DIR/bad-reg.rs:68:34 + --> $DIR/bad-reg.rs:66:34 | LL | asm!("", in("xmm0") foo, out("ymm0") bar); | -------------- ^^^^^^^^^^^^^^^ register `ymm0` @@ -145,13 +145,13 @@ LL | asm!("", in("xmm0") foo, out("ymm0") bar); | register `xmm0` | help: use `lateout` instead of `out` to avoid conflict - --> $DIR/bad-reg.rs:68:18 + --> $DIR/bad-reg.rs:66:18 | LL | asm!("", in("xmm0") foo, out("ymm0") bar); | ^^^^^^^^^^^^^^ error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:33:30 + --> $DIR/bad-reg.rs:31:30 | LL | asm!("", in("st(2)") foo); | ^^^ @@ -159,7 +159,7 @@ LL | asm!("", in("st(2)") foo); = note: register class `x87_reg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:36:28 + --> $DIR/bad-reg.rs:34:28 | LL | asm!("", in("mm0") foo); | ^^^ @@ -167,7 +167,7 @@ LL | asm!("", in("mm0") foo); = note: register class `mmx_reg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:39:27 + --> $DIR/bad-reg.rs:37:27 | LL | asm!("", in("k0") foo); | ^^^ @@ -175,7 +175,7 @@ LL | asm!("", in("k0") foo); = note: register class `kreg0` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:44:32 + --> $DIR/bad-reg.rs:42:32 | LL | asm!("{}", in(x87_reg) foo); | ^^^ @@ -183,7 +183,7 @@ LL | asm!("{}", in(x87_reg) foo); = note: register class `x87_reg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:47:32 + --> $DIR/bad-reg.rs:45:32 | LL | asm!("{}", in(mmx_reg) foo); | ^^^ @@ -191,7 +191,7 @@ LL | asm!("{}", in(mmx_reg) foo); = note: register class `mmx_reg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:58:42 + --> $DIR/bad-reg.rs:56:42 | LL | asm!("", in("eax") foo, in("al") bar); | ^^^ @@ -199,7 +199,7 @@ LL | asm!("", in("eax") foo, in("al") bar); = note: register class `reg_byte` supports these types: i8 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:63:27 + --> $DIR/bad-reg.rs:61:27 | LL | asm!("", in("al") foo, lateout("al") bar); | ^^^ @@ -207,7 +207,7 @@ LL | asm!("", in("al") foo, lateout("al") bar); = note: register class `reg_byte` supports these types: i8 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:63:46 + --> $DIR/bad-reg.rs:61:46 | LL | asm!("", in("al") foo, lateout("al") bar); | ^^^ diff --git a/tests/ui/asm/x86_64/const.rs b/tests/ui/asm/x86_64/const.rs index 817a338a5b9..eaaaf92e823 100644 --- a/tests/ui/asm/x86_64/const.rs +++ b/tests/ui/asm/x86_64/const.rs @@ -2,8 +2,6 @@ //@ run-pass //@ needs-asm-support -#![feature(asm_const)] - use std::arch::{asm, global_asm}; fn const_generic() -> usize { diff --git a/tests/ui/asm/x86_64/type-check-3.rs b/tests/ui/asm/x86_64/type-check-3.rs index bd242af3dbc..bfb795d2624 100644 --- a/tests/ui/asm/x86_64/type-check-3.rs +++ b/tests/ui/asm/x86_64/type-check-3.rs @@ -1,8 +1,6 @@ //@ only-x86_64 //@ compile-flags: -C target-feature=+avx512f -#![feature(asm_const)] - use std::arch::{asm, global_asm}; use std::arch::x86_64::{_mm256_setzero_ps, _mm_setzero_ps}; diff --git a/tests/ui/asm/x86_64/type-check-3.stderr b/tests/ui/asm/x86_64/type-check-3.stderr index 202b97ca5c0..5a7b349413e 100644 --- a/tests/ui/asm/x86_64/type-check-3.stderr +++ b/tests/ui/asm/x86_64/type-check-3.stderr @@ -1,5 +1,5 @@ error: type `i128` cannot be used with this register class - --> $DIR/type-check-3.rs:14:28 + --> $DIR/type-check-3.rs:12:28 | LL | asm!("{}", in(reg) 0i128); | ^^^^^ @@ -7,7 +7,7 @@ LL | asm!("{}", in(reg) 0i128); = note: register class `reg` supports these types: i16, i32, i64, f16, f32, f64 error: type `__m128` cannot be used with this register class - --> $DIR/type-check-3.rs:16:28 + --> $DIR/type-check-3.rs:14:28 | LL | asm!("{}", in(reg) _mm_setzero_ps()); | ^^^^^^^^^^^^^^^^ @@ -15,7 +15,7 @@ LL | asm!("{}", in(reg) _mm_setzero_ps()); = note: register class `reg` supports these types: i16, i32, i64, f16, f32, f64 error: type `__m256` cannot be used with this register class - --> $DIR/type-check-3.rs:18:28 + --> $DIR/type-check-3.rs:16:28 | LL | asm!("{}", in(reg) _mm256_setzero_ps()); | ^^^^^^^^^^^^^^^^^^^ @@ -23,7 +23,7 @@ LL | asm!("{}", in(reg) _mm256_setzero_ps()); = note: register class `reg` supports these types: i16, i32, i64, f16, f32, f64 error: type `u8` cannot be used with this register class - --> $DIR/type-check-3.rs:20:32 + --> $DIR/type-check-3.rs:18:32 | LL | asm!("{}", in(xmm_reg) 0u8); | ^^^ @@ -31,7 +31,7 @@ LL | asm!("{}", in(xmm_reg) 0u8); = note: register class `xmm_reg` supports these types: i32, i64, f16, f32, f64, f128, i8x16, i16x8, i32x4, i64x2, f16x8, f32x4, f64x2 error: `avx512bw` target feature is not enabled - --> $DIR/type-check-3.rs:29:29 + --> $DIR/type-check-3.rs:27:29 | LL | asm!("{}", in(kreg) 0u64); | ^^^^ @@ -39,7 +39,7 @@ LL | asm!("{}", in(kreg) 0u64); = note: this is required to use type `u64` with register class `kreg` warning: formatting may not be suitable for sub-register argument - --> $DIR/type-check-3.rs:34:15 + --> $DIR/type-check-3.rs:32:15 | LL | asm!("{0} {0}", in(reg) 0i16); | ^^^ ^^^ ---- for this argument @@ -49,7 +49,7 @@ LL | asm!("{0} {0}", in(reg) 0i16); = note: `#[warn(asm_sub_register)]` on by default warning: formatting may not be suitable for sub-register argument - --> $DIR/type-check-3.rs:36:15 + --> $DIR/type-check-3.rs:34:15 | LL | asm!("{0} {0:x}", in(reg) 0i16); | ^^^ ---- for this argument @@ -58,7 +58,7 @@ LL | asm!("{0} {0:x}", in(reg) 0i16); = help: or use `{0:r}` to keep the default formatting of `rax` (for 64-bit values) warning: formatting may not be suitable for sub-register argument - --> $DIR/type-check-3.rs:38:15 + --> $DIR/type-check-3.rs:36:15 | LL | asm!("{}", in(reg) 0i32); | ^^ ---- for this argument @@ -67,7 +67,7 @@ LL | asm!("{}", in(reg) 0i32); = help: or use `{0:r}` to keep the default formatting of `rax` (for 64-bit values) warning: formatting may not be suitable for sub-register argument - --> $DIR/type-check-3.rs:41:15 + --> $DIR/type-check-3.rs:39:15 | LL | asm!("{}", in(ymm_reg) 0i64); | ^^ ---- for this argument @@ -76,7 +76,7 @@ LL | asm!("{}", in(ymm_reg) 0i64); = help: or use `{0:y}` to keep the default formatting of `ymm0` (for 256-bit values) error: type `i8` cannot be used with this register class - --> $DIR/type-check-3.rs:52:28 + --> $DIR/type-check-3.rs:50:28 | LL | asm!("{}", in(reg) 0i8); | ^^^ @@ -85,7 +85,7 @@ LL | asm!("{}", in(reg) 0i8); = help: consider using the `reg_byte` register class instead error: incompatible types for asm inout argument - --> $DIR/type-check-3.rs:64:33 + --> $DIR/type-check-3.rs:62:33 | LL | asm!("{:r}", inout(reg) 0u32 => val_f32); | ^^^^ ^^^^^^^ type `f32` @@ -95,7 +95,7 @@ LL | asm!("{:r}", inout(reg) 0u32 => val_f32); = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size error: incompatible types for asm inout argument - --> $DIR/type-check-3.rs:66:33 + --> $DIR/type-check-3.rs:64:33 | LL | asm!("{:r}", inout(reg) 0u32 => val_ptr); | ^^^^ ^^^^^^^ type `*mut u8` @@ -105,7 +105,7 @@ LL | asm!("{:r}", inout(reg) 0u32 => val_ptr); = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size error: incompatible types for asm inout argument - --> $DIR/type-check-3.rs:68:33 + --> $DIR/type-check-3.rs:66:33 | LL | asm!("{:r}", inout(reg) main => val_u32); | ^^^^ ^^^^^^^ type `u32` diff --git a/tests/ui/asm/x86_64/type-check-4.rs b/tests/ui/asm/x86_64/type-check-4.rs index f7bf60d04df..9503cd6d8ab 100644 --- a/tests/ui/asm/x86_64/type-check-4.rs +++ b/tests/ui/asm/x86_64/type-check-4.rs @@ -1,8 +1,6 @@ //@ only-x86_64 //@ compile-flags: -C target-feature=+avx512f -#![feature(asm_const)] - use std::arch::{asm, global_asm}; use std::arch::x86_64::{_mm256_setzero_ps, _mm_setzero_ps}; diff --git a/tests/ui/asm/x86_64/type-check-4.stderr b/tests/ui/asm/x86_64/type-check-4.stderr index cbdc051b343..f1bbc9e7d33 100644 --- a/tests/ui/asm/x86_64/type-check-4.stderr +++ b/tests/ui/asm/x86_64/type-check-4.stderr @@ -1,5 +1,5 @@ error[E0658]: referencing statics in constants is unstable - --> $DIR/type-check-4.rs:21:25 + --> $DIR/type-check-4.rs:19:25 | LL | global_asm!("{}", const S); | ^ @@ -11,7 +11,7 @@ LL | global_asm!("{}", const S); = help: to fix this, the value can be extracted to a `const` and then used. error[E0658]: referencing statics in constants is unstable - --> $DIR/type-check-4.rs:24:35 + --> $DIR/type-check-4.rs:22:35 | LL | global_asm!("{}", const const_foo(S)); | ^ @@ -23,7 +23,7 @@ LL | global_asm!("{}", const const_foo(S)); = help: to fix this, the value can be extracted to a `const` and then used. error[E0658]: referencing statics in constants is unstable - --> $DIR/type-check-4.rs:27:35 + --> $DIR/type-check-4.rs:25:35 | LL | global_asm!("{}", const const_bar(S)); | ^ diff --git a/tests/ui/asm/x86_64/x86_64_parse_error.rs b/tests/ui/asm/x86_64/x86_64_parse_error.rs index 850033d4ce0..3df0febf6b0 100644 --- a/tests/ui/asm/x86_64/x86_64_parse_error.rs +++ b/tests/ui/asm/x86_64/x86_64_parse_error.rs @@ -1,7 +1,5 @@ //@ only-x86_64 -#![feature(asm_const)] - use std::arch::asm; fn main() { diff --git a/tests/ui/asm/x86_64/x86_64_parse_error.stderr b/tests/ui/asm/x86_64/x86_64_parse_error.stderr index 9751f7b09d0..b64f6c1127e 100644 --- a/tests/ui/asm/x86_64/x86_64_parse_error.stderr +++ b/tests/ui/asm/x86_64/x86_64_parse_error.stderr @@ -1,17 +1,28 @@ error: explicit register arguments cannot have names - --> $DIR/x86_64_parse_error.rs:11:18 + --> $DIR/x86_64_parse_error.rs:9:18 | LL | asm!("", a = in("eax") foo); | ^^^^^^^^^^^^^^^^^ error: positional arguments cannot follow named arguments or explicit register arguments - --> $DIR/x86_64_parse_error.rs:17:36 + --> $DIR/x86_64_parse_error.rs:15:36 | LL | asm!("{1}", in("eax") foo, const bar); | ------------- ^^^^^^^^^ positional argument | | | explicit register argument +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/x86_64_parse_error.rs:11:46 + | +LL | asm!("{a}", in("eax") foo, a = const bar); + | ^^^ non-constant value + | +help: consider using `const` instead of `let` + | +LL | const bar: /* Type */ = 0; + | ~~~~~ ++++++++++++ + error[E0435]: attempt to use a non-constant value in a constant --> $DIR/x86_64_parse_error.rs:13:46 | @@ -24,18 +35,7 @@ LL | const bar: /* Type */ = 0; | ~~~~~ ++++++++++++ error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/x86_64_parse_error.rs:15:46 - | -LL | asm!("{a}", in("eax") foo, a = const bar); - | ^^^ non-constant value - | -help: consider using `const` instead of `let` - | -LL | const bar: /* Type */ = 0; - | ~~~~~ ++++++++++++ - -error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/x86_64_parse_error.rs:17:42 + --> $DIR/x86_64_parse_error.rs:15:42 | LL | asm!("{1}", in("eax") foo, const bar); | ^^^ non-constant value diff --git a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.stderr b/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.stderr index a495e94bd9a..cf5d8f614dd 100644 --- a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.stderr +++ b/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.stderr @@ -4,11 +4,6 @@ error[E0391]: cycle detected when computing predicates of `Foo` LL | struct Foo { | ^^^^^^^^^^ | -note: ...which requires computing predicates of `Foo`... - --> $DIR/cycle-iat-inside-of-adt.rs:7:1 - | -LL | struct Foo { - | ^^^^^^^^^^ note: ...which requires computing inferred outlives predicates of `Foo`... --> $DIR/cycle-iat-inside-of-adt.rs:7:1 | diff --git a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-where-predicate.stderr b/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-where-predicate.stderr index e7292c08ebd..e97a5df9d49 100644 --- a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-where-predicate.stderr +++ b/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-where-predicate.stderr @@ -4,11 +4,6 @@ error[E0391]: cycle detected when computing predicates of `user` LL | fn user() where S::P: std::fmt::Debug {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: ...which requires computing predicates of `user`... - --> $DIR/cycle-iat-inside-of-where-predicate.rs:8:1 - | -LL | fn user() where S::P: std::fmt::Debug {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires computing explicit predicates of `user`... --> $DIR/cycle-iat-inside-of-where-predicate.rs:8:1 | diff --git a/tests/ui/async-await/async-closures/move-out-of-ref.rs b/tests/ui/async-await/async-closures/move-out-of-ref.rs new file mode 100644 index 00000000000..a05447232f6 --- /dev/null +++ b/tests/ui/async-await/async-closures/move-out-of-ref.rs @@ -0,0 +1,16 @@ +//@ compile-flags: -Zvalidate-mir +//@ edition: 2021 + +#![feature(async_closure)] + +// NOT copy. +struct Ty; + +fn hello(x: &Ty) { + let c = async || { + *x; + //~^ ERROR cannot move out of `*x` which is behind a shared reference + }; +} + +fn main() {} diff --git a/tests/ui/async-await/async-closures/move-out-of-ref.stderr b/tests/ui/async-await/async-closures/move-out-of-ref.stderr new file mode 100644 index 00000000000..294905a481d --- /dev/null +++ b/tests/ui/async-await/async-closures/move-out-of-ref.stderr @@ -0,0 +1,18 @@ +error[E0507]: cannot move out of `*x` which is behind a shared reference + --> $DIR/move-out-of-ref.rs:11:9 + | +LL | *x; + | ^^ move occurs because `*x` has type `Ty`, which does not implement the `Copy` trait + | +note: if `Ty` implemented `Clone`, you could clone the value + --> $DIR/move-out-of-ref.rs:7:1 + | +LL | struct Ty; + | ^^^^^^^^^ consider implementing `Clone` for this type +... +LL | *x; + | -- you could clone this value + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/async-await/async-closures/sig-from-bare-fn.rs b/tests/ui/async-await/async-closures/sig-from-bare-fn.rs new file mode 100644 index 00000000000..a679471a3b3 --- /dev/null +++ b/tests/ui/async-await/async-closures/sig-from-bare-fn.rs @@ -0,0 +1,49 @@ +//@ check-pass +//@ edition: 2021 + +// Make sure that we infer the args of an async closure even if it's passed to +// a function that requires the async closure implement `Fn*` but does *not* have +// a `Future` bound on the return type. + +#![feature(async_closure)] + +use std::future::Future; + +trait TryStream { + type Ok; + type Err; +} + +trait TryFuture { + type Ok; + type Err; +} + +impl TryFuture for F where F: Future> { + type Ok = T; + type Err = E; +} + +trait TryStreamExt: TryStream { + fn try_for_each(&self, f: F) + where + F: FnMut(Self::Ok) -> Fut, + Fut: TryFuture; +} + +impl TryStreamExt for S where S: TryStream { + fn try_for_each(&self, f: F) + where + F: FnMut(Self::Ok) -> Fut, + Fut: TryFuture, + { } +} + +fn test(stream: impl TryStream) { + stream.try_for_each(async |s| { + s.trim(); // Make sure we know the type of `s` at this point. + Ok(()) + }); +} + +fn main() {} diff --git a/tests/ui/async-await/async-fn/recurse-ice-129215.rs b/tests/ui/async-await/async-fn/recurse-ice-129215.rs new file mode 100644 index 00000000000..06a2d7be9ef --- /dev/null +++ b/tests/ui/async-await/async-fn/recurse-ice-129215.rs @@ -0,0 +1,9 @@ +//@ edition: 2021 + +async fn a() { + //~^ ERROR `()` is not a future + //~| ERROR mismatched types + a() //~ ERROR `()` is not a future +} + +fn main() {} diff --git a/tests/ui/async-await/async-fn/recurse-ice-129215.stderr b/tests/ui/async-await/async-fn/recurse-ice-129215.stderr new file mode 100644 index 00000000000..98c7be2a5a3 --- /dev/null +++ b/tests/ui/async-await/async-fn/recurse-ice-129215.stderr @@ -0,0 +1,34 @@ +error[E0277]: `()` is not a future + --> $DIR/recurse-ice-129215.rs:6:5 + | +LL | a() + | ^^^ `()` is not a future + | + = help: the trait `Future` is not implemented for `()` + +error[E0277]: `()` is not a future + --> $DIR/recurse-ice-129215.rs:3:1 + | +LL | async fn a() { + | ^^^^^^^^^^^^ `()` is not a future + | + = help: the trait `Future` is not implemented for `()` + +error[E0308]: mismatched types + --> $DIR/recurse-ice-129215.rs:3:14 + | +LL | async fn a() { + | ______________^ +LL | | +LL | | +LL | | a() +LL | | } + | |_^ expected `()`, found `async` fn body + | + = note: expected unit type `()` + found `async` fn body `{async fn body of a()}` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr b/tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr index 5ae1d78a92b..167b5ee4425 100644 --- a/tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr +++ b/tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr @@ -26,10 +26,10 @@ LL | | (a, b) LL | | } | |_^ | -help: to declare that `impl Trait<'a>` captures `'b`, you can add an explicit `'b` lifetime bound +help: add a `use<...>` bound to explicitly capture `'b` | -LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b { - | ++++ +LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + use<'a, 'b> { + | +++++++++++++ error: aborting due to 2 previous errors diff --git a/tests/ui/attributes/assoc-expr.rs b/tests/ui/attributes/assoc-expr.rs new file mode 100644 index 00000000000..f39557d2ef0 --- /dev/null +++ b/tests/ui/attributes/assoc-expr.rs @@ -0,0 +1,42 @@ +//@ check-pass +// This test triggered an assertion failure in token collection due to +// mishandling of attributes on associative expressions. + +#![feature(cfg_eval)] +#![feature(rustc_attrs)] +#![feature(stmt_expr_attributes)] +#![allow(internal_features)] + +fn main() {} + +#[cfg_eval] +struct Foo1( + [ bool; { + let _x = 30; + #[cfg_attr(unix, rustc_dummy(aa))] 1 + } ] +); + +#[cfg_eval] +struct Foo12( + [ bool; { + let _x = 30; + #[cfg_attr(unix, rustc_dummy(bb))] 1 + 2 + } ] +); + +#[cfg_eval] +struct Foox( + [ bool; { + let _x = 30; + #[cfg_attr(unix, rustc_dummy(cc))] _x + } ] +); + +#[cfg_eval] +struct Foox2( + [ bool; { + let _x = 30; + #[cfg_attr(unix, rustc_dummy(dd))] _x + 2 + } ] +); diff --git a/tests/ui/attributes/linkage.rs b/tests/ui/attributes/linkage.rs new file mode 100644 index 00000000000..0d5ce699fa8 --- /dev/null +++ b/tests/ui/attributes/linkage.rs @@ -0,0 +1,42 @@ +#![feature(linkage)] +#![feature(stmt_expr_attributes)] +#![deny(unused_attributes)] +#![allow(dead_code)] + +#[linkage = "weak"] //~ ERROR attribute should be applied to a function or static +type InvalidTy = (); + +#[linkage = "weak"] //~ ERROR attribute should be applied to a function or static +mod invalid_module {} + +#[linkage = "weak"] //~ ERROR attribute should be applied to a function or static +struct F; + +#[linkage = "weak"] //~ ERROR attribute should be applied to a function or static +impl F { + #[linkage = "weak"] + fn valid(&self) {} +} + +#[linkage = "weak"] +fn f() { + #[linkage = "weak"] + { + 1 + }; + //~^^^^ ERROR attribute should be applied to a function or static +} + +extern "C" { + #[linkage = "weak"] + static A: *const (); + + #[linkage = "weak"] + fn bar(); +} + +fn main() { + let _ = #[linkage = "weak"] + (|| 1); + //~^^ ERROR attribute should be applied to a function or static +} diff --git a/tests/ui/attributes/linkage.stderr b/tests/ui/attributes/linkage.stderr new file mode 100644 index 00000000000..d5595529f40 --- /dev/null +++ b/tests/ui/attributes/linkage.stderr @@ -0,0 +1,55 @@ +error: attribute should be applied to a function or static + --> $DIR/linkage.rs:6:1 + | +LL | #[linkage = "weak"] + | ^^^^^^^^^^^^^^^^^^^ +LL | type InvalidTy = (); + | -------------------- not a function definition or static + +error: attribute should be applied to a function or static + --> $DIR/linkage.rs:9:1 + | +LL | #[linkage = "weak"] + | ^^^^^^^^^^^^^^^^^^^ +LL | mod invalid_module {} + | --------------------- not a function definition or static + +error: attribute should be applied to a function or static + --> $DIR/linkage.rs:12:1 + | +LL | #[linkage = "weak"] + | ^^^^^^^^^^^^^^^^^^^ +LL | struct F; + | --------- not a function definition or static + +error: attribute should be applied to a function or static + --> $DIR/linkage.rs:15:1 + | +LL | #[linkage = "weak"] + | ^^^^^^^^^^^^^^^^^^^ +LL | / impl F { +LL | | #[linkage = "weak"] +LL | | fn valid(&self) {} +LL | | } + | |_- not a function definition or static + +error: attribute should be applied to a function or static + --> $DIR/linkage.rs:23:5 + | +LL | #[linkage = "weak"] + | ^^^^^^^^^^^^^^^^^^^ +LL | / { +LL | | 1 +LL | | }; + | |_____- not a function definition or static + +error: attribute should be applied to a function or static + --> $DIR/linkage.rs:39:13 + | +LL | let _ = #[linkage = "weak"] + | ^^^^^^^^^^^^^^^^^^^ +LL | (|| 1); + | ------ not a function definition or static + +error: aborting due to 6 previous errors + diff --git a/tests/ui/attributes/may_dangle.rs b/tests/ui/attributes/may_dangle.rs new file mode 100644 index 00000000000..209ba0e88ad --- /dev/null +++ b/tests/ui/attributes/may_dangle.rs @@ -0,0 +1,53 @@ +#![feature(dropck_eyepatch)] + +struct Implee1<'a, T, const N: usize>(&'a T); +struct Implee2<'a, T, const N: usize>(&'a T); +struct Implee3<'a, T, const N: usize>(&'a T); +trait NotDrop {} + +unsafe impl<#[may_dangle] 'a, T, const N: usize> NotDrop for Implee1<'a, T, N> {} +//~^ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl + +unsafe impl<'a, #[may_dangle] T, const N: usize> NotDrop for Implee2<'a, T, N> {} +//~^ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl + +unsafe impl<'a, T, #[may_dangle] const N: usize> Drop for Implee1<'a, T, N> { + //~^ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl + fn drop(&mut self) {} +} + +// Ok, lifetime param in a `Drop` impl. +unsafe impl<#[may_dangle] 'a, T, const N: usize> Drop for Implee2<'a, T, N> { + fn drop(&mut self) {} +} + +// Ok, type param in a `Drop` impl. +unsafe impl<'a, #[may_dangle] T, const N: usize> Drop for Implee3<'a, T, N> { + fn drop(&mut self) {} +} + +// Check that this check is not textual. +mod fake { + trait Drop { + fn drop(&mut self); + } + struct Implee(T); + + unsafe impl<#[may_dangle] T> Drop for Implee { + //~^ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl + fn drop(&mut self) {} + } +} + +#[may_dangle] //~ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl +struct Dangling; + +#[may_dangle] //~ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl +impl NotDrop for () { +} + +#[may_dangle] //~ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl +fn main() { + #[may_dangle] //~ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl + let () = (); +} diff --git a/tests/ui/attributes/may_dangle.stderr b/tests/ui/attributes/may_dangle.stderr new file mode 100644 index 00000000000..dc24f847f71 --- /dev/null +++ b/tests/ui/attributes/may_dangle.stderr @@ -0,0 +1,50 @@ +error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl + --> $DIR/may_dangle.rs:8:13 + | +LL | unsafe impl<#[may_dangle] 'a, T, const N: usize> NotDrop for Implee1<'a, T, N> {} + | ^^^^^^^^^^^^^ + +error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl + --> $DIR/may_dangle.rs:11:17 + | +LL | unsafe impl<'a, #[may_dangle] T, const N: usize> NotDrop for Implee2<'a, T, N> {} + | ^^^^^^^^^^^^^ + +error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl + --> $DIR/may_dangle.rs:14:20 + | +LL | unsafe impl<'a, T, #[may_dangle] const N: usize> Drop for Implee1<'a, T, N> { + | ^^^^^^^^^^^^^ + +error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl + --> $DIR/may_dangle.rs:42:1 + | +LL | #[may_dangle] + | ^^^^^^^^^^^^^ + +error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl + --> $DIR/may_dangle.rs:45:1 + | +LL | #[may_dangle] + | ^^^^^^^^^^^^^ + +error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl + --> $DIR/may_dangle.rs:49:1 + | +LL | #[may_dangle] + | ^^^^^^^^^^^^^ + +error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl + --> $DIR/may_dangle.rs:51:5 + | +LL | #[may_dangle] + | ^^^^^^^^^^^^^ + +error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl + --> $DIR/may_dangle.rs:36:17 + | +LL | unsafe impl<#[may_dangle] T> Drop for Implee { + | ^^^^^^^^^^^^^ + +error: aborting due to 8 previous errors + diff --git a/tests/ui/attributes/rustc_pub_transparent.rs b/tests/ui/attributes/rustc_pub_transparent.rs new file mode 100644 index 00000000000..4508fa39baf --- /dev/null +++ b/tests/ui/attributes/rustc_pub_transparent.rs @@ -0,0 +1,25 @@ +#![feature(rustc_attrs, transparent_unions)] + +#[rustc_pub_transparent] +#[repr(transparent)] +union E { + value: T, + uninit: (), +} + +#[repr(transparent)] +#[rustc_pub_transparent] +struct S(T); + +#[rustc_pub_transparent] //~ ERROR attribute should be applied to `#[repr(transparent)]` types +#[repr(C)] +struct S1 { + A: u8, +} + +#[rustc_pub_transparent] //~ ERROR attribute should be applied to `#[repr(transparent)]` types +struct S2 { + value: T, +} + +fn main() {} diff --git a/tests/ui/attributes/rustc_pub_transparent.stderr b/tests/ui/attributes/rustc_pub_transparent.stderr new file mode 100644 index 00000000000..1d1f9437cb2 --- /dev/null +++ b/tests/ui/attributes/rustc_pub_transparent.stderr @@ -0,0 +1,23 @@ +error: attribute should be applied to `#[repr(transparent)]` types + --> $DIR/rustc_pub_transparent.rs:14:1 + | +LL | #[rustc_pub_transparent] + | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[repr(C)] +LL | / struct S1 { +LL | | A: u8, +LL | | } + | |_- not a `#[repr(transparent)]` type + +error: attribute should be applied to `#[repr(transparent)]` types + --> $DIR/rustc_pub_transparent.rs:20:1 + | +LL | #[rustc_pub_transparent] + | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / struct S2 { +LL | | value: T, +LL | | } + | |_- not a `#[repr(transparent)]` type + +error: aborting due to 2 previous errors + diff --git a/tests/ui/attributes/unsafe/cfg-unsafe-attributes.rs b/tests/ui/attributes/unsafe/cfg-unsafe-attributes.rs index ce365d1a8b1..6a9853b2f6f 100644 --- a/tests/ui/attributes/unsafe/cfg-unsafe-attributes.rs +++ b/tests/ui/attributes/unsafe/cfg-unsafe-attributes.rs @@ -1,5 +1,4 @@ //@ build-pass -#![feature(unsafe_attributes)] #[cfg_attr(all(), unsafe(no_mangle))] fn a() {} diff --git a/tests/ui/attributes/unsafe/derive-unsafe-attributes.rs b/tests/ui/attributes/unsafe/derive-unsafe-attributes.rs index b8edb4aab90..95fc19f506b 100644 --- a/tests/ui/attributes/unsafe/derive-unsafe-attributes.rs +++ b/tests/ui/attributes/unsafe/derive-unsafe-attributes.rs @@ -1,5 +1,3 @@ -#![feature(unsafe_attributes)] - #[derive(unsafe(Debug))] //~^ ERROR: expected identifier, found keyword `unsafe` //~| ERROR: traits in `#[derive(...)]` don't accept arguments diff --git a/tests/ui/attributes/unsafe/derive-unsafe-attributes.stderr b/tests/ui/attributes/unsafe/derive-unsafe-attributes.stderr index c40a5512fd5..4002c930b63 100644 --- a/tests/ui/attributes/unsafe/derive-unsafe-attributes.stderr +++ b/tests/ui/attributes/unsafe/derive-unsafe-attributes.stderr @@ -1,5 +1,5 @@ error: expected identifier, found keyword `unsafe` - --> $DIR/derive-unsafe-attributes.rs:3:10 + --> $DIR/derive-unsafe-attributes.rs:1:10 | LL | #[derive(unsafe(Debug))] | ^^^^^^ expected identifier, found keyword @@ -10,13 +10,13 @@ LL | #[derive(r#unsafe(Debug))] | ++ error: traits in `#[derive(...)]` don't accept arguments - --> $DIR/derive-unsafe-attributes.rs:3:16 + --> $DIR/derive-unsafe-attributes.rs:1:16 | LL | #[derive(unsafe(Debug))] | ^^^^^^^ help: remove the arguments error: `derive` is not an unsafe attribute - --> $DIR/derive-unsafe-attributes.rs:12:3 + --> $DIR/derive-unsafe-attributes.rs:10:3 | LL | #[unsafe(derive(Debug))] | ^^^^^^ this is not an unsafe attribute @@ -24,7 +24,7 @@ LL | #[unsafe(derive(Debug))] = note: extraneous unsafe is not allowed in attributes error: expected identifier, found keyword `unsafe` - --> $DIR/derive-unsafe-attributes.rs:3:10 + --> $DIR/derive-unsafe-attributes.rs:1:10 | LL | #[derive(unsafe(Debug))] | ^^^^^^ expected identifier, found keyword @@ -36,7 +36,7 @@ LL | #[derive(r#unsafe(Debug))] | ++ error: expected identifier, found keyword `unsafe` - --> $DIR/derive-unsafe-attributes.rs:3:10 + --> $DIR/derive-unsafe-attributes.rs:1:10 | LL | #[derive(unsafe(Debug))] | ^^^^^^ expected identifier, found keyword @@ -48,13 +48,13 @@ LL | #[derive(r#unsafe(Debug))] | ++ error: cannot find derive macro `r#unsafe` in this scope - --> $DIR/derive-unsafe-attributes.rs:3:10 + --> $DIR/derive-unsafe-attributes.rs:1:10 | LL | #[derive(unsafe(Debug))] | ^^^^^^ error: cannot find derive macro `r#unsafe` in this scope - --> $DIR/derive-unsafe-attributes.rs:3:10 + --> $DIR/derive-unsafe-attributes.rs:1:10 | LL | #[derive(unsafe(Debug))] | ^^^^^^ diff --git a/tests/ui/attributes/unsafe/double-unsafe-attributes.rs b/tests/ui/attributes/unsafe/double-unsafe-attributes.rs index a6c0ea578f2..894d1327da7 100644 --- a/tests/ui/attributes/unsafe/double-unsafe-attributes.rs +++ b/tests/ui/attributes/unsafe/double-unsafe-attributes.rs @@ -1,5 +1,3 @@ -#![feature(unsafe_attributes)] - #[unsafe(unsafe(no_mangle))] //~^ ERROR expected identifier, found keyword `unsafe` //~| ERROR cannot find attribute `r#unsafe` in this scope diff --git a/tests/ui/attributes/unsafe/double-unsafe-attributes.stderr b/tests/ui/attributes/unsafe/double-unsafe-attributes.stderr index 950b2636993..0825cf79408 100644 --- a/tests/ui/attributes/unsafe/double-unsafe-attributes.stderr +++ b/tests/ui/attributes/unsafe/double-unsafe-attributes.stderr @@ -1,5 +1,5 @@ error: expected identifier, found keyword `unsafe` - --> $DIR/double-unsafe-attributes.rs:3:10 + --> $DIR/double-unsafe-attributes.rs:1:10 | LL | #[unsafe(unsafe(no_mangle))] | ^^^^^^ expected identifier, found keyword @@ -10,7 +10,7 @@ LL | #[unsafe(r#unsafe(no_mangle))] | ++ error: `r#unsafe` is not an unsafe attribute - --> $DIR/double-unsafe-attributes.rs:3:3 + --> $DIR/double-unsafe-attributes.rs:1:3 | LL | #[unsafe(unsafe(no_mangle))] | ^^^^^^ this is not an unsafe attribute @@ -18,7 +18,7 @@ LL | #[unsafe(unsafe(no_mangle))] = note: extraneous unsafe is not allowed in attributes error: cannot find attribute `r#unsafe` in this scope - --> $DIR/double-unsafe-attributes.rs:3:10 + --> $DIR/double-unsafe-attributes.rs:1:10 | LL | #[unsafe(unsafe(no_mangle))] | ^^^^^^ diff --git a/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.rs b/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.rs index 0181add843b..b561550c198 100644 --- a/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.rs +++ b/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.rs @@ -1,6 +1,5 @@ //@ edition: 2024 //@ compile-flags: -Zunstable-options -#![feature(unsafe_attributes)] #[unsafe(cfg(any()))] //~ ERROR: is not an unsafe attribute fn a() {} diff --git a/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.stderr b/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.stderr index f39074b613d..9fb7f062b91 100644 --- a/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.stderr +++ b/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.stderr @@ -1,5 +1,5 @@ error: `cfg` is not an unsafe attribute - --> $DIR/extraneous-unsafe-attributes.rs:5:3 + --> $DIR/extraneous-unsafe-attributes.rs:4:3 | LL | #[unsafe(cfg(any()))] | ^^^^^^ this is not an unsafe attribute @@ -7,7 +7,7 @@ LL | #[unsafe(cfg(any()))] = note: extraneous unsafe is not allowed in attributes error: `cfg_attr` is not an unsafe attribute - --> $DIR/extraneous-unsafe-attributes.rs:8:3 + --> $DIR/extraneous-unsafe-attributes.rs:7:3 | LL | #[unsafe(cfg_attr(any(), allow(dead_code)))] | ^^^^^^ this is not an unsafe attribute @@ -15,7 +15,7 @@ LL | #[unsafe(cfg_attr(any(), allow(dead_code)))] = note: extraneous unsafe is not allowed in attributes error: `test` is not an unsafe attribute - --> $DIR/extraneous-unsafe-attributes.rs:11:3 + --> $DIR/extraneous-unsafe-attributes.rs:10:3 | LL | #[unsafe(test)] | ^^^^^^ this is not an unsafe attribute @@ -23,7 +23,7 @@ LL | #[unsafe(test)] = note: extraneous unsafe is not allowed in attributes error: `ignore` is not an unsafe attribute - --> $DIR/extraneous-unsafe-attributes.rs:14:3 + --> $DIR/extraneous-unsafe-attributes.rs:13:3 | LL | #[unsafe(ignore = "test")] | ^^^^^^ this is not an unsafe attribute @@ -31,7 +31,7 @@ LL | #[unsafe(ignore = "test")] = note: extraneous unsafe is not allowed in attributes error: `should_panic` is not an unsafe attribute - --> $DIR/extraneous-unsafe-attributes.rs:17:3 + --> $DIR/extraneous-unsafe-attributes.rs:16:3 | LL | #[unsafe(should_panic(expected = "test"))] | ^^^^^^ this is not an unsafe attribute @@ -39,7 +39,7 @@ LL | #[unsafe(should_panic(expected = "test"))] = note: extraneous unsafe is not allowed in attributes error: `macro_use` is not an unsafe attribute - --> $DIR/extraneous-unsafe-attributes.rs:20:3 + --> $DIR/extraneous-unsafe-attributes.rs:19:3 | LL | #[unsafe(macro_use)] | ^^^^^^ this is not an unsafe attribute @@ -47,7 +47,7 @@ LL | #[unsafe(macro_use)] = note: extraneous unsafe is not allowed in attributes error: `macro_export` is not an unsafe attribute - --> $DIR/extraneous-unsafe-attributes.rs:22:7 + --> $DIR/extraneous-unsafe-attributes.rs:21:7 | LL | #[unsafe(macro_export)] | ^^^^^^ this is not an unsafe attribute @@ -55,7 +55,7 @@ LL | #[unsafe(macro_export)] = note: extraneous unsafe is not allowed in attributes error: `used` is not an unsafe attribute - --> $DIR/extraneous-unsafe-attributes.rs:28:3 + --> $DIR/extraneous-unsafe-attributes.rs:27:3 | LL | #[unsafe(used)] | ^^^^^^ this is not an unsafe attribute diff --git a/tests/ui/attributes/unsafe/proc-unsafe-attributes.rs b/tests/ui/attributes/unsafe/proc-unsafe-attributes.rs index f29a5b3252b..eaf8706369a 100644 --- a/tests/ui/attributes/unsafe/proc-unsafe-attributes.rs +++ b/tests/ui/attributes/unsafe/proc-unsafe-attributes.rs @@ -1,5 +1,3 @@ -#![feature(unsafe_attributes)] - #[unsafe(proc_macro)] //~^ ERROR: is not an unsafe attribute //~| ERROR attribute is only usable with crates of the `proc-macro` crate type diff --git a/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr b/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr index 79d34d458bd..9c5751c82e4 100644 --- a/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr +++ b/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr @@ -1,11 +1,11 @@ error[E0452]: malformed lint attribute input - --> $DIR/proc-unsafe-attributes.rs:28:16 + --> $DIR/proc-unsafe-attributes.rs:26:16 | LL | #[unsafe(allow(unsafe(dead_code)))] | ^^^^^^^^^^^^^^^^^ bad attribute argument error[E0452]: malformed lint attribute input - --> $DIR/proc-unsafe-attributes.rs:28:16 + --> $DIR/proc-unsafe-attributes.rs:26:16 | LL | #[unsafe(allow(unsafe(dead_code)))] | ^^^^^^^^^^^^^^^^^ bad attribute argument @@ -13,7 +13,7 @@ LL | #[unsafe(allow(unsafe(dead_code)))] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `proc_macro` is not an unsafe attribute - --> $DIR/proc-unsafe-attributes.rs:3:3 + --> $DIR/proc-unsafe-attributes.rs:1:3 | LL | #[unsafe(proc_macro)] | ^^^^^^ this is not an unsafe attribute @@ -21,7 +21,7 @@ LL | #[unsafe(proc_macro)] = note: extraneous unsafe is not allowed in attributes error: `proc_macro_derive` is not an unsafe attribute - --> $DIR/proc-unsafe-attributes.rs:9:3 + --> $DIR/proc-unsafe-attributes.rs:7:3 | LL | #[unsafe(proc_macro_derive(Foo))] | ^^^^^^ this is not an unsafe attribute @@ -29,7 +29,7 @@ LL | #[unsafe(proc_macro_derive(Foo))] = note: extraneous unsafe is not allowed in attributes error: expected identifier, found keyword `unsafe` - --> $DIR/proc-unsafe-attributes.rs:14:21 + --> $DIR/proc-unsafe-attributes.rs:12:21 | LL | #[proc_macro_derive(unsafe(Foo))] | ^^^^^^ expected identifier, found keyword @@ -40,7 +40,7 @@ LL | #[proc_macro_derive(r#unsafe(Foo))] | ++ error: `proc_macro_attribute` is not an unsafe attribute - --> $DIR/proc-unsafe-attributes.rs:19:3 + --> $DIR/proc-unsafe-attributes.rs:17:3 | LL | #[unsafe(proc_macro_attribute)] | ^^^^^^ this is not an unsafe attribute @@ -48,7 +48,7 @@ LL | #[unsafe(proc_macro_attribute)] = note: extraneous unsafe is not allowed in attributes error: `allow` is not an unsafe attribute - --> $DIR/proc-unsafe-attributes.rs:24:3 + --> $DIR/proc-unsafe-attributes.rs:22:3 | LL | #[unsafe(allow(dead_code))] | ^^^^^^ this is not an unsafe attribute @@ -56,7 +56,7 @@ LL | #[unsafe(allow(dead_code))] = note: extraneous unsafe is not allowed in attributes error: `allow` is not an unsafe attribute - --> $DIR/proc-unsafe-attributes.rs:28:3 + --> $DIR/proc-unsafe-attributes.rs:26:3 | LL | #[unsafe(allow(unsafe(dead_code)))] | ^^^^^^ this is not an unsafe attribute @@ -64,7 +64,7 @@ LL | #[unsafe(allow(unsafe(dead_code)))] = note: extraneous unsafe is not allowed in attributes error: expected identifier, found keyword `unsafe` - --> $DIR/proc-unsafe-attributes.rs:28:16 + --> $DIR/proc-unsafe-attributes.rs:26:16 | LL | #[unsafe(allow(unsafe(dead_code)))] | ^^^^^^ expected identifier, found keyword @@ -75,31 +75,31 @@ LL | #[unsafe(allow(r#unsafe(dead_code)))] | ++ error: the `#[proc_macro]` attribute is only usable with crates of the `proc-macro` crate type - --> $DIR/proc-unsafe-attributes.rs:3:1 + --> $DIR/proc-unsafe-attributes.rs:1:1 | LL | #[unsafe(proc_macro)] | ^^^^^^^^^^^^^^^^^^^^^ error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type - --> $DIR/proc-unsafe-attributes.rs:9:1 + --> $DIR/proc-unsafe-attributes.rs:7:1 | LL | #[unsafe(proc_macro_derive(Foo))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type - --> $DIR/proc-unsafe-attributes.rs:14:1 + --> $DIR/proc-unsafe-attributes.rs:12:1 | LL | #[proc_macro_derive(unsafe(Foo))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the `#[proc_macro_attribute]` attribute is only usable with crates of the `proc-macro` crate type - --> $DIR/proc-unsafe-attributes.rs:19:1 + --> $DIR/proc-unsafe-attributes.rs:17:1 | LL | #[unsafe(proc_macro_attribute)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0452]: malformed lint attribute input - --> $DIR/proc-unsafe-attributes.rs:28:16 + --> $DIR/proc-unsafe-attributes.rs:26:16 | LL | #[unsafe(allow(unsafe(dead_code)))] | ^^^^^^^^^^^^^^^^^ bad attribute argument @@ -107,7 +107,7 @@ LL | #[unsafe(allow(unsafe(dead_code)))] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0452]: malformed lint attribute input - --> $DIR/proc-unsafe-attributes.rs:28:16 + --> $DIR/proc-unsafe-attributes.rs:26:16 | LL | #[unsafe(allow(unsafe(dead_code)))] | ^^^^^^^^^^^^^^^^^ bad attribute argument diff --git a/tests/ui/attributes/unsafe/unsafe-attributes.rs b/tests/ui/attributes/unsafe/unsafe-attributes.rs index 33a412add50..5c57767b3b9 100644 --- a/tests/ui/attributes/unsafe/unsafe-attributes.rs +++ b/tests/ui/attributes/unsafe/unsafe-attributes.rs @@ -1,5 +1,4 @@ //@ build-pass -#![feature(unsafe_attributes)] #[unsafe(no_mangle)] fn a() {} diff --git a/tests/ui/attributes/unsafe/unsafe-safe-attribute.rs b/tests/ui/attributes/unsafe/unsafe-safe-attribute.rs index 67db36afd2e..5af03a2b8d1 100644 --- a/tests/ui/attributes/unsafe/unsafe-safe-attribute.rs +++ b/tests/ui/attributes/unsafe/unsafe-safe-attribute.rs @@ -1,5 +1,3 @@ -#![feature(unsafe_attributes)] - #[unsafe(repr(C))] //~ ERROR: is not an unsafe attribute struct Foo {} diff --git a/tests/ui/attributes/unsafe/unsafe-safe-attribute.stderr b/tests/ui/attributes/unsafe/unsafe-safe-attribute.stderr index 584b0ea797d..55172c91aae 100644 --- a/tests/ui/attributes/unsafe/unsafe-safe-attribute.stderr +++ b/tests/ui/attributes/unsafe/unsafe-safe-attribute.stderr @@ -1,5 +1,5 @@ error: `repr` is not an unsafe attribute - --> $DIR/unsafe-safe-attribute.rs:3:3 + --> $DIR/unsafe-safe-attribute.rs:1:3 | LL | #[unsafe(repr(C))] | ^^^^^^ this is not an unsafe attribute diff --git a/tests/ui/attributes/unsafe/unsafe-safe-attribute_diagnostic.rs b/tests/ui/attributes/unsafe/unsafe-safe-attribute_diagnostic.rs index ff2eb61b405..0f241cc439f 100644 --- a/tests/ui/attributes/unsafe/unsafe-safe-attribute_diagnostic.rs +++ b/tests/ui/attributes/unsafe/unsafe-safe-attribute_diagnostic.rs @@ -1,5 +1,3 @@ -#![feature(unsafe_attributes)] - #[unsafe(diagnostic::on_unimplemented( //~ ERROR: is not an unsafe attribute message = "testing", ))] diff --git a/tests/ui/attributes/unsafe/unsafe-safe-attribute_diagnostic.stderr b/tests/ui/attributes/unsafe/unsafe-safe-attribute_diagnostic.stderr index 26b5e4e37b9..3bc291db5ac 100644 --- a/tests/ui/attributes/unsafe/unsafe-safe-attribute_diagnostic.stderr +++ b/tests/ui/attributes/unsafe/unsafe-safe-attribute_diagnostic.stderr @@ -1,5 +1,5 @@ error: `diagnostic::on_unimplemented` is not an unsafe attribute - --> $DIR/unsafe-safe-attribute_diagnostic.rs:3:3 + --> $DIR/unsafe-safe-attribute_diagnostic.rs:1:3 | LL | #[unsafe(diagnostic::on_unimplemented( | ^^^^^^ this is not an unsafe attribute diff --git a/tests/ui/borrowck/alias-liveness/opaque-type-param.stderr b/tests/ui/borrowck/alias-liveness/opaque-type-param.stderr index 73de5864953..1a32d120057 100644 --- a/tests/ui/borrowck/alias-liveness/opaque-type-param.stderr +++ b/tests/ui/borrowck/alias-liveness/opaque-type-param.stderr @@ -7,6 +7,11 @@ LL | fn foo<'a>(s: &'a str) -> impl Trait + 'static { | hidden type `impl Trait + 'static` captures the lifetime `'a` as defined here LL | bar(s) | ^^^^^^ + | +help: add a `use<...>` bound to explicitly capture `'a` + | +LL | fn foo<'a>(s: &'a str) -> impl Trait + 'static + use<'a> { + | +++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/borrow-raw-address-of-borrowed.rs b/tests/ui/borrowck/borrow-raw-address-of-borrowed.rs index f25fd7f66b3..3ed42d07289 100644 --- a/tests/ui/borrowck/borrow-raw-address-of-borrowed.rs +++ b/tests/ui/borrowck/borrow-raw-address-of-borrowed.rs @@ -1,5 +1,3 @@ -#![feature(raw_ref_op)] - fn address_of_shared() { let mut x = 0; let y = &x; diff --git a/tests/ui/borrowck/borrow-raw-address-of-borrowed.stderr b/tests/ui/borrowck/borrow-raw-address-of-borrowed.stderr index 6f7b7e08070..1a38f8c780e 100644 --- a/tests/ui/borrowck/borrow-raw-address-of-borrowed.stderr +++ b/tests/ui/borrowck/borrow-raw-address-of-borrowed.stderr @@ -1,5 +1,5 @@ error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable - --> $DIR/borrow-raw-address-of-borrowed.rs:7:13 + --> $DIR/borrow-raw-address-of-borrowed.rs:5:13 | LL | let y = &x; | -- immutable borrow occurs here @@ -11,7 +11,7 @@ LL | drop(y); | - immutable borrow later used here error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable - --> $DIR/borrow-raw-address-of-borrowed.rs:16:13 + --> $DIR/borrow-raw-address-of-borrowed.rs:14:13 | LL | let y = &mut x; | ------ mutable borrow occurs here @@ -23,7 +23,7 @@ LL | drop(y); | - mutable borrow later used here error[E0499]: cannot borrow `x` as mutable more than once at a time - --> $DIR/borrow-raw-address-of-borrowed.rs:17:13 + --> $DIR/borrow-raw-address-of-borrowed.rs:15:13 | LL | let y = &mut x; | ------ first mutable borrow occurs here diff --git a/tests/ui/borrowck/borrow-raw-address-of-deref-mutability-ok.rs b/tests/ui/borrowck/borrow-raw-address-of-deref-mutability-ok.rs index 0dfced34c7e..23409795227 100644 --- a/tests/ui/borrowck/borrow-raw-address-of-deref-mutability-ok.rs +++ b/tests/ui/borrowck/borrow-raw-address-of-deref-mutability-ok.rs @@ -1,7 +1,5 @@ //@ check-pass -#![feature(raw_ref_op)] - fn raw_reborrow() { let x = &0; let y = &mut 0; diff --git a/tests/ui/borrowck/borrow-raw-address-of-deref-mutability.rs b/tests/ui/borrowck/borrow-raw-address-of-deref-mutability.rs index 712873528b5..5b3936ef5a3 100644 --- a/tests/ui/borrowck/borrow-raw-address-of-deref-mutability.rs +++ b/tests/ui/borrowck/borrow-raw-address-of-deref-mutability.rs @@ -1,7 +1,5 @@ // Check that `&raw mut` cannot be used to turn a `&T` into a `*mut T`. -#![feature(raw_ref_op)] - fn raw_reborrow() { let x = &0; diff --git a/tests/ui/borrowck/borrow-raw-address-of-deref-mutability.stderr b/tests/ui/borrowck/borrow-raw-address-of-deref-mutability.stderr index cfc86ff0dc1..ac0241cf9a7 100644 --- a/tests/ui/borrowck/borrow-raw-address-of-deref-mutability.stderr +++ b/tests/ui/borrowck/borrow-raw-address-of-deref-mutability.stderr @@ -1,5 +1,5 @@ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference - --> $DIR/borrow-raw-address-of-deref-mutability.rs:8:13 + --> $DIR/borrow-raw-address-of-deref-mutability.rs:6:13 | LL | let q = &raw mut *x; | ^^^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable @@ -10,7 +10,7 @@ LL | let x = &mut 0; | +++ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `*const` pointer - --> $DIR/borrow-raw-address-of-deref-mutability.rs:14:13 + --> $DIR/borrow-raw-address-of-deref-mutability.rs:12:13 | LL | let q = &raw mut *x; | ^^^^^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be borrowed as mutable diff --git a/tests/ui/borrowck/borrow-raw-address-of-mutability-ok.rs b/tests/ui/borrowck/borrow-raw-address-of-mutability-ok.rs index 7b0232a9d45..ed8c5502a75 100644 --- a/tests/ui/borrowck/borrow-raw-address-of-mutability-ok.rs +++ b/tests/ui/borrowck/borrow-raw-address-of-mutability-ok.rs @@ -1,7 +1,5 @@ //@ check-pass -#![feature(raw_ref_op)] - fn mutable_address_of() { let mut x = 0; let y = &raw mut x; diff --git a/tests/ui/borrowck/borrow-raw-address-of-mutability.rs b/tests/ui/borrowck/borrow-raw-address-of-mutability.rs index 320c54b806a..2c5d636d096 100644 --- a/tests/ui/borrowck/borrow-raw-address-of-mutability.rs +++ b/tests/ui/borrowck/borrow-raw-address-of-mutability.rs @@ -1,5 +1,3 @@ -#![feature(raw_ref_op)] - fn mutable_address_of() { let x = 0; let y = &raw mut x; //~ ERROR cannot borrow diff --git a/tests/ui/borrowck/borrow-raw-address-of-mutability.stderr b/tests/ui/borrowck/borrow-raw-address-of-mutability.stderr index 4b5b368287e..f81a8c99376 100644 --- a/tests/ui/borrowck/borrow-raw-address-of-mutability.stderr +++ b/tests/ui/borrowck/borrow-raw-address-of-mutability.stderr @@ -1,5 +1,5 @@ error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable - --> $DIR/borrow-raw-address-of-mutability.rs:5:13 + --> $DIR/borrow-raw-address-of-mutability.rs:3:13 | LL | let y = &raw mut x; | ^^^^^^^^^^ cannot borrow as mutable @@ -10,7 +10,7 @@ LL | let mut x = 0; | +++ error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable - --> $DIR/borrow-raw-address-of-mutability.rs:11:17 + --> $DIR/borrow-raw-address-of-mutability.rs:9:17 | LL | let y = &raw mut x; | ^^^^^^^^^^ cannot borrow as mutable @@ -21,7 +21,7 @@ LL | let mut x = 0; | +++ error[E0596]: cannot borrow `f` as mutable, as it is not declared as mutable - --> $DIR/borrow-raw-address-of-mutability.rs:21:5 + --> $DIR/borrow-raw-address-of-mutability.rs:19:5 | LL | let y = &raw mut x; | - calling `f` requires mutable binding due to mutable borrow of `x` @@ -35,7 +35,7 @@ LL | let mut f = || { | +++ error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure - --> $DIR/borrow-raw-address-of-mutability.rs:29:17 + --> $DIR/borrow-raw-address-of-mutability.rs:27:17 | LL | fn make_fn(f: F) -> F { f } | - change this to accept `FnMut` instead of `Fn` @@ -48,7 +48,7 @@ LL | let y = &raw mut x; | ^^^^^^^^^^ cannot borrow as mutable error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure - --> $DIR/borrow-raw-address-of-mutability.rs:37:17 + --> $DIR/borrow-raw-address-of-mutability.rs:35:17 | LL | fn make_fn(f: F) -> F { f } | - change this to accept `FnMut` instead of `Fn` diff --git a/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr b/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr index 54d8f26f4ea..5f0347bdb4d 100644 --- a/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr +++ b/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr @@ -30,9 +30,9 @@ note: the lifetime `'c` as defined here... LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { | ^^ note: ...does not necessarily outlive the lifetime `'c` as defined here - --> $DIR/regions-bound-missing-bound-in-impl.rs:27:24 + --> $DIR/regions-bound-missing-bound-in-impl.rs:12:24 | -LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { +LL | fn wrong_bound1<'b,'c,'d:'a+'b>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>); | ^^ error[E0308]: method not compatible with trait @@ -44,16 +44,15 @@ LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d = note: expected signature `fn(&'a _, Inv<'c>, Inv<'c>, Inv<'_>)` found signature `fn(&'a _, Inv<'_>, Inv<'c>, Inv<'_>)` note: the lifetime `'c` as defined here... - --> $DIR/regions-bound-missing-bound-in-impl.rs:27:24 + --> $DIR/regions-bound-missing-bound-in-impl.rs:12:24 | -LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { +LL | fn wrong_bound1<'b,'c,'d:'a+'b>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>); | ^^ note: ...does not necessarily outlive the lifetime `'c` as defined here --> $DIR/regions-bound-missing-bound-in-impl.rs:27:24 | LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { | ^^ - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0195]: lifetime parameters or bounds on method `wrong_bound2` do not match the trait declaration --> $DIR/regions-bound-missing-bound-in-impl.rs:42:20 diff --git a/tests/ui/cast/ptr-to-trait-obj-different-args.stderr b/tests/ui/cast/ptr-to-trait-obj-different-args.stderr index b04289ae747..8e60ca42f0a 100644 --- a/tests/ui/cast/ptr-to-trait-obj-different-args.stderr +++ b/tests/ui/cast/ptr-to-trait-obj-different-args.stderr @@ -14,6 +14,7 @@ LL | let y: *const dyn Trait = x as _; | = note: expected trait object `dyn Trait` found trait object `dyn Trait` + = help: `dyn Trait` implements `Trait` so you could box the found value and coerce it to the trait object `Box`, you will have to change the expected type as well error[E0308]: mismatched types --> $DIR/ptr-to-trait-obj-different-args.rs:27:34 @@ -25,6 +26,7 @@ LL | let _: *const dyn Trait = x as _; | = note: expected trait object `dyn Trait` found trait object `dyn Trait` + = help: `dyn Trait` implements `Trait` so you could box the found value and coerce it to the trait object `Box`, you will have to change the expected type as well error[E0308]: mismatched types --> $DIR/ptr-to-trait-obj-different-args.rs:28:34 @@ -37,6 +39,7 @@ LL | let _: *const dyn Trait = t as _; | = note: expected trait object `dyn Trait` found trait object `dyn Trait` + = help: `dyn Trait` implements `Trait` so you could box the found value and coerce it to the trait object `Box`, you will have to change the expected type as well error[E0308]: mismatched types --> $DIR/ptr-to-trait-obj-different-args.rs:36:5 diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr index 520cffc4b02..9b6448fe5a0 100644 --- a/tests/ui/check-cfg/mix.stderr +++ b/tests/ui/check-cfg/mix.stderr @@ -251,7 +251,7 @@ warning: unexpected `cfg` condition value: `zebra` LL | cfg!(target_feature = "zebra"); | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, and `avx512vpopcntdq` and 201 more + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, and `avx512vpopcntdq` and 239 more = note: see for more information about checking conditional configuration warning: 27 warnings emitted diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index d780e04e729..56423d8c307 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -165,7 +165,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_feature = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `backchain`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sha512`, `sign-ext`, `simd128`, `sm3`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vector`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xop`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt` + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `backchain`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `cssc`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `ecv`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `faminmax`, `fcma`, `fdivdu`, `fhm`, `flagm`, `flagm2`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fp8`, `fp8dot2`, `fp8dot4`, `fp8fma`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `hbc`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lse128`, `lse2`, `lsx`, `lut`, `lvz`, `lzcnt`, `m`, `mclass`, `mops`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rcpc3`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sha512`, `sign-ext`, `simd128`, `sm3`, `sm4`, `sme`, `sme-f16f16`, `sme-f64f64`, `sme-f8f16`, `sme-f8f32`, `sme-fa64`, `sme-i16i64`, `sme-lutv2`, `sme2`, `sme2p1`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `ssve-fp8dot2`, `ssve-fp8dot4`, `ssve-fp8fma`, `sve`, `sve-b16b16`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `sve2p1`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `v8.8a`, `v8.9a`, `v9.1a`, `v9.2a`, `v9.3a`, `v9.4a`, `v9.5a`, `v9a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vector`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `wfxt`, `xop`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -201,7 +201,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_os = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` + = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -285,7 +285,7 @@ LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux` | | | help: there is a expected value with a similar name: `"linux"` | - = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` + = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` = note: see for more information about checking conditional configuration warning: 29 warnings emitted diff --git a/tests/ui/closures/add_semicolon_non_block_closure.rs b/tests/ui/closures/add_semicolon_non_block_closure.rs index 3ae91be60c5..62c5e343cd3 100644 --- a/tests/ui/closures/add_semicolon_non_block_closure.rs +++ b/tests/ui/closures/add_semicolon_non_block_closure.rs @@ -8,4 +8,5 @@ fn main() { foo(|| bar()) //~^ ERROR mismatched types [E0308] //~| HELP consider using a semicolon here + //~| HELP try adding a return type } diff --git a/tests/ui/closures/add_semicolon_non_block_closure.stderr b/tests/ui/closures/add_semicolon_non_block_closure.stderr index d095e59c7eb..7883db8f98e 100644 --- a/tests/ui/closures/add_semicolon_non_block_closure.stderr +++ b/tests/ui/closures/add_semicolon_non_block_closure.stderr @@ -1,8 +1,6 @@ error[E0308]: mismatched types --> $DIR/add_semicolon_non_block_closure.rs:8:12 | -LL | fn main() { - | - expected `()` because of default return type LL | foo(|| bar()) | ^^^^^ expected `()`, found `i32` | @@ -10,6 +8,10 @@ help: consider using a semicolon here | LL | foo(|| { bar(); }) | + +++ +help: try adding a return type + | +LL | foo(|| -> i32 bar()) + | ++++++ error: aborting due to 1 previous error diff --git a/tests/ui/closures/coerce-unsafe-to-closure.stderr b/tests/ui/closures/coerce-unsafe-to-closure.stderr index cb718ca160f..2538fc0361c 100644 --- a/tests/ui/closures/coerce-unsafe-to-closure.stderr +++ b/tests/ui/closures/coerce-unsafe-to-closure.stderr @@ -1,4 +1,4 @@ -error[E0277]: expected a `FnOnce(&str)` closure, found `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}` +error[E0277]: expected a `FnOnce(&str)` closure, found `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}` --> $DIR/coerce-unsafe-to-closure.rs:2:44 | LL | let x: Option<&[u8]> = Some("foo").map(std::mem::transmute); @@ -6,7 +6,7 @@ LL | let x: Option<&[u8]> = Some("foo").map(std::mem::transmute); | | | required by a bound introduced by this call | - = help: the trait `FnOnce(&str)` is not implemented for fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}` + = help: the trait `FnOnce(&str)` is not implemented for fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}` = note: unsafe function cannot be called generically without an unsafe block note: required by a bound in `Option::::map` --> $SRC_DIR/core/src/option.rs:LL:COL diff --git a/tests/ui/coercion/cast-higher-ranked-unsafe-fn-ptr.rs b/tests/ui/coercion/cast-higher-ranked-unsafe-fn-ptr.rs new file mode 100644 index 00000000000..19723bee4d4 --- /dev/null +++ b/tests/ui/coercion/cast-higher-ranked-unsafe-fn-ptr.rs @@ -0,0 +1,14 @@ +//@ check-pass + +fn higher_ranked_fndef(ctx: &mut ()) {} + +fn test(higher_ranked_fnptr: fn(&mut ())) { + fn as_unsafe(_: unsafe fn(T)) {} + + // Make sure that we can cast higher-ranked fn items and pointers to + // a non-higher-ranked target. + as_unsafe(higher_ranked_fndef); + as_unsafe(higher_ranked_fnptr); +} + +fn main() {} diff --git a/tests/ui/coercion/coerce-expect-unsized-ascribed.stderr b/tests/ui/coercion/coerce-expect-unsized-ascribed.stderr index 646044ae41a..0c220a13876 100644 --- a/tests/ui/coercion/coerce-expect-unsized-ascribed.stderr +++ b/tests/ui/coercion/coerce-expect-unsized-ascribed.stderr @@ -42,6 +42,7 @@ LL | let _ = type_ascribe!(Box::new( if true { false } else { true }), Box` found struct `Box` + = help: `bool` implements `Debug` so you could box the found value and coerce it to the trait object `Box`, you will have to change the expected type as well error[E0308]: mismatched types --> $DIR/coerce-expect-unsized-ascribed.rs:16:27 @@ -51,6 +52,7 @@ LL | let _ = type_ascribe!(Box::new( match true { true => 'a', false => 'b' | = note: expected struct `Box` found struct `Box` + = help: `char` implements `Debug` so you could box the found value and coerce it to the trait object `Box`, you will have to change the expected type as well error[E0308]: mismatched types --> $DIR/coerce-expect-unsized-ascribed.rs:18:27 @@ -96,6 +98,7 @@ LL | let _ = type_ascribe!(&if true { false } else { true }, &dyn Debug); | = note: expected reference `&dyn Debug` found reference `&bool` + = help: `bool` implements `Debug` so you could box the found value and coerce it to the trait object `Box`, you will have to change the expected type as well error[E0308]: mismatched types --> $DIR/coerce-expect-unsized-ascribed.rs:24:27 @@ -105,6 +108,7 @@ LL | let _ = type_ascribe!(&match true { true => 'a', false => 'b' }, &dyn D | = note: expected reference `&dyn Debug` found reference `&char` + = help: `char` implements `Debug` so you could box the found value and coerce it to the trait object `Box`, you will have to change the expected type as well error[E0308]: mismatched types --> $DIR/coerce-expect-unsized-ascribed.rs:26:27 diff --git a/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.rs b/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.rs index e07fa78463c..cdfeb9c434e 100644 --- a/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.rs +++ b/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.rs @@ -5,7 +5,9 @@ #![feature(with_negative_coherence)] trait Trait {} impl Trait for [(); N] {} +//~^ ERROR: mismatched types impl Trait for [(); N] {} //~^ ERROR: conflicting implementations of trait `Trait` +//~| ERROR: mismatched types fn main() {} diff --git a/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.stderr b/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.stderr index 2087be8e711..d65450845bc 100644 --- a/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.stderr +++ b/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.stderr @@ -1,11 +1,25 @@ error[E0119]: conflicting implementations of trait `Trait` for type `[(); _]` - --> $DIR/generic_const_type_mismatch.rs:8:1 + --> $DIR/generic_const_type_mismatch.rs:9:1 | LL | impl Trait for [(); N] {} | ----------------------------------- first implementation here +LL | LL | impl Trait for [(); N] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[(); _]` -error: aborting due to 1 previous error +error[E0308]: mismatched types + --> $DIR/generic_const_type_mismatch.rs:7:34 + | +LL | impl Trait for [(); N] {} + | ^ expected `usize`, found `u8` -For more information about this error, try `rustc --explain E0119`. +error[E0308]: mismatched types + --> $DIR/generic_const_type_mismatch.rs:9:34 + | +LL | impl Trait for [(); N] {} + | ^ expected `usize`, found `i8` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0119, E0308. +For more information about an error, try `rustc --explain E0119`. diff --git a/tests/crashes/116308.rs b/tests/ui/const-generics/adt_const_params/116308.rs similarity index 81% rename from tests/crashes/116308.rs rename to tests/ui/const-generics/adt_const_params/116308.rs index cb96c80d79b..9ea7022e29c 100644 --- a/tests/crashes/116308.rs +++ b/tests/ui/const-generics/adt_const_params/116308.rs @@ -1,6 +1,8 @@ -//@ known-bug: #116308 +//@ check-pass #![feature(adt_const_params)] +// Regression test for #116308 + pub trait Identity { type Identity; } diff --git a/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.rs b/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.rs index 569e57fa326..401267a0f16 100644 --- a/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.rs +++ b/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.rs @@ -4,11 +4,11 @@ #![allow(incomplete_features, unstable_features)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable() where - Dst: BikeshedIntrinsicFrom, + Dst: TransmuteFrom, //~^ ERROR trait takes at most 2 generic arguments but 3 generic arguments were supplied { } diff --git a/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.stderr b/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.stderr index 5c04c4c9d5b..96716685614 100644 --- a/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.stderr +++ b/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.stderr @@ -1,8 +1,8 @@ error[E0107]: trait takes at most 2 generic arguments but 3 generic arguments were supplied --> $DIR/transmutable-ice-110969.rs:11:14 | -LL | Dst: BikeshedIntrinsicFrom, - | ^^^^^^^^^^^^^^^^^^^^^ -------- help: remove the unnecessary generic argument +LL | Dst: TransmuteFrom, + | ^^^^^^^^^^^^^ -------- help: remove the unnecessary generic argument | | | expected at most 2 generic arguments diff --git a/tests/ui/const-generics/bad-subst-const-kind.rs b/tests/ui/const-generics/bad-subst-const-kind.rs index cc2ff9b8dea..c4e74596e9f 100644 --- a/tests/ui/const-generics/bad-subst-const-kind.rs +++ b/tests/ui/const-generics/bad-subst-const-kind.rs @@ -7,6 +7,7 @@ trait Q { impl Q for [u8; N] { //~^ ERROR: the constant `N` is not of type `usize` + //~| ERROR: mismatched types const ASSOC: usize = 1; } diff --git a/tests/ui/const-generics/bad-subst-const-kind.stderr b/tests/ui/const-generics/bad-subst-const-kind.stderr index 5c8d9c90363..21ec8f0768c 100644 --- a/tests/ui/const-generics/bad-subst-const-kind.stderr +++ b/tests/ui/const-generics/bad-subst-const-kind.stderr @@ -5,7 +5,7 @@ LL | impl Q for [u8; N] { | ^^^^^^^ expected `usize`, found `u64` error: the constant `13` is not of type `u64` - --> $DIR/bad-subst-const-kind.rs:13:24 + --> $DIR/bad-subst-const-kind.rs:14:24 | LL | pub fn test() -> [u8; <[u8; 13] as Q>::ASSOC] { | ^^^^^^^^ expected `u64`, found `usize` @@ -18,5 +18,12 @@ LL | impl Q for [u8; N] { | | | unsatisfied trait bound introduced here -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/bad-subst-const-kind.rs:8:31 + | +LL | impl Q for [u8; N] { + | ^ expected `usize`, found `u64` +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/const-ty-is-normalized.rs b/tests/ui/const-generics/const-ty-is-normalized.rs new file mode 100644 index 00000000000..784145f735e --- /dev/null +++ b/tests/ui/const-generics/const-ty-is-normalized.rs @@ -0,0 +1,25 @@ +//@ compile-flags: -Cdebuginfo=2 --crate-type=lib +//@ build-pass +#![feature(adt_const_params)] + +const N_ISLANDS: usize = 4; + +pub type Matrix = [[usize; N_ISLANDS]; N_ISLANDS]; + +const EMPTY_MATRIX: Matrix = [[0; N_ISLANDS]; N_ISLANDS]; + +const fn to_matrix() -> Matrix { + EMPTY_MATRIX +} + +const BRIDGE_MATRIX: [[usize; N_ISLANDS]; N_ISLANDS] = to_matrix(); + +pub struct Walk { + _p: (), +} + +impl Walk<0, BRIDGE_MATRIX> { + pub const fn new() -> Self { + Self { _p: () } + } +} diff --git a/tests/ui/const-generics/early/trivial-const-arg-macro-nested.rs b/tests/ui/const-generics/early/trivial-const-arg-macro-nested.rs new file mode 100644 index 00000000000..f9730cf8566 --- /dev/null +++ b/tests/ui/const-generics/early/trivial-const-arg-macro-nested.rs @@ -0,0 +1,21 @@ +//@ check-pass + +// This is a regression test for #128016. + +macro_rules! len_inner { + () => { + BAR + }; +} + +macro_rules! len { + () => { + len_inner!() + }; +} + +const BAR: usize = 0; + +fn main() { + let val: [bool; len!()] = []; +} diff --git a/tests/ui/const-generics/early/trivial-const-arg-macro-param.rs b/tests/ui/const-generics/early/trivial-const-arg-macro-param.rs new file mode 100644 index 00000000000..f123e55c028 --- /dev/null +++ b/tests/ui/const-generics/early/trivial-const-arg-macro-param.rs @@ -0,0 +1,13 @@ +//@ check-pass + +macro_rules! len { + ($x:ident) => { + $x + }; +} + +fn bar() { + let val: [bool; len!(N)] = [true; N]; +} + +fn main() {} diff --git a/tests/ui/const-generics/early/trivial-const-arg-macro-res-error.rs b/tests/ui/const-generics/early/trivial-const-arg-macro-res-error.rs new file mode 100644 index 00000000000..f218caac0cf --- /dev/null +++ b/tests/ui/const-generics/early/trivial-const-arg-macro-res-error.rs @@ -0,0 +1,13 @@ +// This is a regression test for #128016. + +macro_rules! len { + () => { + target + //~^ ERROR cannot find value `target` + }; +} + +fn main() { + let val: [str; len!()] = []; + //~^ ERROR the size for values +} diff --git a/tests/ui/const-generics/early/trivial-const-arg-macro-res-error.stderr b/tests/ui/const-generics/early/trivial-const-arg-macro-res-error.stderr new file mode 100644 index 00000000000..ab289e5a6b7 --- /dev/null +++ b/tests/ui/const-generics/early/trivial-const-arg-macro-res-error.stderr @@ -0,0 +1,24 @@ +error[E0425]: cannot find value `target` in this scope + --> $DIR/trivial-const-arg-macro-res-error.rs:5:9 + | +LL | target + | ^^^^^^ not found in this scope +... +LL | let val: [str; len!()] = []; + | ------ in this macro invocation + | + = note: this error originates in the macro `len` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/trivial-const-arg-macro-res-error.rs:11:14 + | +LL | let val: [str; len!()] = []; + | ^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: slice and array elements must have `Sized` type + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0425. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/early/trivial-const-arg-macro.rs b/tests/ui/const-generics/early/trivial-const-arg-macro.rs new file mode 100644 index 00000000000..a19d9abfdcb --- /dev/null +++ b/tests/ui/const-generics/early/trivial-const-arg-macro.rs @@ -0,0 +1,15 @@ +//@ check-pass + +// This is a regression test for #128016. + +macro_rules! len { + () => { + BAR + }; +} + +const BAR: usize = 0; + +fn main() { + let val: [bool; len!()] = []; +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-109141.stderr b/tests/ui/const-generics/generic_const_exprs/issue-109141.stderr index 7a9572d000d..24f3ed7cdf1 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-109141.stderr +++ b/tests/ui/const-generics/generic_const_exprs/issue-109141.stderr @@ -30,10 +30,10 @@ LL | fn a(&self) -> impl Iterator { LL | self.0.iter_mut() | ^^^^^^^^^^^^^^^^^ | -help: to declare that `impl Iterator` captures `'_`, you can add an explicit `'_` lifetime bound +help: add a `use<...>` bound to explicitly capture `'_` | -LL | fn a(&self) -> impl Iterator + '_ { - | ++++ +LL | fn a(&self) -> impl Iterator + use<'_> { + | +++++++++ error: aborting due to 3 previous errors diff --git a/tests/ui/const-generics/generic_const_exprs/type_mismatch.rs b/tests/ui/const-generics/generic_const_exprs/type_mismatch.rs index 8e5e23b2337..a45deabbb0f 100644 --- a/tests/ui/const-generics/generic_const_exprs/type_mismatch.rs +++ b/tests/ui/const-generics/generic_const_exprs/type_mismatch.rs @@ -8,6 +8,7 @@ trait Q { impl Q for [u8; N] {} //~^ ERROR not all trait items implemented //~| ERROR the constant `N` is not of type `usize` +//~| ERROR mismatched types pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {} //~^ ERROR the constant `13` is not of type `u64` diff --git a/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr b/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr index e03580ec007..68870a8d38d 100644 --- a/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr +++ b/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr @@ -14,7 +14,7 @@ LL | impl Q for [u8; N] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `ASSOC` in implementation error: the constant `13` is not of type `u64` - --> $DIR/type_mismatch.rs:12:26 + --> $DIR/type_mismatch.rs:13:26 | LL | pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {} | ^^^^^^^^ expected `u64`, found `usize` @@ -28,14 +28,20 @@ LL | impl Q for [u8; N] {} | unsatisfied trait bound introduced here error[E0308]: mismatched types - --> $DIR/type_mismatch.rs:12:20 + --> $DIR/type_mismatch.rs:13:20 | LL | pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {} | ------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `[u8; <[u8; 13] as Q>::ASSOC]`, found `()` | | | implicitly returns `()` as its body has no tail or `return` expression -error: aborting due to 4 previous errors +error[E0308]: mismatched types + --> $DIR/type_mismatch.rs:8:31 + | +LL | impl Q for [u8; N] {} + | ^ expected `usize`, found `u64` + +error: aborting due to 5 previous errors Some errors have detailed explanations: E0046, E0308. For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs index 8b7ee577569..05a3487ffca 100644 --- a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs +++ b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs @@ -14,8 +14,8 @@ mod v20 { //~^ ERROR cannot find value `v8` in this scope //~| ERROR cannot find function `v6` in this scope pub struct v17 { - //~^ WARN type `v17` should have an upper camel case name - //~| ERROR `[[usize; v4]; v4]` is forbidden as the type of a const generic parameter + //~^ WARN type `v17` should have an upper camel case name + //~| ERROR `[[usize; v4]; v4]` is forbidden as the type of a const generic parameter _p: (), } @@ -25,10 +25,10 @@ mod v20 { } impl v17 { - //~^ ERROR maximum number of nodes exceeded in constant v20::v17::::{constant#0} - //~| ERROR maximum number of nodes exceeded in constant v20::v17::::{constant#0} + //~^ ERROR maximum number of nodes exceeded in constant v20::v17::::{constant#1} + //~| ERROR maximum number of nodes exceeded in constant v20::v17::::{constant#1} pub const fn v21() -> v18 { - //~^ ERROR cannot find type `v18` in this scope + //~^ ERROR cannot find type `v18` in this scope v18 { _p: () } //~^ ERROR cannot find struct, variant or union type `v18` in this scope } diff --git a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr index 15d3c472585..39f022fbee9 100644 --- a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr +++ b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr @@ -72,13 +72,13 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more LL + #![feature(adt_const_params)] | -error: maximum number of nodes exceeded in constant v20::v17::::{constant#0} +error: maximum number of nodes exceeded in constant v20::v17::::{constant#1} --> $DIR/unevaluated-const-ice-119731.rs:27:37 | LL | impl v17 { | ^^ -error: maximum number of nodes exceeded in constant v20::v17::::{constant#0} +error: maximum number of nodes exceeded in constant v20::v17::::{constant#1} --> $DIR/unevaluated-const-ice-119731.rs:27:37 | LL | impl v17 { diff --git a/tests/ui/const-generics/transmute-fail.rs b/tests/ui/const-generics/transmute-fail.rs index 59b77c678e8..a9b297ffb62 100644 --- a/tests/ui/const-generics/transmute-fail.rs +++ b/tests/ui/const-generics/transmute-fail.rs @@ -2,108 +2,108 @@ #![feature(generic_const_exprs)] #![allow(incomplete_features)] -fn foo(v: [[u32;H+1]; W]) -> [[u32; W+1]; H] { - unsafe { - std::mem::transmute(v) - //~^ ERROR cannot transmute - } +fn foo(v: [[u32; H + 1]; W]) -> [[u32; W + 1]; H] { + unsafe { + std::mem::transmute(v) + //~^ ERROR cannot transmute + } } fn bar(v: [[u32; H]; W]) -> [[u32; W]; H] { - //~^ ERROR the constant `W` is not of type `usize` - unsafe { - std::mem::transmute(v) - //~^ ERROR the constant `W` is not of type `usize` - } + //~^ ERROR: the constant `W` is not of type `usize` + //~| ERROR: mismatched types + //~| ERROR: mismatched types + unsafe { + std::mem::transmute(v) + //~^ ERROR: the constant `W` is not of type `usize` + } } fn baz(v: [[u32; H]; W]) -> [u32; W * H * H] { - unsafe { - std::mem::transmute(v) - //~^ ERROR cannot transmute - } + unsafe { + std::mem::transmute(v) + //~^ ERROR cannot transmute + } } fn overflow(v: [[[u32; 8888888]; 9999999]; 777777777]) -> [[[u32; 9999999]; 777777777]; 8888888] { - unsafe { - std::mem::transmute(v) - //~^ ERROR cannot transmute - } + unsafe { + std::mem::transmute(v) + //~^ ERROR cannot transmute + } } -fn transpose(v: [[u32;H]; W]) -> [[u32; W]; H] { - unsafe { - std::mem::transmute(v) - //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types - } +fn transpose(v: [[u32; H]; W]) -> [[u32; W]; H] { + unsafe { + std::mem::transmute(v) + //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types + } } fn ident(v: [[u32; H]; W]) -> [[u32; H]; W] { - unsafe { - std::mem::transmute(v) - } + unsafe { std::mem::transmute(v) } } fn flatten(v: [[u32; H]; W]) -> [u32; W * H] { - unsafe { - std::mem::transmute(v) - //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types - } + unsafe { + std::mem::transmute(v) + //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types + } } -fn coagulate(v: [u32; H*W]) -> [[u32; W];H] { - unsafe { - std::mem::transmute(v) - //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types - } +fn coagulate(v: [u32; H * W]) -> [[u32; W]; H] { + unsafe { + std::mem::transmute(v) + //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types + } } fn flatten_3d( - v: [[[u32; D]; H]; W] + v: [[[u32; D]; H]; W], ) -> [u32; D * W * H] { - unsafe { - std::mem::transmute(v) - //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types - } + unsafe { + std::mem::transmute(v) + //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types + } } fn flatten_somewhat( - v: [[[u32; D]; H]; W] + v: [[[u32; D]; H]; W], ) -> [[u32; D * W]; H] { - unsafe { - std::mem::transmute(v) - //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types - } + unsafe { + std::mem::transmute(v) + //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types + } } fn known_size(v: [u16; L]) -> [u8; L * 2] { - unsafe { - std::mem::transmute(v) - //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types - } + unsafe { + std::mem::transmute(v) + //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types + } } fn condense_bytes(v: [u8; L * 2]) -> [u16; L] { - unsafe { - std::mem::transmute(v) - //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types - } + unsafe { + std::mem::transmute(v) + //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types + } } -fn singleton_each(v: [u8; L]) -> [[u8;1]; L] { - unsafe { - std::mem::transmute(v) - //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types - } +fn singleton_each(v: [u8; L]) -> [[u8; 1]; L] { + unsafe { + std::mem::transmute(v) + //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types + } } fn transpose_with_const( - v: [[u32; 2 * H]; W + W] + v: [[u32; 2 * H]; W + W], ) -> [[u32; W + W]; 2 * H] { - unsafe { - std::mem::transmute(v) - //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types - } + unsafe { + std::mem::transmute(v) + //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types + } } fn main() {} diff --git a/tests/ui/const-generics/transmute-fail.stderr b/tests/ui/const-generics/transmute-fail.stderr index b40fb23c331..124fbee8850 100644 --- a/tests/ui/const-generics/transmute-fail.stderr +++ b/tests/ui/const-generics/transmute-fail.stderr @@ -5,119 +5,132 @@ LL | fn bar(v: [[u32; H]; W]) -> [[u32; W]; H] { | ^^^^^^^^^^^^^ expected `usize`, found `bool` error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:7:5 + --> $DIR/transmute-fail.rs:7:9 | -LL | std::mem::transmute(v) - | ^^^^^^^^^^^^^^^^^^^ +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ | - = note: source type: `[[u32; H+1]; W]` (size can vary because of [u32; H+1]) - = note: target type: `[[u32; W+1]; H]` (size can vary because of [u32; W+1]) + = note: source type: `[[u32; H + 1]; W]` (size can vary because of [u32; H + 1]) + = note: target type: `[[u32; W + 1]; H]` (size can vary because of [u32; W + 1]) error: the constant `W` is not of type `usize` - --> $DIR/transmute-fail.rs:15:5 + --> $DIR/transmute-fail.rs:17:9 | -LL | std::mem::transmute(v) - | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool` +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool` error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:22:5 + --> $DIR/transmute-fail.rs:24:9 | -LL | std::mem::transmute(v) - | ^^^^^^^^^^^^^^^^^^^ +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ | = note: source type: `[[u32; H]; W]` (size can vary because of [u32; H]) = note: target type: `[u32; W * H * H]` (this type does not have a fixed size) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:29:5 + --> $DIR/transmute-fail.rs:31:9 | -LL | std::mem::transmute(v) - | ^^^^^^^^^^^^^^^^^^^ +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ | = note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[u32; 8888888]; 9999999]` are too big for the current architecture) = note: target type: `[[[u32; 9999999]; 777777777]; 8888888]` (values of the type `[[u32; 9999999]; 777777777]` are too big for the current architecture) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:36:5 + --> $DIR/transmute-fail.rs:38:9 | -LL | std::mem::transmute(v) - | ^^^^^^^^^^^^^^^^^^^ +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ | = note: source type: `[[u32; H]; W]` (size can vary because of [u32; H]) = note: target type: `[[u32; W]; H]` (size can vary because of [u32; W]) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:49:5 + --> $DIR/transmute-fail.rs:49:9 | -LL | std::mem::transmute(v) - | ^^^^^^^^^^^^^^^^^^^ +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ | = note: source type: `[[u32; H]; W]` (size can vary because of [u32; H]) = note: target type: `[u32; W * H]` (this type does not have a fixed size) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:56:5 + --> $DIR/transmute-fail.rs:56:9 | -LL | std::mem::transmute(v) - | ^^^^^^^^^^^^^^^^^^^ +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ | - = note: source type: `[u32; H*W]` (this type does not have a fixed size) + = note: source type: `[u32; H * W]` (this type does not have a fixed size) = note: target type: `[[u32; W]; H]` (size can vary because of [u32; W]) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:65:5 + --> $DIR/transmute-fail.rs:65:9 | -LL | std::mem::transmute(v) - | ^^^^^^^^^^^^^^^^^^^ +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ | = note: source type: `[[[u32; D]; H]; W]` (size can vary because of [u32; D]) = note: target type: `[u32; D * W * H]` (this type does not have a fixed size) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:74:5 + --> $DIR/transmute-fail.rs:74:9 | -LL | std::mem::transmute(v) - | ^^^^^^^^^^^^^^^^^^^ +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ | = note: source type: `[[[u32; D]; H]; W]` (size can vary because of [u32; D]) = note: target type: `[[u32; D * W]; H]` (size can vary because of [u32; D * W]) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:81:5 + --> $DIR/transmute-fail.rs:81:9 | -LL | std::mem::transmute(v) - | ^^^^^^^^^^^^^^^^^^^ +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ | = note: source type: `[u16; L]` (this type does not have a fixed size) = note: target type: `[u8; L * 2]` (this type does not have a fixed size) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:88:5 + --> $DIR/transmute-fail.rs:88:9 | -LL | std::mem::transmute(v) - | ^^^^^^^^^^^^^^^^^^^ +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ | = note: source type: `[u8; L * 2]` (this type does not have a fixed size) = note: target type: `[u16; L]` (this type does not have a fixed size) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:95:5 + --> $DIR/transmute-fail.rs:95:9 | -LL | std::mem::transmute(v) - | ^^^^^^^^^^^^^^^^^^^ +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ | = note: source type: `[u8; L]` (this type does not have a fixed size) = note: target type: `[[u8; 1]; L]` (this type does not have a fixed size) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:104:5 + --> $DIR/transmute-fail.rs:104:9 | -LL | std::mem::transmute(v) - | ^^^^^^^^^^^^^^^^^^^ +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ | = note: source type: `[[u32; 2 * H]; W + W]` (size can vary because of [u32; 2 * H]) = note: target type: `[[u32; W + W]; 2 * H]` (size can vary because of [u32; W + W]) -error: aborting due to 14 previous errors +error[E0308]: mismatched types + --> $DIR/transmute-fail.rs:12:53 + | +LL | fn bar(v: [[u32; H]; W]) -> [[u32; W]; H] { + | ^ expected `usize`, found `bool` -For more information about this error, try `rustc --explain E0512`. +error[E0308]: mismatched types + --> $DIR/transmute-fail.rs:12:67 + | +LL | fn bar(v: [[u32; H]; W]) -> [[u32; W]; H] { + | ^ expected `usize`, found `bool` + +error: aborting due to 16 previous errors + +Some errors have detailed explanations: E0308, E0512. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/type_mismatch.rs b/tests/ui/const-generics/type_mismatch.rs index 8187c785cd1..9c7217cd83e 100644 --- a/tests/ui/const-generics/type_mismatch.rs +++ b/tests/ui/const-generics/type_mismatch.rs @@ -1,10 +1,12 @@ fn foo() -> [u8; N] { bar::() //~^ ERROR the constant `N` is not of type `u8` + //~| ERROR: mismatched types } fn bar() -> [u8; N] {} //~^ ERROR the constant `N` is not of type `usize` +//~| ERROR: mismatched types //~| ERROR mismatched types fn main() {} diff --git a/tests/ui/const-generics/type_mismatch.stderr b/tests/ui/const-generics/type_mismatch.stderr index d1bb5c1242f..77e9f5e2b44 100644 --- a/tests/ui/const-generics/type_mismatch.stderr +++ b/tests/ui/const-generics/type_mismatch.stderr @@ -1,5 +1,5 @@ error: the constant `N` is not of type `usize` - --> $DIR/type_mismatch.rs:6:26 + --> $DIR/type_mismatch.rs:7:26 | LL | fn bar() -> [u8; N] {} | ^^^^^^^ expected `usize`, found `u8` @@ -11,19 +11,31 @@ LL | bar::() | ^ expected `u8`, found `usize` | note: required by a const generic parameter in `bar` - --> $DIR/type_mismatch.rs:6:8 + --> $DIR/type_mismatch.rs:7:8 | LL | fn bar() -> [u8; N] {} | ^^^^^^^^^^^ required by this const generic parameter in `bar` error[E0308]: mismatched types - --> $DIR/type_mismatch.rs:6:26 + --> $DIR/type_mismatch.rs:7:26 | LL | fn bar() -> [u8; N] {} | --- ^^^^^^^ expected `[u8; N]`, found `()` | | | implicitly returns `()` as its body has no tail or `return` expression -error: aborting due to 3 previous errors +error[E0308]: mismatched types + --> $DIR/type_mismatch.rs:2:11 + | +LL | bar::() + | ^ expected `u8`, found `usize` + +error[E0308]: mismatched types + --> $DIR/type_mismatch.rs:7:31 + | +LL | fn bar() -> [u8; N] {} + | ^ expected `usize`, found `u8` + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/consts/const-address-of-interior-mut.rs b/tests/ui/consts/const-address-of-interior-mut.rs index 60c7c31daca..930fa0c492f 100644 --- a/tests/ui/consts/const-address-of-interior-mut.rs +++ b/tests/ui/consts/const-address-of-interior-mut.rs @@ -1,5 +1,3 @@ -#![feature(raw_ref_op)] - use std::cell::Cell; const A: () = { let x = Cell::new(2); &raw const x; }; //~ ERROR interior mutability diff --git a/tests/ui/consts/const-address-of-interior-mut.stderr b/tests/ui/consts/const-address-of-interior-mut.stderr index 12c8917d740..203745f0b01 100644 --- a/tests/ui/consts/const-address-of-interior-mut.stderr +++ b/tests/ui/consts/const-address-of-interior-mut.stderr @@ -1,5 +1,5 @@ error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability - --> $DIR/const-address-of-interior-mut.rs:5:39 + --> $DIR/const-address-of-interior-mut.rs:3:39 | LL | const A: () = { let x = Cell::new(2); &raw const x; }; | ^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | const A: () = { let x = Cell::new(2); &raw const x; }; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability - --> $DIR/const-address-of-interior-mut.rs:7:40 + --> $DIR/const-address-of-interior-mut.rs:5:40 | LL | static B: () = { let x = Cell::new(2); &raw const x; }; | ^^^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | static B: () = { let x = Cell::new(2); &raw const x; }; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability - --> $DIR/const-address-of-interior-mut.rs:9:44 + --> $DIR/const-address-of-interior-mut.rs:7:44 | LL | static mut C: () = { let x = Cell::new(2); &raw const x; }; | ^^^^^^^^^^^^ @@ -29,7 +29,7 @@ LL | static mut C: () = { let x = Cell::new(2); &raw const x; }; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability - --> $DIR/const-address-of-interior-mut.rs:13:13 + --> $DIR/const-address-of-interior-mut.rs:11:13 | LL | let y = &raw const x; | ^^^^^^^^^^^^ diff --git a/tests/ui/consts/const-address-of-mut.rs b/tests/ui/consts/const-address-of-mut.rs index 0018bf18e41..c3f37843d3c 100644 --- a/tests/ui/consts/const-address-of-mut.rs +++ b/tests/ui/consts/const-address-of-mut.rs @@ -1,5 +1,3 @@ -#![feature(raw_ref_op)] - const A: () = { let mut x = 2; &raw mut x; }; //~ mutable pointer static B: () = { let mut x = 2; &raw mut x; }; //~ mutable pointer diff --git a/tests/ui/consts/const-address-of-mut.stderr b/tests/ui/consts/const-address-of-mut.stderr index 95a91ff463f..d4243485de1 100644 --- a/tests/ui/consts/const-address-of-mut.stderr +++ b/tests/ui/consts/const-address-of-mut.stderr @@ -1,5 +1,5 @@ error[E0658]: raw mutable pointers are not allowed in constants - --> $DIR/const-address-of-mut.rs:3:32 + --> $DIR/const-address-of-mut.rs:1:32 | LL | const A: () = { let mut x = 2; &raw mut x; }; | ^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | const A: () = { let mut x = 2; &raw mut x; }; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: raw mutable pointers are not allowed in statics - --> $DIR/const-address-of-mut.rs:5:33 + --> $DIR/const-address-of-mut.rs:3:33 | LL | static B: () = { let mut x = 2; &raw mut x; }; | ^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | static B: () = { let mut x = 2; &raw mut x; }; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: raw mutable pointers are not allowed in constant functions - --> $DIR/const-address-of-mut.rs:9:13 + --> $DIR/const-address-of-mut.rs:7:13 | LL | let y = &raw mut x; | ^^^^^^^^^^ diff --git a/tests/ui/consts/const-address-of.rs b/tests/ui/consts/const-address-of.rs index 4eb3c3840ba..39ed430e17e 100644 --- a/tests/ui/consts/const-address-of.rs +++ b/tests/ui/consts/const-address-of.rs @@ -1,7 +1,5 @@ //@ check-pass -#![feature(raw_ref_op)] - const A: *const i32 = &raw const *&2; static B: () = { &raw const *&2; }; static mut C: *const i32 = &raw const *&2; diff --git a/tests/ui/consts/const-eval/const_fn_target_feature.rs b/tests/ui/consts/const-eval/const_fn_target_feature.rs index ee669abb51e..8db41ba11c0 100644 --- a/tests/ui/consts/const-eval/const_fn_target_feature.rs +++ b/tests/ui/consts/const-eval/const_fn_target_feature.rs @@ -1,6 +1,7 @@ //@ only-x86_64 // Set the base cpu explicitly, in case the default has been changed. //@ compile-flags: -C target-cpu=x86-64 -C target-feature=+ssse3 +//@ check-pass #![crate_type = "lib"] @@ -9,7 +10,8 @@ const A: () = unsafe { ssse3_fn() }; // error (avx2 not enabled at compile time) const B: () = unsafe { avx2_fn() }; -//~^ ERROR evaluation of constant value failed +// FIXME: currently we do not detect this UB, since we don't want the result of const-eval +// to depend on `tcx.sess` which can differ between crates in a crate graph. #[target_feature(enable = "ssse3")] const unsafe fn ssse3_fn() {} diff --git a/tests/ui/consts/const-eval/const_fn_target_feature.stderr b/tests/ui/consts/const-eval/const_fn_target_feature.stderr deleted file mode 100644 index d3a00b57ebb..00000000000 --- a/tests/ui/consts/const-eval/const_fn_target_feature.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0080]: evaluation of constant value failed - --> $DIR/const_fn_target_feature.rs:11:24 - | -LL | const B: () = unsafe { avx2_fn() }; - | ^^^^^^^^^ calling a function that requires unavailable target features: avx2 - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/const_fn_target_feature_wasm.rs b/tests/ui/consts/const-eval/const_fn_target_feature_wasm.rs index deed09e4b2a..8ddfe61943c 100644 --- a/tests/ui/consts/const-eval/const_fn_target_feature_wasm.rs +++ b/tests/ui/consts/const-eval/const_fn_target_feature_wasm.rs @@ -7,7 +7,9 @@ #[cfg(target_feature = "simd128")] compile_error!("simd128 target feature should be disabled"); -// Calling functions with `#[target_feature]` is not unsound on WASM, see #84988 +// Calling functions with `#[target_feature]` is not unsound on WASM, see #84988. +// (It can still lead to a runtime error though so we'd be in our right to abort execution, +// just not to declare it UB.) const A: () = simd128_fn(); #[target_feature(enable = "simd128")] diff --git a/tests/ui/consts/const-eval/ub-write-through-immutable.rs b/tests/ui/consts/const-eval/ub-write-through-immutable.rs index 945367f1823..9860b8fde4a 100644 --- a/tests/ui/consts/const-eval/ub-write-through-immutable.rs +++ b/tests/ui/consts/const-eval/ub-write-through-immutable.rs @@ -1,6 +1,5 @@ //! Ensure we catch UB due to writing through a shared reference. #![feature(const_mut_refs, const_refs_to_cell)] -#![deny(writes_through_immutable_pointer)] #![allow(invalid_reference_casting)] use std::mem; @@ -9,15 +8,15 @@ use std::cell::UnsafeCell; const WRITE_AFTER_CAST: () = unsafe { let mut x = 0; let ptr = &x as *const i32 as *mut i32; - *ptr = 0; //~ERROR: writes_through_immutable_pointer - //~^ previously accepted + *ptr = 0; //~ERROR: evaluation of constant value failed + //~| immutable }; const WRITE_AFTER_TRANSMUTE: () = unsafe { let mut x = 0; let ptr: *mut i32 = mem::transmute(&x); - *ptr = 0; //~ERROR: writes_through_immutable_pointer - //~^ previously accepted + *ptr = 0; //~ERROR: evaluation of constant value failed + //~| immutable }; // it's okay when there is interior mutability; diff --git a/tests/ui/consts/const-eval/ub-write-through-immutable.stderr b/tests/ui/consts/const-eval/ub-write-through-immutable.stderr index 27eb2d2c0d1..dbcd35e0b88 100644 --- a/tests/ui/consts/const-eval/ub-write-through-immutable.stderr +++ b/tests/ui/consts/const-eval/ub-write-through-immutable.stderr @@ -1,55 +1,15 @@ -error: writing through a pointer that was derived from a shared (immutable) reference - --> $DIR/ub-write-through-immutable.rs:12:5 +error[E0080]: evaluation of constant value failed + --> $DIR/ub-write-through-immutable.rs:11:5 | LL | *ptr = 0; - | ^^^^^^^^ - | - = 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 #X -note: the lint level is defined here - --> $DIR/ub-write-through-immutable.rs:3:9 - | -LL | #![deny(writes_through_immutable_pointer)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^ writing through a pointer that was derived from a shared (immutable) reference -error: writing through a pointer that was derived from a shared (immutable) reference - --> $DIR/ub-write-through-immutable.rs:19:5 +error[E0080]: evaluation of constant value failed + --> $DIR/ub-write-through-immutable.rs:18:5 | LL | *ptr = 0; - | ^^^^^^^^ - | - = 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 #X + | ^^^^^^^^ writing through a pointer that was derived from a shared (immutable) reference error: aborting due to 2 previous errors -Future incompatibility report: Future breakage diagnostic: -error: writing through a pointer that was derived from a shared (immutable) reference - --> $DIR/ub-write-through-immutable.rs:12:5 - | -LL | *ptr = 0; - | ^^^^^^^^ - | - = 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 #X -note: the lint level is defined here - --> $DIR/ub-write-through-immutable.rs:3:9 - | -LL | #![deny(writes_through_immutable_pointer)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Future breakage diagnostic: -error: writing through a pointer that was derived from a shared (immutable) reference - --> $DIR/ub-write-through-immutable.rs:19:5 - | -LL | *ptr = 0; - | ^^^^^^^^ - | - = 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 #X -note: the lint level is defined here - --> $DIR/ub-write-through-immutable.rs:3:9 - | -LL | #![deny(writes_through_immutable_pointer)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs b/tests/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs index c7078e46fa6..efc0a1c2fba 100644 --- a/tests/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs +++ b/tests/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs @@ -1,9 +1,5 @@ #![feature(const_extern_fn)] -const extern "C" fn unsize(x: &[u8; 3]) -> &[u8] { x } -const unsafe extern "C" fn closure() -> fn() { || {} } -const unsafe extern "C" fn use_float() { 1.0 + 1.0; } -//~^ ERROR floating point arithmetic const extern "C" fn ptr_cast(val: *const u8) { val as usize; } //~^ ERROR pointers cannot be cast to integers diff --git a/tests/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr b/tests/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr index 29fa90d611c..9cdeec159be 100644 --- a/tests/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr +++ b/tests/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr @@ -1,15 +1,5 @@ -error[E0658]: floating point arithmetic is not allowed in constant functions - --> $DIR/const-extern-fn-min-const-fn.rs:5:42 - | -LL | const unsafe extern "C" fn use_float() { 1.0 + 1.0; } - | ^^^^^^^^^ - | - = note: see issue #57241 for more information - = help: add `#![feature(const_fn_floating_point_arithmetic)]` 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: pointers cannot be cast to integers during const eval - --> $DIR/const-extern-fn-min-const-fn.rs:7:48 + --> $DIR/const-extern-fn-min-const-fn.rs:3:48 | LL | const extern "C" fn ptr_cast(val: *const u8) { val as usize; } | ^^^^^^^^^^^^ @@ -17,6 +7,5 @@ LL | const extern "C" fn ptr_cast(val: *const u8) { val as usize; } = note: at compile-time, pointers do not have an integer value = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/const-extern-fn/const-extern-fn.rs b/tests/ui/consts/const-extern-fn/const-extern-fn.rs index 57f5da8d0af..4b164767064 100644 --- a/tests/ui/consts/const-extern-fn/const-extern-fn.rs +++ b/tests/ui/consts/const-extern-fn/const-extern-fn.rs @@ -17,6 +17,19 @@ const unsafe extern "C" fn bar2(val: bool) -> bool { !val } +#[allow(improper_ctypes_definitions)] +const extern "C" fn unsize(x: &[u8; 3]) -> &[u8] { + x +} + +#[allow(improper_ctypes_definitions)] +const unsafe extern "C" fn closure() -> fn() { + || {} +} + +const unsafe extern "C" fn use_float() -> f32 { + 1.0 + 1.0 +} fn main() { let a: [u8; foo1(25) as usize] = [0; 26]; @@ -32,4 +45,8 @@ fn main() { let _foo2_cast: extern "C" fn(u8) -> u8 = foo2; let _bar1_cast: unsafe extern "C" fn(bool) -> bool = bar1; let _bar2_cast: unsafe extern "C" fn(bool) -> bool = bar2; + + unsize(&[0, 1, 2]); + unsafe { closure(); } + unsafe { use_float(); } } diff --git a/tests/ui/consts/const-float-bits-conv.rs b/tests/ui/consts/const-float-bits-conv.rs index ba8db4c23dc..3a526c54dc3 100644 --- a/tests/ui/consts/const-float-bits-conv.rs +++ b/tests/ui/consts/const-float-bits-conv.rs @@ -3,8 +3,9 @@ #![feature(const_float_bits_conv)] #![feature(const_float_classify)] +#![feature(f16)] +#![feature(f128)] #![allow(unused_macro_rules)] - // Don't promote const fn nop(x: T) -> T { x } @@ -23,6 +24,42 @@ macro_rules! const_assert { }; } +fn has_broken_floats() -> bool { + // i586 targets are broken due to . + std::env::var("TARGET").is_ok_and(|v| v.contains("i586")) +} + +#[cfg(target_arch = "x86_64")] +fn f16(){ + const_assert!((1f16).to_bits(), 0x3c00); + const_assert!(u16::from_be_bytes(1f16.to_be_bytes()), 0x3c00); + const_assert!((12.5f16).to_bits(), 0x4a40); + const_assert!(u16::from_le_bytes(12.5f16.to_le_bytes()), 0x4a40); + const_assert!((1337f16).to_bits(), 0x6539); + const_assert!(u16::from_ne_bytes(1337f16.to_ne_bytes()), 0x6539); + const_assert!((-14.25f16).to_bits(), 0xcb20); + const_assert!(f16::from_bits(0x3c00), 1.0); + const_assert!(f16::from_be_bytes(0x3c00u16.to_be_bytes()), 1.0); + const_assert!(f16::from_bits(0x4a40), 12.5); + const_assert!(f16::from_le_bytes(0x4a40u16.to_le_bytes()), 12.5); + const_assert!(f16::from_bits(0x5be0), 252.0); + const_assert!(f16::from_ne_bytes(0x5be0u16.to_ne_bytes()), 252.0); + const_assert!(f16::from_bits(0xcb20), -14.25); + + // Check that NaNs roundtrip their bits regardless of signalingness + // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits + // NOTE: These names assume `f{BITS}::NAN` is a quiet NAN and IEEE754-2008's NaN rules apply! + const QUIET_NAN: u16 = f16::NAN.to_bits() ^ 0x0155; + const SIGNALING_NAN: u16 = f16::NAN.to_bits() ^ 0x02AA; + + const_assert!(f16::from_bits(QUIET_NAN).is_nan()); + const_assert!(f16::from_bits(SIGNALING_NAN).is_nan()); + const_assert!(f16::from_bits(QUIET_NAN).to_bits(), QUIET_NAN); + if !has_broken_floats() { + const_assert!(f16::from_bits(SIGNALING_NAN).to_bits(), SIGNALING_NAN); + } +} + fn f32() { const_assert!((1f32).to_bits(), 0x3f800000); const_assert!(u32::from_be_bytes(1f32.to_be_bytes()), 0x3f800000); @@ -38,6 +75,19 @@ fn f32() { const_assert!(f32::from_bits(0x44a72000), 1337.0); const_assert!(f32::from_ne_bytes(0x44a72000u32.to_ne_bytes()), 1337.0); const_assert!(f32::from_bits(0xc1640000), -14.25); + + // Check that NaNs roundtrip their bits regardless of signalingness + // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits + // NOTE: These names assume `f{BITS}::NAN` is a quiet NAN and IEEE754-2008's NaN rules apply! + const QUIET_NAN: u32 = f32::NAN.to_bits() ^ 0x002A_AAAA; + const SIGNALING_NAN: u32 = f32::NAN.to_bits() ^ 0x0055_5555; + + const_assert!(f32::from_bits(QUIET_NAN).is_nan()); + const_assert!(f32::from_bits(SIGNALING_NAN).is_nan()); + const_assert!(f32::from_bits(QUIET_NAN).to_bits(), QUIET_NAN); + if !has_broken_floats() { + const_assert!(f32::from_bits(SIGNALING_NAN).to_bits(), SIGNALING_NAN); + } } fn f64() { @@ -55,9 +105,58 @@ fn f64() { const_assert!(f64::from_bits(0x4094e40000000000), 1337.0); const_assert!(f64::from_ne_bytes(0x4094e40000000000u64.to_ne_bytes()), 1337.0); const_assert!(f64::from_bits(0xc02c800000000000), -14.25); + + // Check that NaNs roundtrip their bits regardless of signalingness + // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits + // NOTE: These names assume `f{BITS}::NAN` is a quiet NAN and IEEE754-2008's NaN rules apply! + const QUIET_NAN: u64 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555; + const SIGNALING_NAN: u64 = f64::NAN.to_bits() ^ 0x000A_AAAA_AAAA_AAAA; + + const_assert!(f64::from_bits(QUIET_NAN).is_nan()); + const_assert!(f64::from_bits(SIGNALING_NAN).is_nan()); + const_assert!(f64::from_bits(QUIET_NAN).to_bits(), QUIET_NAN); + if !has_broken_floats() { + const_assert!(f64::from_bits(SIGNALING_NAN).to_bits(), SIGNALING_NAN); + } +} + +#[cfg(target_arch = "x86_64")] +fn f128() { + const_assert!((1f128).to_bits(), 0x3fff0000000000000000000000000000); + const_assert!(u128::from_be_bytes(1f128.to_be_bytes()), 0x3fff0000000000000000000000000000); + const_assert!((12.5f128).to_bits(), 0x40029000000000000000000000000000); + const_assert!(u128::from_le_bytes(12.5f128.to_le_bytes()), 0x40029000000000000000000000000000); + const_assert!((1337f128).to_bits(), 0x40094e40000000000000000000000000); + const_assert!(u128::from_ne_bytes(1337f128.to_ne_bytes()), 0x40094e40000000000000000000000000); + const_assert!((-14.25f128).to_bits(), 0xc002c800000000000000000000000000); + const_assert!(f128::from_bits(0x3fff0000000000000000000000000000), 1.0); + const_assert!(f128::from_be_bytes(0x3fff0000000000000000000000000000u128.to_be_bytes()), 1.0); + const_assert!(f128::from_bits(0x40029000000000000000000000000000), 12.5); + const_assert!(f128::from_le_bytes(0x40029000000000000000000000000000u128.to_le_bytes()), 12.5); + const_assert!(f128::from_bits(0x40094e40000000000000000000000000), 1337.0); + assert_eq!(f128::from_ne_bytes(0x40094e40000000000000000000000000u128.to_ne_bytes()), 1337.0); + const_assert!(f128::from_bits(0xc002c800000000000000000000000000), -14.25); + + // Check that NaNs roundtrip their bits regardless of signalingness + // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits + // NOTE: These names assume `f{BITS}::NAN` is a quiet NAN and IEEE754-2008's NaN rules apply! + const QUIET_NAN: u128 = f128::NAN.to_bits() | 0x0000_AAAA_AAAA_AAAA_AAAA_AAAA_AAAA_AAAA; + const SIGNALING_NAN: u128 = f128::NAN.to_bits() ^ 0x0000_5555_5555_5555_5555_5555_5555_5555; + + const_assert!(f128::from_bits(QUIET_NAN).is_nan()); + const_assert!(f128::from_bits(SIGNALING_NAN).is_nan()); + const_assert!(f128::from_bits(QUIET_NAN).to_bits(), QUIET_NAN); + if !has_broken_floats() { + const_assert!(f128::from_bits(SIGNALING_NAN).to_bits(), SIGNALING_NAN); + } } fn main() { + #[cfg(target_arch = "x86_64")] + { + f16(); + f128(); + } f32(); f64(); } diff --git a/tests/ui/consts/const-float-bits-reject-conv.rs b/tests/ui/consts/const-float-bits-reject-conv.rs deleted file mode 100644 index febb272869a..00000000000 --- a/tests/ui/consts/const-float-bits-reject-conv.rs +++ /dev/null @@ -1,68 +0,0 @@ -//@ compile-flags: -Zmir-opt-level=0 -//@ error-pattern: cannot use f32::to_bits on a NaN -#![feature(const_float_bits_conv)] -#![feature(const_float_classify)] - -// Don't promote -const fn nop(x: T) -> T { x } - -macro_rules! const_assert { - ($a:expr) => { - { - const _: () = assert!($a); - assert!(nop($a)); - } - }; - ($a:expr, $b:expr) => { - { - const _: () = assert!($a == $b); - assert_eq!(nop($a), nop($b)); - } - }; -} - -fn f32() { - // Check that NaNs roundtrip their bits regardless of signalingness - // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits - // ...actually, let's just check that these break. :D - const MASKED_NAN1: u32 = f32::NAN.to_bits() ^ 0x002A_AAAA; - //~^ inside - const MASKED_NAN2: u32 = f32::NAN.to_bits() ^ 0x0055_5555; - //~^ inside - - // The rest of the code is dead because the constants already fail to evaluate. - - const_assert!(f32::from_bits(MASKED_NAN1).is_nan()); - const_assert!(f32::from_bits(MASKED_NAN1).is_nan()); - - // LLVM does not guarantee that loads and stores of NaNs preserve their exact bit pattern. - // In practice, this seems to only cause a problem on x86, since the most widely used calling - // convention mandates that floating point values are returned on the x87 FPU stack. See #73328. - // However, during CTFE we still preserve bit patterns (though that is not a guarantee). - const_assert!(f32::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1); - const_assert!(f32::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2); -} - -fn f64() { - // Check that NaNs roundtrip their bits regardless of signalingness - // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits - // ...actually, let's just check that these break. :D - const MASKED_NAN1: u64 = f64::NAN.to_bits() ^ 0x000A_AAAA_AAAA_AAAA; - //~^ inside - const MASKED_NAN2: u64 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555; - //~^ inside - - // The rest of the code is dead because the constants already fail to evaluate. - - const_assert!(f64::from_bits(MASKED_NAN1).is_nan()); - const_assert!(f64::from_bits(MASKED_NAN1).is_nan()); - - // See comment above. - const_assert!(f64::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1); - const_assert!(f64::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2); -} - -fn main() { - f32(); - f64(); -} diff --git a/tests/ui/consts/const-float-bits-reject-conv.stderr b/tests/ui/consts/const-float-bits-reject-conv.stderr deleted file mode 100644 index 1511dab12b0..00000000000 --- a/tests/ui/consts/const-float-bits-reject-conv.stderr +++ /dev/null @@ -1,115 +0,0 @@ -error[E0080]: evaluation of constant value failed - --> $SRC_DIR/core/src/num/f32.rs:LL:COL - | - = note: the evaluated program panicked at 'const-eval error: cannot use f32::to_bits on a NaN', $SRC_DIR/core/src/num/f32.rs:LL:COL - | -note: inside `core::f32::::to_bits::ct_f32_to_u32` - --> $SRC_DIR/core/src/num/f32.rs:LL:COL -note: inside `core::f32::::to_bits` - --> $SRC_DIR/core/src/num/f32.rs:LL:COL -note: inside `f32::MASKED_NAN1` - --> $DIR/const-float-bits-reject-conv.rs:28:30 - | -LL | const MASKED_NAN1: u32 = f32::NAN.to_bits() ^ 0x002A_AAAA; - | ^^^^^^^^^^^^^^^^^^ - = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0080]: evaluation of constant value failed - --> $SRC_DIR/core/src/num/f32.rs:LL:COL - | - = note: the evaluated program panicked at 'const-eval error: cannot use f32::to_bits on a NaN', $SRC_DIR/core/src/num/f32.rs:LL:COL - | -note: inside `core::f32::::to_bits::ct_f32_to_u32` - --> $SRC_DIR/core/src/num/f32.rs:LL:COL -note: inside `core::f32::::to_bits` - --> $SRC_DIR/core/src/num/f32.rs:LL:COL -note: inside `f32::MASKED_NAN2` - --> $DIR/const-float-bits-reject-conv.rs:30:30 - | -LL | const MASKED_NAN2: u32 = f32::NAN.to_bits() ^ 0x0055_5555; - | ^^^^^^^^^^^^^^^^^^ - = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) - -note: erroneous constant encountered - --> $DIR/const-float-bits-reject-conv.rs:35:34 - | -LL | const_assert!(f32::from_bits(MASKED_NAN1).is_nan()); - | ^^^^^^^^^^^ - -note: erroneous constant encountered - --> $DIR/const-float-bits-reject-conv.rs:36:34 - | -LL | const_assert!(f32::from_bits(MASKED_NAN1).is_nan()); - | ^^^^^^^^^^^ - -note: erroneous constant encountered - --> $DIR/const-float-bits-reject-conv.rs:42:34 - | -LL | const_assert!(f32::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1); - | ^^^^^^^^^^^ - -note: erroneous constant encountered - --> $DIR/const-float-bits-reject-conv.rs:43:34 - | -LL | const_assert!(f32::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2); - | ^^^^^^^^^^^ - -error[E0080]: evaluation of constant value failed - --> $SRC_DIR/core/src/num/f64.rs:LL:COL - | - = note: the evaluated program panicked at 'const-eval error: cannot use f64::to_bits on a NaN', $SRC_DIR/core/src/num/f64.rs:LL:COL - | -note: inside `core::f64::::to_bits::ct_f64_to_u64` - --> $SRC_DIR/core/src/num/f64.rs:LL:COL -note: inside `core::f64::::to_bits` - --> $SRC_DIR/core/src/num/f64.rs:LL:COL -note: inside `f64::MASKED_NAN1` - --> $DIR/const-float-bits-reject-conv.rs:50:30 - | -LL | const MASKED_NAN1: u64 = f64::NAN.to_bits() ^ 0x000A_AAAA_AAAA_AAAA; - | ^^^^^^^^^^^^^^^^^^ - = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0080]: evaluation of constant value failed - --> $SRC_DIR/core/src/num/f64.rs:LL:COL - | - = note: the evaluated program panicked at 'const-eval error: cannot use f64::to_bits on a NaN', $SRC_DIR/core/src/num/f64.rs:LL:COL - | -note: inside `core::f64::::to_bits::ct_f64_to_u64` - --> $SRC_DIR/core/src/num/f64.rs:LL:COL -note: inside `core::f64::::to_bits` - --> $SRC_DIR/core/src/num/f64.rs:LL:COL -note: inside `f64::MASKED_NAN2` - --> $DIR/const-float-bits-reject-conv.rs:52:30 - | -LL | const MASKED_NAN2: u64 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555; - | ^^^^^^^^^^^^^^^^^^ - = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) - -note: erroneous constant encountered - --> $DIR/const-float-bits-reject-conv.rs:57:34 - | -LL | const_assert!(f64::from_bits(MASKED_NAN1).is_nan()); - | ^^^^^^^^^^^ - -note: erroneous constant encountered - --> $DIR/const-float-bits-reject-conv.rs:58:34 - | -LL | const_assert!(f64::from_bits(MASKED_NAN1).is_nan()); - | ^^^^^^^^^^^ - -note: erroneous constant encountered - --> $DIR/const-float-bits-reject-conv.rs:61:34 - | -LL | const_assert!(f64::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1); - | ^^^^^^^^^^^ - -note: erroneous constant encountered - --> $DIR/const-float-bits-reject-conv.rs:62:34 - | -LL | const_assert!(f64::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2); - | ^^^^^^^^^^^ - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-mut-refs/const_mut_address_of.rs b/tests/ui/consts/const-mut-refs/const_mut_address_of.rs index 66a4ec50c11..437bdc88722 100644 --- a/tests/ui/consts/const-mut-refs/const_mut_address_of.rs +++ b/tests/ui/consts/const-mut-refs/const_mut_address_of.rs @@ -1,6 +1,5 @@ //@ check-pass #![feature(const_mut_refs)] -#![feature(raw_ref_op)] struct Foo { x: usize diff --git a/tests/ui/consts/const-mut-refs/mut_ref_in_final.rs b/tests/ui/consts/const-mut-refs/mut_ref_in_final.rs index 93197d5bce4..10339ee6798 100644 --- a/tests/ui/consts/const-mut-refs/mut_ref_in_final.rs +++ b/tests/ui/consts/const-mut-refs/mut_ref_in_final.rs @@ -1,5 +1,4 @@ #![feature(const_mut_refs)] -#![feature(raw_ref_op)] const NULL: *mut i32 = std::ptr::null_mut(); const A: *const i32 = &4; diff --git a/tests/ui/consts/const-mut-refs/mut_ref_in_final.stderr b/tests/ui/consts/const-mut-refs/mut_ref_in_final.stderr index 59e6aa4011c..00a8421076b 100644 --- a/tests/ui/consts/const-mut-refs/mut_ref_in_final.stderr +++ b/tests/ui/consts/const-mut-refs/mut_ref_in_final.stderr @@ -1,11 +1,11 @@ error[E0764]: mutable references are not allowed in the final value of constants - --> $DIR/mut_ref_in_final.rs:10:21 + --> $DIR/mut_ref_in_final.rs:9:21 | LL | const B: *mut i32 = &mut 4; | ^^^^^^ error[E0716]: temporary value dropped while borrowed - --> $DIR/mut_ref_in_final.rs:16:40 + --> $DIR/mut_ref_in_final.rs:15:40 | LL | const B3: Option<&mut i32> = Some(&mut 42); | ----------^^- @@ -15,7 +15,7 @@ LL | const B3: Option<&mut i32> = Some(&mut 42); | using this value as a constant requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed - --> $DIR/mut_ref_in_final.rs:19:42 + --> $DIR/mut_ref_in_final.rs:18:42 | LL | const B4: Option<&mut i32> = helper(&mut 42); | ------------^^- @@ -25,7 +25,7 @@ LL | const B4: Option<&mut i32> = helper(&mut 42); | using this value as a constant requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed - --> $DIR/mut_ref_in_final.rs:34:65 + --> $DIR/mut_ref_in_final.rs:33:65 | LL | const FOO: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | -------------------------------^^-- @@ -35,7 +35,7 @@ LL | const FOO: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | using this value as a constant requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed - --> $DIR/mut_ref_in_final.rs:37:67 + --> $DIR/mut_ref_in_final.rs:36:67 | LL | static FOO2: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | -------------------------------^^-- @@ -45,7 +45,7 @@ LL | static FOO2: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | using this value as a static requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed - --> $DIR/mut_ref_in_final.rs:40:71 + --> $DIR/mut_ref_in_final.rs:39:71 | LL | static mut FOO3: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | -------------------------------^^-- @@ -55,25 +55,25 @@ LL | static mut FOO3: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | using this value as a static requires that borrow lasts for `'static` error[E0764]: mutable references are not allowed in the final value of statics - --> $DIR/mut_ref_in_final.rs:53:53 + --> $DIR/mut_ref_in_final.rs:52:53 | LL | static RAW_MUT_CAST_S: SyncPtr = SyncPtr { x : &mut 42 as *mut _ as *const _ }; | ^^^^^^^ error[E0764]: mutable references are not allowed in the final value of statics - --> $DIR/mut_ref_in_final.rs:55:54 + --> $DIR/mut_ref_in_final.rs:54:54 | LL | static RAW_MUT_COERCE_S: SyncPtr = SyncPtr { x: &mut 0 }; | ^^^^^^ error[E0764]: mutable references are not allowed in the final value of constants - --> $DIR/mut_ref_in_final.rs:57:52 + --> $DIR/mut_ref_in_final.rs:56:52 | LL | const RAW_MUT_CAST_C: SyncPtr = SyncPtr { x : &mut 42 as *mut _ as *const _ }; | ^^^^^^^ error[E0764]: mutable references are not allowed in the final value of constants - --> $DIR/mut_ref_in_final.rs:59:53 + --> $DIR/mut_ref_in_final.rs:58:53 | LL | const RAW_MUT_COERCE_C: SyncPtr = SyncPtr { x: &mut 0 }; | ^^^^^^ diff --git a/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs b/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs index c12c22447b5..e208845e747 100644 --- a/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs +++ b/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs @@ -2,7 +2,6 @@ //@ normalize-stderr-test: "( 0x[0-9a-f][0-9a-f] │)? ([0-9a-f][0-9a-f] |__ |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?()?─*╼ )+ *│.*" -> " HEX_DUMP" //@ normalize-stderr-test: "HEX_DUMP\s*\n\s*HEX_DUMP" -> "HEX_DUMP" #![feature(const_mut_refs, const_refs_to_static)] -#![feature(raw_ref_op)] use std::sync::Mutex; diff --git a/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr b/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr index ea9dccf0173..4ea6fa62475 100644 --- a/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr +++ b/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/mut_ref_in_final_dynamic_check.rs:20:1 + --> $DIR/mut_ref_in_final_dynamic_check.rs:19:1 | LL | const MUT: Option<&mut i32> = helper(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered reference to mutable memory in `const` @@ -10,7 +10,7 @@ LL | const MUT: Option<&mut i32> = helper(); } error[E0080]: it is undefined behavior to use this value - --> $DIR/mut_ref_in_final_dynamic_check.rs:27:1 + --> $DIR/mut_ref_in_final_dynamic_check.rs:26:1 | LL | const INT2PTR: Option<&mut i32> = helper_int2ptr(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered a dangling reference (0x2a[noalloc] has no provenance) @@ -21,7 +21,7 @@ LL | const INT2PTR: Option<&mut i32> = helper_int2ptr(); } error[E0080]: it is undefined behavior to use this value - --> $DIR/mut_ref_in_final_dynamic_check.rs:29:1 + --> $DIR/mut_ref_in_final_dynamic_check.rs:28:1 | LL | static INT2PTR_STATIC: Option<&mut i32> = helper_int2ptr(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered a dangling reference (0x2a[noalloc] has no provenance) @@ -32,7 +32,7 @@ LL | static INT2PTR_STATIC: Option<&mut i32> = helper_int2ptr(); } error[E0080]: it is undefined behavior to use this value - --> $DIR/mut_ref_in_final_dynamic_check.rs:36:1 + --> $DIR/mut_ref_in_final_dynamic_check.rs:35:1 | LL | const DANGLING: Option<&mut i32> = helper_dangling(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered a dangling reference (use-after-free) @@ -43,7 +43,7 @@ LL | const DANGLING: Option<&mut i32> = helper_dangling(); } error[E0080]: it is undefined behavior to use this value - --> $DIR/mut_ref_in_final_dynamic_check.rs:37:1 + --> $DIR/mut_ref_in_final_dynamic_check.rs:36:1 | LL | static DANGLING_STATIC: Option<&mut i32> = helper_dangling(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered a dangling reference (use-after-free) diff --git a/tests/ui/consts/const_fn_floating_point_arithmetic.gated.stderr b/tests/ui/consts/const_fn_floating_point_arithmetic.gated.stderr deleted file mode 100644 index e1b8154a287..00000000000 --- a/tests/ui/consts/const_fn_floating_point_arithmetic.gated.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: fatal error triggered by #[rustc_error] - --> $DIR/const_fn_floating_point_arithmetic.rs:20:1 - | -LL | fn main() {} - | ^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/consts/const_fn_floating_point_arithmetic.rs b/tests/ui/consts/const_fn_floating_point_arithmetic.rs deleted file mode 100644 index b0d0bc6b9f4..00000000000 --- a/tests/ui/consts/const_fn_floating_point_arithmetic.rs +++ /dev/null @@ -1,20 +0,0 @@ -// gate-test-const_fn_floating_point_arithmetic - -//@ revisions: stock gated - -#![feature(rustc_attrs)] -#![cfg_attr(gated, feature(const_fn_floating_point_arithmetic))] - -const fn add(f: f32) -> f32 { f + 2.0 } -//[stock]~^ floating point arithmetic -const fn sub(f: f32) -> f32 { 2.0 - f } -//[stock]~^ floating point arithmetic -const fn mul(f: f32, g: f32) -> f32 { f * g } -//[stock]~^ floating point arithmetic -const fn div(f: f32, g: f32) -> f32 { f / g } -//[stock]~^ floating point arithmetic -const fn neg(f: f32) -> f32 { -f } -//[stock]~^ floating point arithmetic - -#[rustc_error] -fn main() {} //[gated]~ fatal error triggered by #[rustc_error] diff --git a/tests/ui/consts/const_fn_floating_point_arithmetic.stock.stderr b/tests/ui/consts/const_fn_floating_point_arithmetic.stock.stderr deleted file mode 100644 index b5b94786ebb..00000000000 --- a/tests/ui/consts/const_fn_floating_point_arithmetic.stock.stderr +++ /dev/null @@ -1,53 +0,0 @@ -error[E0658]: floating point arithmetic is not allowed in constant functions - --> $DIR/const_fn_floating_point_arithmetic.rs:8:31 - | -LL | const fn add(f: f32) -> f32 { f + 2.0 } - | ^^^^^^^ - | - = note: see issue #57241 for more information - = help: add `#![feature(const_fn_floating_point_arithmetic)]` 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]: floating point arithmetic is not allowed in constant functions - --> $DIR/const_fn_floating_point_arithmetic.rs:10:31 - | -LL | const fn sub(f: f32) -> f32 { 2.0 - f } - | ^^^^^^^ - | - = note: see issue #57241 for more information - = help: add `#![feature(const_fn_floating_point_arithmetic)]` 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]: floating point arithmetic is not allowed in constant functions - --> $DIR/const_fn_floating_point_arithmetic.rs:12:39 - | -LL | const fn mul(f: f32, g: f32) -> f32 { f * g } - | ^^^^^ - | - = note: see issue #57241 for more information - = help: add `#![feature(const_fn_floating_point_arithmetic)]` 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]: floating point arithmetic is not allowed in constant functions - --> $DIR/const_fn_floating_point_arithmetic.rs:14:39 - | -LL | const fn div(f: f32, g: f32) -> f32 { f / g } - | ^^^^^ - | - = note: see issue #57241 for more information - = help: add `#![feature(const_fn_floating_point_arithmetic)]` 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]: floating point arithmetic is not allowed in constant functions - --> $DIR/const_fn_floating_point_arithmetic.rs:16:31 - | -LL | const fn neg(f: f32) -> f32 { -f } - | ^^ - | - = note: see issue #57241 for more information - = help: add `#![feature(const_fn_floating_point_arithmetic)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 5 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/const_let_eq_float.rs b/tests/ui/consts/const_let_eq_float.rs index 30d839cdc2a..c9ca6b8b7ea 100644 --- a/tests/ui/consts/const_let_eq_float.rs +++ b/tests/ui/consts/const_let_eq_float.rs @@ -1,7 +1,5 @@ //@ run-pass -#![feature(const_fn_floating_point_arithmetic)] - struct Foo(T); struct Bar { x: T } struct W(f32); diff --git a/tests/ui/consts/issue-36163.stderr b/tests/ui/consts/issue-36163.stderr index 52d3e003f0a..8a7a0981f41 100644 --- a/tests/ui/consts/issue-36163.stderr +++ b/tests/ui/consts/issue-36163.stderr @@ -1,10 +1,10 @@ -error[E0391]: cycle detected when simplifying constant for the type system `Foo::{constant#0}` +error[E0391]: cycle detected when simplifying constant for the type system `Foo::B::{constant#0}` --> $DIR/issue-36163.rs:4:9 | LL | B = A, | ^ | -note: ...which requires const-evaluating + checking `Foo::{constant#0}`... +note: ...which requires const-evaluating + checking `Foo::B::{constant#0}`... --> $DIR/issue-36163.rs:4:9 | LL | B = A, @@ -19,7 +19,7 @@ note: ...which requires const-evaluating + checking `A`... | LL | const A: isize = Foo::B as isize; | ^^^^^^^^^^^^^^^ - = note: ...which again requires simplifying constant for the type system `Foo::{constant#0}`, completing the cycle + = note: ...which again requires simplifying constant for the type system `Foo::B::{constant#0}`, completing the cycle note: cycle used when checking that `Foo` is well-formed --> $DIR/issue-36163.rs:3:1 | diff --git a/tests/ui/consts/min_const_fn/address_of.rs b/tests/ui/consts/min_const_fn/address_of.rs index aa75423ca4d..dc481e17ba3 100644 --- a/tests/ui/consts/min_const_fn/address_of.rs +++ b/tests/ui/consts/min_const_fn/address_of.rs @@ -1,5 +1,3 @@ -#![feature(raw_ref_op)] - const fn mutable_address_of_in_const() { let mut a = 0; let b = &raw mut a; //~ ERROR mutable pointer diff --git a/tests/ui/consts/min_const_fn/address_of.stderr b/tests/ui/consts/min_const_fn/address_of.stderr index 143760c0943..dd6fe6486d4 100644 --- a/tests/ui/consts/min_const_fn/address_of.stderr +++ b/tests/ui/consts/min_const_fn/address_of.stderr @@ -1,5 +1,5 @@ error[E0658]: raw mutable pointers are not allowed in constant functions - --> $DIR/address_of.rs:5:13 + --> $DIR/address_of.rs:3:13 | LL | let b = &raw mut a; | ^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | let b = &raw mut a; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: raw mutable pointers are not allowed in constant functions - --> $DIR/address_of.rs:13:17 + --> $DIR/address_of.rs:11:17 | LL | let b = &raw mut a; | ^^^^^^^^^^ diff --git a/tests/ui/consts/min_const_fn/address_of_const.rs b/tests/ui/consts/min_const_fn/address_of_const.rs index 4280d0745c1..1520622679f 100644 --- a/tests/ui/consts/min_const_fn/address_of_const.rs +++ b/tests/ui/consts/min_const_fn/address_of_const.rs @@ -1,7 +1,5 @@ //@ check-pass -#![feature(raw_ref_op)] - const fn const_address_of_in_const() { let mut a = 0; let b = &raw const a; diff --git a/tests/ui/consts/min_const_fn/allow_const_fn_ptr_run_pass.rs b/tests/ui/consts/min_const_fn/allow_const_fn_ptr_run_pass.rs index a97eeadd92f..fe92787aec1 100644 --- a/tests/ui/consts/min_const_fn/allow_const_fn_ptr_run_pass.rs +++ b/tests/ui/consts/min_const_fn/allow_const_fn_ptr_run_pass.rs @@ -1,6 +1,4 @@ //@ run-pass -#![feature(rustc_allow_const_fn_unstable)] - #![feature(rustc_attrs, staged_api)] #![stable(feature = "rust1", since = "1.0.0")] diff --git a/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs index bb240fb4ad6..480b16b28a5 100644 --- a/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs +++ b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs @@ -3,7 +3,7 @@ we're apparently really bad at it", issue = "none")] -#![feature(const_fn_floating_point_arithmetic, foo, foo2)] +#![feature(const_refs_to_cell, foo, foo2)] #![feature(staged_api)] #[stable(feature = "rust1", since = "1.0.0")] @@ -25,9 +25,15 @@ const fn bar2() -> u32 { foo2() } //~ ERROR not yet stable as a const fn #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "rust1", since = "1.0.0")] -// Const-stable functions cannot rely on unstable const-eval features. -const fn bar3() -> u32 { (5f32 + 6f32) as u32 } -//~^ ERROR const-stable function cannot use `#[feature(const_fn_floating_point_arithmetic)]` +// conformity is required +const fn bar3() -> u32 { + let x = std::cell::Cell::new(0u32); + x.get(); + //~^ ERROR const-stable function cannot use `#[feature(const_refs_to_cell)]` + //~| ERROR cannot call non-const fn + foo() + //~^ ERROR is not yet stable as a const fn +} // check whether this function cannot be called even with the feature gate active #[unstable(feature = "foo2", issue = "none")] diff --git a/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr index 7ec2508ca93..019deda063c 100644 --- a/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr +++ b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr @@ -14,30 +14,47 @@ LL | const fn bar2() -> u32 { foo2() } | = help: const-stable functions can only call other const-stable functions -error: const-stable function cannot use `#[feature(const_fn_floating_point_arithmetic)]` - --> $DIR/min_const_fn_libstd_stability.rs:29:26 +error: const-stable function cannot use `#[feature(const_refs_to_cell)]` + --> $DIR/min_const_fn_libstd_stability.rs:31:5 | -LL | const fn bar3() -> u32 { (5f32 + 6f32) as u32 } - | ^^^^^^^^^^^^^ +LL | x.get(); + | ^ | help: if it is not part of the public API, make this function unstably const | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn bar3() -> u32 { (5f32 + 6f32) as u32 } +LL | const fn bar3() -> u32 { | -help: otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks +help: otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (but requires team approval) | -LL + #[rustc_allow_const_fn_unstable(const_fn_floating_point_arithmetic)] -LL | const fn bar3() -> u32 { (5f32 + 6f32) as u32 } +LL + #[rustc_allow_const_fn_unstable(const_refs_to_cell)] +LL | const fn bar3() -> u32 { | +error[E0015]: cannot call non-const fn `Cell::::get` in constant functions + --> $DIR/min_const_fn_libstd_stability.rs:31:7 + | +LL | x.get(); + | ^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: `foo` is not yet stable as a const fn + --> $DIR/min_const_fn_libstd_stability.rs:34:5 + | +LL | foo() + | ^^^^^ + | + = help: const-stable functions can only call other const-stable functions + error: `foo2_gated` is not yet stable as a const fn - --> $DIR/min_const_fn_libstd_stability.rs:39:32 + --> $DIR/min_const_fn_libstd_stability.rs:45:32 | LL | const fn bar2_gated() -> u32 { foo2_gated() } | ^^^^^^^^^^^^ | = help: const-stable functions can only call other const-stable functions -error: aborting due to 4 previous errors +error: aborting due to 6 previous errors +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs index 03084c8674d..f2a54b8a13d 100644 --- a/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs +++ b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs @@ -3,7 +3,7 @@ we're apparently really bad at it", issue = "none")] -#![feature(const_fn_floating_point_arithmetic, foo, foo2)] +#![feature(const_refs_to_cell, foo, foo2)] #![feature(staged_api)] #[stable(feature = "rust1", since = "1.0.0")] @@ -23,12 +23,6 @@ const unsafe fn foo2() -> u32 { 42 } // can't call non-min_const_fn const unsafe fn bar2() -> u32 { unsafe { foo2() } } //~ ERROR not yet stable as a const fn -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_stable(feature = "rust1", since = "1.0.0")] -// conformity is required -const unsafe fn bar3() -> u32 { (5f32 + 6f32) as u32 } -//~^ ERROR const-stable function cannot use `#[feature(const_fn_floating_point_arithmetic)]` - // check whether this function cannot be called even with the feature gate active #[unstable(feature = "foo2", issue = "none")] const unsafe fn foo2_gated() -> u32 { 42 } diff --git a/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr index 72c1f175d1d..353b117efbc 100644 --- a/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr +++ b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr @@ -14,30 +14,13 @@ LL | const unsafe fn bar2() -> u32 { unsafe { foo2() } } | = help: const-stable functions can only call other const-stable functions -error: const-stable function cannot use `#[feature(const_fn_floating_point_arithmetic)]` - --> $DIR/min_const_unsafe_fn_libstd_stability.rs:29:33 - | -LL | const unsafe fn bar3() -> u32 { (5f32 + 6f32) as u32 } - | ^^^^^^^^^^^^^ - | -help: if it is not part of the public API, make this function unstably const - | -LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const unsafe fn bar3() -> u32 { (5f32 + 6f32) as u32 } - | -help: otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks - | -LL + #[rustc_allow_const_fn_unstable(const_fn_floating_point_arithmetic)] -LL | const unsafe fn bar3() -> u32 { (5f32 + 6f32) as u32 } - | - error: `foo2_gated` is not yet stable as a const fn - --> $DIR/min_const_unsafe_fn_libstd_stability.rs:39:48 + --> $DIR/min_const_unsafe_fn_libstd_stability.rs:33:48 | LL | const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } } | ^^^^^^^^^^^^ | = help: const-stable functions can only call other const-stable functions -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/consts/packed_pattern.stderr b/tests/ui/consts/packed_pattern.stderr index a0b434b2d78..dc26078fb63 100644 --- a/tests/ui/consts/packed_pattern.stderr +++ b/tests/ui/consts/packed_pattern.stderr @@ -2,9 +2,9 @@ warning: unreachable pattern --> $DIR/packed_pattern.rs:16:9 | LL | Foo { field: (5, 6, 7, 8) } => {}, - | --------------------------- matches all the values already + | --------------------------- matches all the relevant values LL | FOO => unreachable!(), - | ^^^ unreachable pattern + | ^^^ no value can reach this | = note: `#[warn(unreachable_patterns)]` on by default diff --git a/tests/ui/consts/packed_pattern2.stderr b/tests/ui/consts/packed_pattern2.stderr index 4785f4d0297..013f61f733c 100644 --- a/tests/ui/consts/packed_pattern2.stderr +++ b/tests/ui/consts/packed_pattern2.stderr @@ -2,9 +2,9 @@ warning: unreachable pattern --> $DIR/packed_pattern2.rs:24:9 | LL | Bar { a: Foo { field: (5, 6) } } => {}, - | -------------------------------- matches all the values already + | -------------------------------- matches all the relevant values LL | FOO => unreachable!(), - | ^^^ unreachable pattern + | ^^^ no value can reach this | = note: `#[warn(unreachable_patterns)]` on by default diff --git a/tests/ui/consts/precise-drop-allow-const-fn-unstable.not_allow.stderr b/tests/ui/consts/precise-drop-allow-const-fn-unstable.not_allow.stderr new file mode 100644 index 00000000000..6038c6d332f --- /dev/null +++ b/tests/ui/consts/precise-drop-allow-const-fn-unstable.not_allow.stderr @@ -0,0 +1,12 @@ +error[E0493]: destructor of `Option` cannot be evaluated at compile-time + --> $DIR/precise-drop-allow-const-fn-unstable.rs:11:24 + | +LL | pub const fn unwrap(this: Option) -> T { + | ^^^^ the destructor for this type cannot be evaluated in constant functions +... +LL | } + | - value is dropped here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/consts/precise-drop-allow-const-fn-unstable.rs b/tests/ui/consts/precise-drop-allow-const-fn-unstable.rs new file mode 100644 index 00000000000..56155e519dc --- /dev/null +++ b/tests/ui/consts/precise-drop-allow-const-fn-unstable.rs @@ -0,0 +1,17 @@ +//@ revisions: allow not_allow +//@ compile-flags: --crate-type=lib -Cinstrument-coverage -Zno-profiler-runtime +//@[allow] check-pass + +#![feature(staged_api, rustc_allow_const_fn_unstable)] +#![stable(feature = "rust_test", since = "1.0.0")] + +#[stable(feature = "rust_test", since = "1.0.0")] +#[rustc_const_stable(feature = "rust_test", since = "1.0.0")] +#[cfg_attr(allow, rustc_allow_const_fn_unstable(const_precise_live_drops))] +pub const fn unwrap(this: Option) -> T { +//[not_allow]~^ ERROR: cannot be evaluated + match this { + Some(x) => x, + None => panic!(), + } +} diff --git a/tests/ui/consts/qualif-indirect-mutation-fail.rs b/tests/ui/consts/qualif-indirect-mutation-fail.rs index 420e32128a4..a99d0633ba1 100644 --- a/tests/ui/consts/qualif-indirect-mutation-fail.rs +++ b/tests/ui/consts/qualif-indirect-mutation-fail.rs @@ -2,7 +2,6 @@ #![feature(const_mut_refs)] #![feature(const_precise_live_drops)] #![feature(const_swap)] -#![feature(raw_ref_op)] // Mutable borrow of a field with drop impl. pub const fn f() { diff --git a/tests/ui/consts/qualif-indirect-mutation-fail.stderr b/tests/ui/consts/qualif-indirect-mutation-fail.stderr index 458dc2071c4..21c872ed13f 100644 --- a/tests/ui/consts/qualif-indirect-mutation-fail.stderr +++ b/tests/ui/consts/qualif-indirect-mutation-fail.stderr @@ -1,5 +1,5 @@ error[E0493]: destructor of `Option` cannot be evaluated at compile-time - --> $DIR/qualif-indirect-mutation-fail.rs:15:9 + --> $DIR/qualif-indirect-mutation-fail.rs:14:9 | LL | let mut x = None; | ^^^^^ the destructor for this type cannot be evaluated in constants @@ -16,13 +16,13 @@ note: inside `std::ptr::drop_in_place:: - shim(Some(String))` note: inside `std::ptr::drop_in_place::> - shim(Some(Option))` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL note: inside `A1` - --> $DIR/qualif-indirect-mutation-fail.rs:21:1 + --> $DIR/qualif-indirect-mutation-fail.rs:20:1 | LL | }; | ^ error[E0493]: destructor of `Option` cannot be evaluated at compile-time - --> $DIR/qualif-indirect-mutation-fail.rs:31:9 + --> $DIR/qualif-indirect-mutation-fail.rs:30:9 | LL | let _z = x; | ^^ the destructor for this type cannot be evaluated in constants @@ -39,49 +39,49 @@ note: inside `std::ptr::drop_in_place:: - shim(Some(String))` note: inside `std::ptr::drop_in_place::> - shim(Some(Option))` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL note: inside `A2` - --> $DIR/qualif-indirect-mutation-fail.rs:32:1 + --> $DIR/qualif-indirect-mutation-fail.rs:31:1 | LL | }; | ^ error[E0493]: destructor of `(u32, Option)` cannot be evaluated at compile-time - --> $DIR/qualif-indirect-mutation-fail.rs:9:9 + --> $DIR/qualif-indirect-mutation-fail.rs:8:9 | LL | let mut a: (u32, Option) = (0, None); | ^^^^^ the destructor for this type cannot be evaluated in constant functions error[E0493]: destructor of `Option` cannot be evaluated at compile-time - --> $DIR/qualif-indirect-mutation-fail.rs:36:9 + --> $DIR/qualif-indirect-mutation-fail.rs:35:9 | LL | let x: Option = None; | ^ the destructor for this type cannot be evaluated in constant functions error[E0493]: destructor of `Option` cannot be evaluated at compile-time - --> $DIR/qualif-indirect-mutation-fail.rs:44:9 + --> $DIR/qualif-indirect-mutation-fail.rs:43:9 | LL | let _y = x; | ^^ the destructor for this type cannot be evaluated in constant functions error[E0493]: destructor of `Option` cannot be evaluated at compile-time - --> $DIR/qualif-indirect-mutation-fail.rs:52:9 + --> $DIR/qualif-indirect-mutation-fail.rs:51:9 | LL | let mut y: Option = None; | ^^^^^ the destructor for this type cannot be evaluated in constant functions error[E0493]: destructor of `Option` cannot be evaluated at compile-time - --> $DIR/qualif-indirect-mutation-fail.rs:49:9 + --> $DIR/qualif-indirect-mutation-fail.rs:48:9 | LL | let mut x: Option = None; | ^^^^^ the destructor for this type cannot be evaluated in constant functions error[E0493]: destructor of `Option` cannot be evaluated at compile-time - --> $DIR/qualif-indirect-mutation-fail.rs:62:9 + --> $DIR/qualif-indirect-mutation-fail.rs:61:9 | LL | let y: Option = None; | ^ the destructor for this type cannot be evaluated in constant functions error[E0493]: destructor of `Option` cannot be evaluated at compile-time - --> $DIR/qualif-indirect-mutation-fail.rs:59:9 + --> $DIR/qualif-indirect-mutation-fail.rs:58:9 | LL | let x: Option = None; | ^ the destructor for this type cannot be evaluated in constant functions diff --git a/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr b/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr index d4fc1717538..ec01225c6bf 100644 --- a/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr +++ b/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr @@ -48,10 +48,10 @@ LL | const STATIC: &str = ""; = note: expected reference `&'static _` found reference `&_` note: the anonymous lifetime as defined here... - --> $DIR/elided-lifetime.rs:15:18 + --> $DIR/elided-lifetime.rs:16:19 | -LL | impl Bar for Foo<'_> { - | ^^ +LL | const STATIC: &str = ""; + | ^ = note: ...does not necessarily outlive the static lifetime error: aborting due to 3 previous errors diff --git a/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr b/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr index 8e4c27875ab..b8e2f412b49 100644 --- a/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr +++ b/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr @@ -30,10 +30,10 @@ LL | const STATIC: &str = ""; = note: expected reference `&_` found reference `&_` note: the anonymous lifetime as defined here... - --> $DIR/static-trait-impl.rs:8:10 + --> $DIR/static-trait-impl.rs:9:19 | -LL | impl Bar<'_> for A { - | ^^ +LL | const STATIC: &str = ""; + | ^ note: ...does not necessarily outlive the anonymous lifetime as defined here --> $DIR/static-trait-impl.rs:8:10 | diff --git a/tests/ui/coroutine/issue-58888.rs b/tests/ui/coroutine/issue-58888.rs index 6266f97ce8c..e4fada0cd43 100644 --- a/tests/ui/coroutine/issue-58888.rs +++ b/tests/ui/coroutine/issue-58888.rs @@ -13,7 +13,8 @@ impl Database { } fn check_connection(&self) -> impl Coroutine + '_ { - #[coroutine] move || { + #[coroutine] + move || { let iter = self.get_connection(); for i in iter { yield i @@ -23,5 +24,5 @@ impl Database { } fn main() { - Database.check_connection(); + let _ = Database.check_connection(); } diff --git a/tests/ui/delegation/correct_body_owner_parent_found_in_diagnostics.rs b/tests/ui/delegation/correct_body_owner_parent_found_in_diagnostics.rs new file mode 100644 index 00000000000..0a7ec5ab5c1 --- /dev/null +++ b/tests/ui/delegation/correct_body_owner_parent_found_in_diagnostics.rs @@ -0,0 +1,34 @@ +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +use std::marker::PhantomData; + +pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>); + +impl<'a> InvariantRef<'a, ()> { + pub const NEW: Self = InvariantRef::new(&()); + //~^ ERROR: no function or associated item named `new` found +} + +trait Trait { + fn foo(&self) -> u8 { 0 } + fn bar(&self) -> u8 { 1 } + fn meh(&self) -> u8 { 2 } +} + +struct Z(u8); + +impl Trait for Z { + reuse ::{foo, bar, meh} { &const { InvariantRef::<'a>::NEW } } + //~^ ERROR: use of undeclared lifetime name `'a` + //~| ERROR: use of undeclared lifetime name `'a` + //~| ERROR: use of undeclared lifetime name `'a` + //~| ERROR: the trait bound `u8: Trait` is not satisfied + //~| ERROR: the trait bound `u8: Trait` is not satisfied + //~| ERROR: the trait bound `u8: Trait` is not satisfied + //~| ERROR: mismatched types + //~| ERROR: mismatched types + //~| ERROR: mismatched types +} + +fn main() { } diff --git a/tests/ui/delegation/correct_body_owner_parent_found_in_diagnostics.stderr b/tests/ui/delegation/correct_body_owner_parent_found_in_diagnostics.stderr new file mode 100644 index 00000000000..2ce3b388073 --- /dev/null +++ b/tests/ui/delegation/correct_body_owner_parent_found_in_diagnostics.stderr @@ -0,0 +1,113 @@ +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/correct_body_owner_parent_found_in_diagnostics.rs:22:68 + | +LL | reuse ::{foo, bar, meh} { &const { InvariantRef::<'a>::NEW } } + | ^^ undeclared lifetime + | +help: consider introducing lifetime `'a` here + | +LL | reuse ::{foo'a, , bar, meh} { &const { InvariantRef::<'a>::NEW } } + | +++ +help: consider introducing lifetime `'a` here + | +LL | impl<'a> Trait for Z { + | ++++ + +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/correct_body_owner_parent_found_in_diagnostics.rs:22:68 + | +LL | reuse ::{foo, bar, meh} { &const { InvariantRef::<'a>::NEW } } + | ^^ undeclared lifetime + | +help: consider introducing lifetime `'a` here + | +LL | reuse ::{foo, bar'a, , meh} { &const { InvariantRef::<'a>::NEW } } + | +++ +help: consider introducing lifetime `'a` here + | +LL | impl<'a> Trait for Z { + | ++++ + +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/correct_body_owner_parent_found_in_diagnostics.rs:22:68 + | +LL | reuse ::{foo, bar, meh} { &const { InvariantRef::<'a>::NEW } } + | ^^ undeclared lifetime + | +help: consider introducing lifetime `'a` here + | +LL | reuse ::{foo, bar, meh'a, } { &const { InvariantRef::<'a>::NEW } } + | +++ +help: consider introducing lifetime `'a` here + | +LL | impl<'a> Trait for Z { + | ++++ + +error[E0599]: no function or associated item named `new` found for struct `InvariantRef` in the current scope + --> $DIR/correct_body_owner_parent_found_in_diagnostics.rs:9:41 + | +LL | pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>); + | -------------------------------------- function or associated item `new` not found for this struct +... +LL | pub const NEW: Self = InvariantRef::new(&()); + | ^^^ function or associated item not found in `InvariantRef<'_, _>` + +error[E0308]: mismatched types + --> $DIR/correct_body_owner_parent_found_in_diagnostics.rs:22:53 + | +LL | reuse ::{foo, bar, meh} { &const { InvariantRef::<'a>::NEW } } + | ^^^^^^^^^^^^^^^^^^^^^^^ expected `u8`, found `InvariantRef<'_, ()>` + | + = note: expected type `u8` + found struct `InvariantRef<'_, ()>` + +error[E0277]: the trait bound `u8: Trait` is not satisfied + --> $DIR/correct_body_owner_parent_found_in_diagnostics.rs:22:12 + | +LL | reuse ::{foo, bar, meh} { &const { InvariantRef::<'a>::NEW } } + | ^^ the trait `Trait` is not implemented for `u8` + | + = help: the trait `Trait` is implemented for `Z` + +error[E0308]: mismatched types + --> $DIR/correct_body_owner_parent_found_in_diagnostics.rs:22:53 + | +LL | reuse ::{foo, bar, meh} { &const { InvariantRef::<'a>::NEW } } + | ^^^^^^^^^^^^^^^^^^^^^^^ expected `u8`, found `InvariantRef<'_, ()>` + | + = note: expected type `u8` + found struct `InvariantRef<'_, ()>` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0277]: the trait bound `u8: Trait` is not satisfied + --> $DIR/correct_body_owner_parent_found_in_diagnostics.rs:22:12 + | +LL | reuse ::{foo, bar, meh} { &const { InvariantRef::<'a>::NEW } } + | ^^ the trait `Trait` is not implemented for `u8` + | + = help: the trait `Trait` is implemented for `Z` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0308]: mismatched types + --> $DIR/correct_body_owner_parent_found_in_diagnostics.rs:22:53 + | +LL | reuse ::{foo, bar, meh} { &const { InvariantRef::<'a>::NEW } } + | ^^^^^^^^^^^^^^^^^^^^^^^ expected `u8`, found `InvariantRef<'_, ()>` + | + = note: expected type `u8` + found struct `InvariantRef<'_, ()>` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0277]: the trait bound `u8: Trait` is not satisfied + --> $DIR/correct_body_owner_parent_found_in_diagnostics.rs:22:12 + | +LL | reuse ::{foo, bar, meh} { &const { InvariantRef::<'a>::NEW } } + | ^^ the trait `Trait` is not implemented for `u8` + | + = help: the trait `Trait` is implemented for `Z` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0261, E0277, E0308, E0599. +For more information about an error, try `rustc --explain E0261`. diff --git a/tests/ui/delegation/inner-attr.stderr b/tests/ui/delegation/inner-attr.stderr index f3b53e331ad..257ab760ffc 100644 --- a/tests/ui/delegation/inner-attr.stderr +++ b/tests/ui/delegation/inner-attr.stderr @@ -8,11 +8,6 @@ LL | fn main() {} | ------------ the inner attribute doesn't annotate this function | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files -help: to annotate the function, change the attribute from inner to outer style - | -LL - reuse a as b { #![rustc_dummy] self } -LL + reuse a as b { #[rustc_dummy] self } - | error: aborting due to 1 previous error diff --git a/tests/ui/deriving/auxiliary/another-proc-macro.rs b/tests/ui/deriving/auxiliary/another-proc-macro.rs new file mode 100644 index 00000000000..a05175c9de9 --- /dev/null +++ b/tests/ui/deriving/auxiliary/another-proc-macro.rs @@ -0,0 +1,45 @@ +//@ force-host +//@ no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(proc_macro_quote)] + +extern crate proc_macro; + +use proc_macro::{quote, TokenStream}; + +#[proc_macro_derive(AnotherMacro, attributes(pointee))] +pub fn derive(_input: TokenStream) -> TokenStream { + quote! { + const _: () = { + const ANOTHER_MACRO_DERIVED: () = (); + }; + } + .into() +} + +#[proc_macro_attribute] +pub fn pointee( + _attr: proc_macro::TokenStream, + _item: proc_macro::TokenStream, +) -> proc_macro::TokenStream { + quote! { + const _: () = { + const POINTEE_MACRO_ATTR_DERIVED: () = (); + }; + } + .into() +} + +#[proc_macro_attribute] +pub fn default( + _attr: proc_macro::TokenStream, + _item: proc_macro::TokenStream, +) -> proc_macro::TokenStream { + quote! { + const _: () = { + const DEFAULT_MACRO_ATTR_DERIVED: () = (); + }; + } + .into() +} diff --git a/tests/ui/deriving/built-in-proc-macro-scope.rs b/tests/ui/deriving/built-in-proc-macro-scope.rs new file mode 100644 index 00000000000..41c95f63b13 --- /dev/null +++ b/tests/ui/deriving/built-in-proc-macro-scope.rs @@ -0,0 +1,25 @@ +//@ check-pass +//@ aux-build: another-proc-macro.rs +//@ compile-flags: -Zunpretty=expanded + +#![feature(derive_smart_pointer)] + +#[macro_use] +extern crate another_proc_macro; + +use another_proc_macro::{pointee, AnotherMacro}; + +#[derive(core::marker::SmartPointer)] +#[repr(transparent)] +pub struct Ptr<'a, #[pointee] T: ?Sized> { + data: &'a mut T, +} + +#[pointee] +fn f() {} + +#[derive(AnotherMacro)] +#[pointee] +struct MyStruct; + +fn main() {} diff --git a/tests/ui/deriving/built-in-proc-macro-scope.stdout b/tests/ui/deriving/built-in-proc-macro-scope.stdout new file mode 100644 index 00000000000..c649b7a9a57 --- /dev/null +++ b/tests/ui/deriving/built-in-proc-macro-scope.stdout @@ -0,0 +1,43 @@ +#![feature(prelude_import)] +#![no_std] +//@ check-pass +//@ aux-build: another-proc-macro.rs +//@ compile-flags: -Zunpretty=expanded + +#![feature(derive_smart_pointer)] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; + +#[macro_use] +extern crate another_proc_macro; + +use another_proc_macro::{pointee, AnotherMacro}; + +#[repr(transparent)] +pub struct Ptr<'a, #[pointee] T: ?Sized> { + data: &'a mut T, +} +#[automatically_derived] +impl<'a, T: ?Sized + ::core::marker::Unsize<__S>, __S: ?Sized> + ::core::ops::DispatchFromDyn> for Ptr<'a, T> { +} +#[automatically_derived] +impl<'a, T: ?Sized + ::core::marker::Unsize<__S>, __S: ?Sized> + ::core::ops::CoerceUnsized> for Ptr<'a, T> { +} + + + +const _: () = + { + const POINTEE_MACRO_ATTR_DERIVED: () = (); + }; +#[pointee] +struct MyStruct; +const _: () = + { + const ANOTHER_MACRO_DERIVED: () = (); + }; +fn main() {} diff --git a/tests/ui/deriving/deriving-smart-pointer-expanded.rs b/tests/ui/deriving/deriving-smart-pointer-expanded.rs index b78258c2529..e48ad3dd4bc 100644 --- a/tests/ui/deriving/deriving-smart-pointer-expanded.rs +++ b/tests/ui/deriving/deriving-smart-pointer-expanded.rs @@ -20,3 +20,9 @@ where data: &'a mut T, x: core::marker::PhantomData, } + +#[derive(SmartPointer)] +#[repr(transparent)] +struct MyPointerWithoutPointee<'a, T: ?Sized> { + ptr: &'a T, +} diff --git a/tests/ui/deriving/deriving-smart-pointer-expanded.stdout b/tests/ui/deriving/deriving-smart-pointer-expanded.stdout index 3c7e7198180..68ef17f2b05 100644 --- a/tests/ui/deriving/deriving-smart-pointer-expanded.stdout +++ b/tests/ui/deriving/deriving-smart-pointer-expanded.stdout @@ -42,3 +42,18 @@ impl<'a, Y, Z: MyTrait + MyTrait<__S>, T: ?Sized + MyTrait + MyTrait<__S>> ::core::ops::CoerceUnsized> for MyPointer2<'a, Y, Z, T, X> where Y: MyTrait, Y: MyTrait<__S> { } + +#[repr(transparent)] +struct MyPointerWithoutPointee<'a, T: ?Sized> { + ptr: &'a T, +} +#[automatically_derived] +impl<'a, T: ?Sized + ::core::marker::Unsize<__S>, __S: ?Sized> + ::core::ops::DispatchFromDyn> for + MyPointerWithoutPointee<'a, T> { +} +#[automatically_derived] +impl<'a, T: ?Sized + ::core::marker::Unsize<__S>, __S: ?Sized> + ::core::ops::CoerceUnsized> for + MyPointerWithoutPointee<'a, T> { +} diff --git a/tests/ui/deriving/deriving-smart-pointer-neg.rs b/tests/ui/deriving/deriving-smart-pointer-neg.rs index 04f52a154fe..f02fb56130f 100644 --- a/tests/ui/deriving/deriving-smart-pointer-neg.rs +++ b/tests/ui/deriving/deriving-smart-pointer-neg.rs @@ -9,13 +9,6 @@ enum NotStruct<'a, T: ?Sized> { Variant(&'a T), } -#[derive(SmartPointer)] -//~^ ERROR: At least one generic type should be designated as `#[pointee]` in order to derive `SmartPointer` traits -#[repr(transparent)] -struct NoPointee<'a, T: ?Sized> { - ptr: &'a T, -} - #[derive(SmartPointer)] //~^ ERROR: `SmartPointer` can only be derived on `struct`s with at least one field #[repr(transparent)] @@ -30,6 +23,23 @@ struct NoFieldUnit<'a, #[pointee] T: ?Sized>(); //~^ ERROR: lifetime parameter `'a` is never used //~| ERROR: type parameter `T` is never used +#[derive(SmartPointer)] +//~^ ERROR: `SmartPointer` can only be derived on `struct`s that are generic over at least one type +#[repr(transparent)] +struct NoGeneric<'a>(&'a u8); + +#[derive(SmartPointer)] +//~^ ERROR: exactly one generic type parameter must be marked as #[pointee] to derive SmartPointer traits +#[repr(transparent)] +struct AmbiguousPointee<'a, T1: ?Sized, T2: ?Sized> { + a: (&'a T1, &'a T2), +} + +#[derive(SmartPointer)] +#[repr(transparent)] +struct TooManyPointees<'a, #[pointee] A: ?Sized, #[pointee] B: ?Sized>((&'a A, &'a B)); +//~^ ERROR: only one type parameter can be marked as `#[pointee]` when deriving SmartPointer traits + #[derive(SmartPointer)] //~^ ERROR: `SmartPointer` can only be derived on `struct`s with `#[repr(transparent)]` struct NotTransparent<'a, #[pointee] T: ?Sized> { diff --git a/tests/ui/deriving/deriving-smart-pointer-neg.stderr b/tests/ui/deriving/deriving-smart-pointer-neg.stderr index 8b0f91d41fb..e7c2afc8b00 100644 --- a/tests/ui/deriving/deriving-smart-pointer-neg.stderr +++ b/tests/ui/deriving/deriving-smart-pointer-neg.stderr @@ -6,7 +6,7 @@ LL | #[derive(SmartPointer)] | = note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info) -error: At least one generic type should be designated as `#[pointee]` in order to derive `SmartPointer` traits +error: `SmartPointer` can only be derived on `struct`s with at least one field --> $DIR/deriving-smart-pointer-neg.rs:12:10 | LL | #[derive(SmartPointer)] @@ -22,7 +22,7 @@ LL | #[derive(SmartPointer)] | = note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info) -error: `SmartPointer` can only be derived on `struct`s with at least one field +error: `SmartPointer` can only be derived on `struct`s that are generic over at least one type --> $DIR/deriving-smart-pointer-neg.rs:26:10 | LL | #[derive(SmartPointer)] @@ -30,8 +30,22 @@ LL | #[derive(SmartPointer)] | = note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info) +error: exactly one generic type parameter must be marked as #[pointee] to derive SmartPointer traits + --> $DIR/deriving-smart-pointer-neg.rs:31:10 + | +LL | #[derive(SmartPointer)] + | ^^^^^^^^^^^^ + | + = note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: only one type parameter can be marked as `#[pointee]` when deriving SmartPointer traits + --> $DIR/deriving-smart-pointer-neg.rs:40:39 + | +LL | struct TooManyPointees<'a, #[pointee] A: ?Sized, #[pointee] B: ?Sized>((&'a A, &'a B)); + | ^ ^ + error: `SmartPointer` can only be derived on `struct`s with `#[repr(transparent)]` - --> $DIR/deriving-smart-pointer-neg.rs:33:10 + --> $DIR/deriving-smart-pointer-neg.rs:43:10 | LL | #[derive(SmartPointer)] | ^^^^^^^^^^^^ @@ -39,13 +53,13 @@ LL | #[derive(SmartPointer)] = note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info) error: `derive(SmartPointer)` requires T to be marked `?Sized` - --> $DIR/deriving-smart-pointer-neg.rs:41:36 + --> $DIR/deriving-smart-pointer-neg.rs:51:36 | LL | struct NoMaybeSized<'a, #[pointee] T> { | ^ error[E0392]: lifetime parameter `'a` is never used - --> $DIR/deriving-smart-pointer-neg.rs:22:16 + --> $DIR/deriving-smart-pointer-neg.rs:15:16 | LL | struct NoField<'a, #[pointee] T: ?Sized> {} | ^^ unused lifetime parameter @@ -53,7 +67,7 @@ LL | struct NoField<'a, #[pointee] T: ?Sized> {} = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` error[E0392]: type parameter `T` is never used - --> $DIR/deriving-smart-pointer-neg.rs:22:31 + --> $DIR/deriving-smart-pointer-neg.rs:15:31 | LL | struct NoField<'a, #[pointee] T: ?Sized> {} | ^ unused type parameter @@ -61,7 +75,7 @@ LL | struct NoField<'a, #[pointee] T: ?Sized> {} = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` error[E0392]: lifetime parameter `'a` is never used - --> $DIR/deriving-smart-pointer-neg.rs:29:20 + --> $DIR/deriving-smart-pointer-neg.rs:22:20 | LL | struct NoFieldUnit<'a, #[pointee] T: ?Sized>(); | ^^ unused lifetime parameter @@ -69,13 +83,13 @@ LL | struct NoFieldUnit<'a, #[pointee] T: ?Sized>(); = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` error[E0392]: type parameter `T` is never used - --> $DIR/deriving-smart-pointer-neg.rs:29:35 + --> $DIR/deriving-smart-pointer-neg.rs:22:35 | LL | struct NoFieldUnit<'a, #[pointee] T: ?Sized>(); | ^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` -error: aborting due to 10 previous errors +error: aborting due to 12 previous errors For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/deriving/proc-macro-attribute-mixing.rs b/tests/ui/deriving/proc-macro-attribute-mixing.rs new file mode 100644 index 00000000000..489665ebeb5 --- /dev/null +++ b/tests/ui/deriving/proc-macro-attribute-mixing.rs @@ -0,0 +1,20 @@ +// This test certify that we can mix attribute macros from Rust and external proc-macros. +// For instance, `#[derive(Default)]` uses `#[default]` and `#[derive(SmartPointer)]` uses +// `#[pointee]`. +// The scoping rule should allow the use of the said two attributes when external proc-macros +// are in scope. + +//@ check-pass +//@ aux-build: another-proc-macro.rs +//@ compile-flags: -Zunpretty=expanded + +#![feature(derive_smart_pointer)] + +#[macro_use] +extern crate another_proc_macro; + +#[pointee] +fn f() {} + +#[default] +fn g() {} diff --git a/tests/ui/deriving/proc-macro-attribute-mixing.stdout b/tests/ui/deriving/proc-macro-attribute-mixing.stdout new file mode 100644 index 00000000000..f314f6efbe2 --- /dev/null +++ b/tests/ui/deriving/proc-macro-attribute-mixing.stdout @@ -0,0 +1,30 @@ +#![feature(prelude_import)] +#![no_std] +// This test certify that we can mix attribute macros from Rust and external proc-macros. +// For instance, `#[derive(Default)]` uses `#[default]` and `#[derive(SmartPointer)]` uses +// `#[pointee]`. +// The scoping rule should allow the use of the said two attributes when external proc-macros +// are in scope. + +//@ check-pass +//@ aux-build: another-proc-macro.rs +//@ compile-flags: -Zunpretty=expanded + +#![feature(derive_smart_pointer)] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; + +#[macro_use] +extern crate another_proc_macro; + + +const _: () = + { + const POINTEE_MACRO_ATTR_DERIVED: () = (); + }; +const _: () = + { + const DEFAULT_MACRO_ATTR_DERIVED: () = (); + }; diff --git a/tests/ui/drop/lint-tail-expr-drop-order-gated.rs b/tests/ui/drop/lint-tail-expr-drop-order-gated.rs new file mode 100644 index 00000000000..b22e72bcfad --- /dev/null +++ b/tests/ui/drop/lint-tail-expr-drop-order-gated.rs @@ -0,0 +1,35 @@ +// This test ensures that `tail_expr_drop_order` does not activate in case Edition 2024 is not used +// or the feature gate `shorter_tail_lifetimes` is disabled. + +//@ revisions: neither no_feature_gate edition_less_than_2024 +//@ check-pass +//@ [neither] edition: 2021 +//@ [no_feature_gate] compile-flags: -Z unstable-options +//@ [no_feature_gate] edition: 2024 +//@ [edition_less_than_2024] edition: 2021 + +#![deny(tail_expr_drop_order)] +#![cfg_attr(edition_less_than_2024, feature(shorter_tail_lifetimes))] + +struct LoudDropper; +impl Drop for LoudDropper { + fn drop(&mut self) { + // This destructor should be considered significant because it is a custom destructor + // and we will assume that the destructor can generate side effects arbitrarily so that + // a change in drop order is visible. + println!("loud drop"); + } +} +impl LoudDropper { + fn get(&self) -> i32 { + 0 + } +} + +fn should_not_lint() -> i32 { + let x = LoudDropper; + x.get() + LoudDropper.get() + // Lint should not action +} + +fn main() {} diff --git a/tests/ui/drop/lint-tail-expr-drop-order.rs b/tests/ui/drop/lint-tail-expr-drop-order.rs new file mode 100644 index 00000000000..0aa0ef02610 --- /dev/null +++ b/tests/ui/drop/lint-tail-expr-drop-order.rs @@ -0,0 +1,71 @@ +//@ compile-flags: -Z unstable-options +//@ edition: 2024 + +// Edition 2024 lint for change in drop order at tail expression +// This lint is to capture potential change in program semantics +// due to implementation of RFC 3606 + +#![deny(tail_expr_drop_order)] +#![feature(shorter_tail_lifetimes)] + +struct LoudDropper; +impl Drop for LoudDropper { + fn drop(&mut self) { + // This destructor should be considered significant because it is a custom destructor + // and we will assume that the destructor can generate side effects arbitrarily so that + // a change in drop order is visible. + println!("loud drop"); + } +} +impl LoudDropper { + fn get(&self) -> i32 { + 0 + } +} + +fn should_lint() -> i32 { + let x = LoudDropper; + // Should lint + x.get() + LoudDropper.get() + //~^ ERROR: these values and local bindings have significant drop implementation that will have a different drop order from that of Edition 2021 + //~| WARN: this changes meaning in Rust 2024 +} + +fn should_lint_closure() -> impl FnOnce() -> i32 { + let x = LoudDropper; + move || x.get() + LoudDropper.get() + //~^ ERROR: these values and local bindings have significant drop implementation that will have a different drop order from that of Edition 2021 + //~| WARN: this changes meaning in Rust 2024 +} + +fn should_not_lint() -> i32 { + let x = LoudDropper; + // Should not lint + x.get() +} + +fn should_not_lint_in_nested_block() -> i32 { + let x = LoudDropper; + // Should not lint because Edition 2021 drops temporaries in blocks earlier already + { LoudDropper.get() } +} + +fn should_not_lint_in_match_arm() -> i32 { + let x = LoudDropper; + // Should not lint because Edition 2021 drops temporaries in blocks earlier already + match &x { + _ => LoudDropper.get(), + } +} + +fn should_lint_in_nested_items() { + fn should_lint_me() -> i32 { + let x = LoudDropper; + // Should lint + x.get() + LoudDropper.get() + //~^ ERROR: these values and local bindings have significant drop implementation that will have a different drop order from that of Edition 2021 + //~| WARN: this changes meaning in Rust 2024 + } +} + +fn main() {} diff --git a/tests/ui/drop/lint-tail-expr-drop-order.stderr b/tests/ui/drop/lint-tail-expr-drop-order.stderr new file mode 100644 index 00000000000..630f0a80f09 --- /dev/null +++ b/tests/ui/drop/lint-tail-expr-drop-order.stderr @@ -0,0 +1,42 @@ +error: these values and local bindings have significant drop implementation that will have a different drop order from that of Edition 2021 + --> $DIR/lint-tail-expr-drop-order.rs:29:15 + | +LL | let x = LoudDropper; + | - these values have significant drop implementation and will observe changes in drop order under Edition 2024 +LL | // Should lint +LL | x.get() + LoudDropper.get() + | ^^^^^^^^^^^ + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #123739 +note: the lint level is defined here + --> $DIR/lint-tail-expr-drop-order.rs:8:9 + | +LL | #![deny(tail_expr_drop_order)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: these values and local bindings have significant drop implementation that will have a different drop order from that of Edition 2021 + --> $DIR/lint-tail-expr-drop-order.rs:36:23 + | +LL | let x = LoudDropper; + | - these values have significant drop implementation and will observe changes in drop order under Edition 2024 +LL | move || x.get() + LoudDropper.get() + | ^^^^^^^^^^^ + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #123739 + +error: these values and local bindings have significant drop implementation that will have a different drop order from that of Edition 2021 + --> $DIR/lint-tail-expr-drop-order.rs:65:19 + | +LL | let x = LoudDropper; + | - these values have significant drop implementation and will observe changes in drop order under Edition 2024 +LL | // Should lint +LL | x.get() + LoudDropper.get() + | ^^^^^^^^^^^ + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #123739 + +error: aborting due to 3 previous errors + diff --git a/tests/ui/dst/dst-rvalue.stderr b/tests/ui/dst/dst-rvalue.stderr index 8d0a82b707d..d8c529617f7 100644 --- a/tests/ui/dst/dst-rvalue.stderr +++ b/tests/ui/dst/dst-rvalue.stderr @@ -9,6 +9,11 @@ LL | let _x: Box = Box::new(*"hello world"); = help: the trait `Sized` is not implemented for `str` note: required by a bound in `Box::::new` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - let _x: Box = Box::new(*"hello world"); +LL + let _x: Box = Box::new("hello world"); + | error[E0277]: the size for values of type `[isize]` cannot be known at compilation time --> $DIR/dst-rvalue.rs:8:37 @@ -21,6 +26,11 @@ LL | let _x: Box<[isize]> = Box::new(*array); = help: the trait `Sized` is not implemented for `[isize]` note: required by a bound in `Box::::new` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - let _x: Box<[isize]> = Box::new(*array); +LL + let _x: Box<[isize]> = Box::new(array); + | error: aborting due to 2 previous errors diff --git a/tests/ui/duplicate-label-E0381-issue-129274.rs b/tests/ui/duplicate-label-E0381-issue-129274.rs new file mode 100644 index 00000000000..b2156e630c8 --- /dev/null +++ b/tests/ui/duplicate-label-E0381-issue-129274.rs @@ -0,0 +1,13 @@ +fn main() { + fn test() { + loop { + let blah: Option; + if true { + blah = Some("".to_string()); + } + if let Some(blah) = blah.as_ref() { //~ ERROR E0381 + } + } + } + println!("{:?}", test()) +} diff --git a/tests/ui/duplicate-label-E0381-issue-129274.stderr b/tests/ui/duplicate-label-E0381-issue-129274.stderr new file mode 100644 index 00000000000..7f8bddb17c5 --- /dev/null +++ b/tests/ui/duplicate-label-E0381-issue-129274.stderr @@ -0,0 +1,15 @@ +error[E0381]: used binding `blah` is possibly-uninitialized + --> $DIR/duplicate-label-E0381-issue-129274.rs:8:33 + | +LL | let blah: Option; + | ---- binding declared here but left uninitialized +LL | if true { +LL | blah = Some("".to_string()); + | ---- binding initialized here in some conditions +LL | } +LL | if let Some(blah) = blah.as_ref() { + | ^^^^ `blah` used here but it is possibly-uninitialized + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.rs b/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.rs new file mode 100644 index 00000000000..19b5edb620f --- /dev/null +++ b/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.rs @@ -0,0 +1,14 @@ +//@ edition: 2021 + +trait Trait {} + +impl dyn Trait { + const CONST: () = (); +} + +fn main() { + match () { + Trait::CONST => {} + //~^ ERROR trait objects must include the `dyn` keyword + } +} diff --git a/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.stderr b/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.stderr new file mode 100644 index 00000000000..4446a89b63b --- /dev/null +++ b/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.stderr @@ -0,0 +1,14 @@ +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-dyn-on-bare-trait-in-pat.rs:11:9 + | +LL | Trait::CONST => {} + | ^^^^^ + | +help: add `dyn` keyword before this trait + | +LL | ::CONST => {} + | ++++ + + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/error-codes/E0001.stderr b/tests/ui/error-codes/E0001.stderr index 40008230ec8..30d0df960f3 100644 --- a/tests/ui/error-codes/E0001.stderr +++ b/tests/ui/error-codes/E0001.stderr @@ -2,9 +2,9 @@ error: unreachable pattern --> $DIR/E0001.rs:8:9 | LL | _ => {/* ... */} - | ^ unreachable pattern + | ^ no value can reach this | -note: these patterns collectively make the last one unreachable +note: multiple earlier patterns match some of the same values --> $DIR/E0001.rs:8:9 | LL | Some(_) => {/* ... */} diff --git a/tests/ui/error-codes/E0208.rs b/tests/ui/error-codes/E0208.rs index 74c138af483..2713ba6ed6c 100644 --- a/tests/ui/error-codes/E0208.rs +++ b/tests/ui/error-codes/E0208.rs @@ -1,7 +1,7 @@ #![feature(rustc_attrs)] #[rustc_variance] -struct Foo<'a, T> { //~ ERROR [+, o] +struct Foo<'a, T> { //~ ERROR ['a: +, T: o] t: &'a mut T, } diff --git a/tests/ui/error-codes/E0208.stderr b/tests/ui/error-codes/E0208.stderr index 77b6ceae4dc..a39e93afab3 100644 --- a/tests/ui/error-codes/E0208.stderr +++ b/tests/ui/error-codes/E0208.stderr @@ -1,4 +1,4 @@ -error: [+, o] +error: ['a: +, T: o] --> $DIR/E0208.rs:4:1 | LL | struct Foo<'a, T> { diff --git a/tests/ui/extern/extern-C-non-FFI-safe-arg-ice-52334.stderr b/tests/ui/extern/extern-C-non-FFI-safe-arg-ice-52334.stderr index 83492988479..044c1ae2dd4 100644 --- a/tests/ui/extern/extern-C-non-FFI-safe-arg-ice-52334.stderr +++ b/tests/ui/extern/extern-C-non-FFI-safe-arg-ice-52334.stderr @@ -1,21 +1,21 @@ -warning: `extern` fn uses type `[i8 or u8 (arch dependant)]`, which is not FFI-safe +warning: `extern` fn uses type `CStr`, which is not FFI-safe --> $DIR/extern-C-non-FFI-safe-arg-ice-52334.rs:7:12 | LL | type Foo = extern "C" fn(::std::ffi::CStr); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | - = help: consider using a raw pointer instead - = note: slices have no C equivalent + = help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + = note: `CStr`/`CString` do not have a guaranteed layout = note: `#[warn(improper_ctypes_definitions)]` on by default -warning: `extern` block uses type `[i8 or u8 (arch dependant)]`, which is not FFI-safe +warning: `extern` block uses type `CStr`, which is not FFI-safe --> $DIR/extern-C-non-FFI-safe-arg-ice-52334.rs:10:18 | LL | fn meh(blah: Foo); | ^^^ not FFI-safe | - = help: consider using a raw pointer instead - = note: slices have no C equivalent + = help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + = note: `CStr`/`CString` do not have a guaranteed layout = note: `#[warn(improper_ctypes)]` on by default warning: 2 warnings emitted diff --git a/tests/ui/extern/extern-main-issue-86110.stderr b/tests/ui/extern/extern-main-issue-86110.stderr index 8a3262fbcc7..d69f4e61768 100644 --- a/tests/ui/extern/extern-main-issue-86110.stderr +++ b/tests/ui/extern/extern-main-issue-86110.stderr @@ -2,7 +2,7 @@ error: the `main` function cannot be declared in an `extern` block --> $DIR/extern-main-issue-86110.rs:4:5 | LL | fn main(); - | ^^^^^^^^^ + | ^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/feature-gates/feature-gate-asm_const.rs b/tests/ui/feature-gates/feature-gate-asm_const.rs deleted file mode 100644 index 42d5ba69222..00000000000 --- a/tests/ui/feature-gates/feature-gate-asm_const.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ only-x86_64 - -use std::arch::asm; - -unsafe fn foo() { - asm!("mov eax, {}", const N + 1); - //~^ ERROR const operands for inline assembly are unstable -} - -fn main() { - unsafe { - foo::<0>(); - asm!("mov eax, {}", const 123); - //~^ ERROR const operands for inline assembly are unstable - } -} diff --git a/tests/ui/feature-gates/feature-gate-asm_const.stderr b/tests/ui/feature-gates/feature-gate-asm_const.stderr deleted file mode 100644 index 4f83fee6759..00000000000 --- a/tests/ui/feature-gates/feature-gate-asm_const.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0658]: const operands for inline assembly are unstable - --> $DIR/feature-gate-asm_const.rs:6:25 - | -LL | asm!("mov eax, {}", const N + 1); - | ^^^^^^^^^^^ - | - = note: see issue #93332 for more information - = help: add `#![feature(asm_const)]` 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]: const operands for inline assembly are unstable - --> $DIR/feature-gate-asm_const.rs:13:29 - | -LL | asm!("mov eax, {}", const 123); - | ^^^^^^^^^ - | - = note: see issue #93332 for more information - = help: add `#![feature(asm_const)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-const-arg-path.rs b/tests/ui/feature-gates/feature-gate-const-arg-path.rs new file mode 100644 index 00000000000..0938c5733a2 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-const-arg-path.rs @@ -0,0 +1,5 @@ +//@ check-pass + +// this doesn't really have any user facing impact.... + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-derive-smart-pointer.rs b/tests/ui/feature-gates/feature-gate-derive-smart-pointer.rs index 3257a9ca624..7b4764ee768 100644 --- a/tests/ui/feature-gates/feature-gate-derive-smart-pointer.rs +++ b/tests/ui/feature-gates/feature-gate-derive-smart-pointer.rs @@ -3,7 +3,6 @@ use std::marker::SmartPointer; //~ ERROR use of unstable library feature 'derive #[derive(SmartPointer)] //~ ERROR use of unstable library feature 'derive_smart_pointer' #[repr(transparent)] struct MyPointer<'a, #[pointee] T: ?Sized> { - //~^ ERROR the `#[pointee]` attribute is an experimental feature ptr: &'a T, } diff --git a/tests/ui/feature-gates/feature-gate-derive-smart-pointer.stderr b/tests/ui/feature-gates/feature-gate-derive-smart-pointer.stderr index 19501939dc5..ea4d1271b7c 100644 --- a/tests/ui/feature-gates/feature-gate-derive-smart-pointer.stderr +++ b/tests/ui/feature-gates/feature-gate-derive-smart-pointer.stderr @@ -8,16 +8,6 @@ LL | #[derive(SmartPointer)] = help: add `#![feature(derive_smart_pointer)]` 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]: the `#[pointee]` attribute is an experimental feature - --> $DIR/feature-gate-derive-smart-pointer.rs:5:22 - | -LL | struct MyPointer<'a, #[pointee] T: ?Sized> { - | ^^^^^^^^^^ - | - = note: see issue #123430 for more information - = help: add `#![feature(derive_smart_pointer)]` 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]: use of unstable library feature 'derive_smart_pointer' --> $DIR/feature-gate-derive-smart-pointer.rs:1:5 | @@ -28,6 +18,6 @@ LL | use std::marker::SmartPointer; = help: add `#![feature(derive_smart_pointer)]` 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 +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-lifetime-capture-rules-2024.stderr b/tests/ui/feature-gates/feature-gate-lifetime-capture-rules-2024.stderr index 173e3dc02cc..d0b18df6a5e 100644 --- a/tests/ui/feature-gates/feature-gate-lifetime-capture-rules-2024.stderr +++ b/tests/ui/feature-gates/feature-gate-lifetime-capture-rules-2024.stderr @@ -8,10 +8,10 @@ LL | fn foo(x: &Vec) -> impl Sized { LL | x | ^ | -help: to declare that `impl Sized` captures `'_`, you can add an explicit `'_` lifetime bound +help: add a `use<...>` bound to explicitly capture `'_` | -LL | fn foo(x: &Vec) -> impl Sized + '_ { - | ++++ +LL | fn foo(x: &Vec) -> impl Sized + use<'_> { + | +++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/feature-gates/feature-gate-precise-capturing.rs b/tests/ui/feature-gates/feature-gate-precise-capturing.rs deleted file mode 100644 index 47a21539d37..00000000000 --- a/tests/ui/feature-gates/feature-gate-precise-capturing.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn hello() -> impl Sized + use<> {} -//~^ ERROR precise captures on `impl Trait` are experimental - -fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-precise-capturing.stderr b/tests/ui/feature-gates/feature-gate-precise-capturing.stderr deleted file mode 100644 index 04365408880..00000000000 --- a/tests/ui/feature-gates/feature-gate-precise-capturing.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0658]: precise captures on `impl Trait` are experimental - --> $DIR/feature-gate-precise-capturing.rs:1:28 - | -LL | fn hello() -> impl Sized + use<> {} - | ^^^ - | - = note: see issue #123432 for more information - = help: add `#![feature(precise_capturing)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-repr-simd.stderr b/tests/ui/feature-gates/feature-gate-repr-simd.stderr index 5b490c0c0c3..5a0ceb2dd74 100644 --- a/tests/ui/feature-gates/feature-gate-repr-simd.stderr +++ b/tests/ui/feature-gates/feature-gate-repr-simd.stderr @@ -35,3 +35,17 @@ error: aborting due to 3 previous errors Some errors have detailed explanations: E0566, E0658. For more information about an error, try `rustc --explain E0566`. +Future incompatibility report: Future breakage diagnostic: +error[E0566]: conflicting representation hints + --> $DIR/feature-gate-repr-simd.rs:4:8 + | +LL | #[repr(C)] + | ^ +LL | +LL | #[repr(simd)] + | ^^^^ + | + = 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 #68585 + = note: `#[deny(conflicting_repr_hints)]` on by default + diff --git a/tests/ui/feature-gates/feature-gate-struct-target-features.rs b/tests/ui/feature-gates/feature-gate-struct-target-features.rs new file mode 100644 index 00000000000..85494881146 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-struct-target-features.rs @@ -0,0 +1,4 @@ +#[target_feature(enable = "avx")] //~ ERROR attribute should be applied to a function definition +struct Avx {} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-struct-target-features.stderr b/tests/ui/feature-gates/feature-gate-struct-target-features.stderr new file mode 100644 index 00000000000..1e18d3ee1e1 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-struct-target-features.stderr @@ -0,0 +1,10 @@ +error: attribute should be applied to a function definition + --> $DIR/feature-gate-struct-target-features.rs:1:1 + | +LL | #[target_feature(enable = "avx")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | struct Avx {} + | ------------- not a function definition + +error: aborting due to 1 previous error + diff --git a/tests/ui/feature-gates/feature-gate-unsafe-attributes.rs b/tests/ui/feature-gates/feature-gate-unsafe-attributes.rs deleted file mode 100644 index 9eba415dda0..00000000000 --- a/tests/ui/feature-gates/feature-gate-unsafe-attributes.rs +++ /dev/null @@ -1,8 +0,0 @@ -#[unsafe(no_mangle)] //~ ERROR [E0658] -extern "C" fn foo() { - -} - -fn main() { - foo(); -} diff --git a/tests/ui/feature-gates/feature-gate-unsafe-attributes.stderr b/tests/ui/feature-gates/feature-gate-unsafe-attributes.stderr deleted file mode 100644 index dfcea756b02..00000000000 --- a/tests/ui/feature-gates/feature-gate-unsafe-attributes.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0658]: `#[unsafe()]` markers for attributes are experimental - --> $DIR/feature-gate-unsafe-attributes.rs:1:3 - | -LL | #[unsafe(no_mangle)] - | ^^^^^^ - | - = note: see issue #123757 for more information - = help: add `#![feature(unsafe_attributes)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/foreign/foreign-safe-fn-arg-mismatch.rs b/tests/ui/foreign/foreign-safe-fn-arg-mismatch.rs new file mode 100644 index 00000000000..bb1052b15e9 --- /dev/null +++ b/tests/ui/foreign/foreign-safe-fn-arg-mismatch.rs @@ -0,0 +1,13 @@ +// Make sure we don't ICE when a foreign fn doesn't implement `Fn` due to arg mismatch. + +unsafe extern "Rust" { + pub safe fn foo(); + pub safe fn bar(x: u32); +} + +fn test(_: impl Fn(i32)) {} + +fn main() { + test(foo); //~ ERROR function is expected to take 1 argument, but it takes 0 arguments + test(bar); //~ ERROR type mismatch in function arguments +} diff --git a/tests/ui/foreign/foreign-safe-fn-arg-mismatch.stderr b/tests/ui/foreign/foreign-safe-fn-arg-mismatch.stderr new file mode 100644 index 00000000000..73ccecff5ab --- /dev/null +++ b/tests/ui/foreign/foreign-safe-fn-arg-mismatch.stderr @@ -0,0 +1,44 @@ +error[E0593]: function is expected to take 1 argument, but it takes 0 arguments + --> $DIR/foreign-safe-fn-arg-mismatch.rs:11:10 + | +LL | pub safe fn foo(); + | ------------------ takes 0 arguments +... +LL | test(foo); + | ---- ^^^ expected function that takes 1 argument + | | + | required by a bound introduced by this call + | +note: required by a bound in `test` + --> $DIR/foreign-safe-fn-arg-mismatch.rs:8:17 + | +LL | fn test(_: impl Fn(i32)) {} + | ^^^^^^^ required by this bound in `test` + +error[E0631]: type mismatch in function arguments + --> $DIR/foreign-safe-fn-arg-mismatch.rs:12:10 + | +LL | pub safe fn bar(x: u32); + | ------------------------ found signature defined here +... +LL | test(bar); + | ---- ^^^ expected due to this + | | + | required by a bound introduced by this call + | + = note: expected function signature `fn(i32) -> _` + found function signature `fn(u32) -> _` +note: required by a bound in `test` + --> $DIR/foreign-safe-fn-arg-mismatch.rs:8:17 + | +LL | fn test(_: impl Fn(i32)) {} + | ^^^^^^^ required by this bound in `test` +help: consider wrapping the function in a closure + | +LL | test(|arg0: i32| bar(/* u32 */)); + | +++++++++++ +++++++++++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0593, E0631. +For more information about an error, try `rustc --explain E0593`. diff --git a/tests/ui/generic-associated-types/gat-in-trait-path.base.stderr b/tests/ui/generic-associated-types/gat-in-trait-path.base.stderr index d1decc0c3f1..37491ca12b0 100644 --- a/tests/ui/generic-associated-types/gat-in-trait-path.base.stderr +++ b/tests/ui/generic-associated-types/gat-in-trait-path.base.stderr @@ -51,7 +51,7 @@ LL | type A<'a> where Self: 'a; = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Foo` for this new enum and using it instead: Fooy Fooer - = note: required for the cast from `Box>` to `Box<(dyn Foo + 'static)>` + = note: required for the cast from `Box>` to `Box<(dyn Foo = &'a ()> + 'static)>` error: aborting due to 3 previous errors diff --git a/tests/ui/generic-associated-types/issue-76535.base.stderr b/tests/ui/generic-associated-types/issue-76535.base.stderr index bb14e297174..88c08051da7 100644 --- a/tests/ui/generic-associated-types/issue-76535.base.stderr +++ b/tests/ui/generic-associated-types/issue-76535.base.stderr @@ -47,7 +47,7 @@ LL | type SubType<'a>: SubTrait where Self: 'a; = help: consider moving `SubType` to another trait = help: only type `SuperStruct` is seen to implement the trait in this crate, consider using it directly instead = note: `SuperTrait` can be implemented in other crates; if you want to support your users passing their own types here, you can't refer to a specific type - = note: required for the cast from `Box` to `Box>>` + = note: required for the cast from `Box` to `Box = SubStruct<'_>>>` error: aborting due to 3 previous errors diff --git a/tests/ui/generic-associated-types/issue-79422.base.stderr b/tests/ui/generic-associated-types/issue-79422.base.stderr index bcc6382cf7c..551ad2a8fdf 100644 --- a/tests/ui/generic-associated-types/issue-79422.base.stderr +++ b/tests/ui/generic-associated-types/issue-79422.base.stderr @@ -49,7 +49,7 @@ LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a; = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `MapLike` for this new enum and using it instead: std::collections::BTreeMap Source - = note: required for the cast from `Box>` to `Box + 'static)>>` + = note: required for the cast from `Box>` to `Box = (dyn RefCont<'_, u8> + 'static)>>` error: aborting due to 3 previous errors diff --git a/tests/ui/generic-associated-types/issue-79422.extended.stderr b/tests/ui/generic-associated-types/issue-79422.extended.stderr index ae1526296a7..031f8d8d851 100644 --- a/tests/ui/generic-associated-types/issue-79422.extended.stderr +++ b/tests/ui/generic-associated-types/issue-79422.extended.stderr @@ -28,7 +28,7 @@ LL | type VRefCont<'a> = &'a V where Self: 'a; = note: expected trait object `(dyn RefCont<'_, u8> + 'static)` found reference `&u8` = help: `&u8` implements `RefCont` so you could box the found value and coerce it to the trait object `Box`, you will have to change the expected type as well - = note: required for the cast from `Box>` to `Box + 'static)>>` + = note: required for the cast from `Box>` to `Box = (dyn RefCont<'_, u8> + 'static)>>` error: aborting due to 2 previous errors diff --git a/tests/ui/higher-ranked/subtyping-fn-ptr-coercion.rs b/tests/ui/higher-ranked/subtyping-fn-ptr-coercion.rs new file mode 100644 index 00000000000..0cecf6808f2 --- /dev/null +++ b/tests/ui/higher-ranked/subtyping-fn-ptr-coercion.rs @@ -0,0 +1,10 @@ +//@ check-pass + +// Check that we use subtyping when reifying a closure into a function pointer. + +fn foo(x: &str) {} + +fn main() { + let c = |_: &str| {}; + let x = c as fn(&'static str); +} diff --git a/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.stderr b/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.stderr index 825682c52f9..a2d00edbb6d 100644 --- a/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.stderr +++ b/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.stderr @@ -8,10 +8,10 @@ LL | fn step2<'a, 'b: 'a>() -> impl Sized + 'a { LL | step1::<'a, 'b>() | ^^^^^^^^^^^^^^^^^ | -help: to declare that `impl Sized + 'a` captures `'b`, you can add an explicit `'b` lifetime bound +help: add a `use<...>` bound to explicitly capture `'b` | -LL | fn step2<'a, 'b: 'a>() -> impl Sized + 'a + 'b { - | ++++ +LL | fn step2<'a, 'b: 'a>() -> impl Sized + 'a + use<'a, 'b> { + | +++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.stderr b/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.stderr index b87e31acc12..a1e92e53384 100644 --- a/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.stderr +++ b/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.stderr @@ -8,10 +8,10 @@ LL | fn hide<'a, 'b: 'a, T: 'static>(x: Rc>) -> impl Swap + 'a { LL | x | ^ | -help: to declare that `impl Swap + 'a` captures `'b`, you can add an explicit `'b` lifetime bound +help: add a `use<...>` bound to explicitly capture `'b` | -LL | fn hide<'a, 'b: 'a, T: 'static>(x: Rc>) -> impl Swap + 'a + 'b { - | ++++ +LL | fn hide<'a, 'b: 'a, T: 'static>(x: Rc>) -> impl Swap + 'a + use<'a, 'b, T> { + | ++++++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/call_method_ambiguous.next.stderr b/tests/ui/impl-trait/call_method_ambiguous.next.stderr index a1f9a8b40a8..5251555f574 100644 --- a/tests/ui/impl-trait/call_method_ambiguous.next.stderr +++ b/tests/ui/impl-trait/call_method_ambiguous.next.stderr @@ -1,5 +1,5 @@ error[E0282]: type annotations needed - --> $DIR/call_method_ambiguous.rs:28:13 + --> $DIR/call_method_ambiguous.rs:26:13 | LL | let mut iter = foo(n - 1, m); | ^^^^^^^^ diff --git a/tests/ui/impl-trait/call_method_ambiguous.rs b/tests/ui/impl-trait/call_method_ambiguous.rs index 4dac605d6b8..8fd6f727b73 100644 --- a/tests/ui/impl-trait/call_method_ambiguous.rs +++ b/tests/ui/impl-trait/call_method_ambiguous.rs @@ -2,8 +2,6 @@ //@[next] compile-flags: -Znext-solver //@[current] run-pass -#![feature(precise_capturing)] - trait Get { fn get(&mut self) -> u32; } diff --git a/tests/ui/impl-trait/capture-lifetime-not-in-hir.rs b/tests/ui/impl-trait/capture-lifetime-not-in-hir.rs index 9c067cb6934..2fde0f200c0 100644 --- a/tests/ui/impl-trait/capture-lifetime-not-in-hir.rs +++ b/tests/ui/impl-trait/capture-lifetime-not-in-hir.rs @@ -6,13 +6,13 @@ trait Bar<'a> { } fn foo<'a, T: Bar<'a>>() -> impl Into { - //~^ ERROR [o, o] + //~^ ERROR ['a: o, T: o] // captures both T and 'a invariantly () } fn foo2<'a, T: Bar<'a>>() -> impl Into + 'a { - //~^ ERROR [o, o, o] + //~^ ERROR ['a: o, T: o, 'a: o] // captures both T and 'a invariantly, and also duplicates `'a` // i.e. the opaque looks like `impl Into<>::Assoc> + 'a_duplicated` () diff --git a/tests/ui/impl-trait/capture-lifetime-not-in-hir.stderr b/tests/ui/impl-trait/capture-lifetime-not-in-hir.stderr index 9d52001b024..fe8a2772a00 100644 --- a/tests/ui/impl-trait/capture-lifetime-not-in-hir.stderr +++ b/tests/ui/impl-trait/capture-lifetime-not-in-hir.stderr @@ -1,10 +1,10 @@ -error: [o, o] +error: ['a: o, T: o] --> $DIR/capture-lifetime-not-in-hir.rs:8:29 | LL | fn foo<'a, T: Bar<'a>>() -> impl Into { | ^^^^^^^^^^^^^^^^^^^ -error: [o, o, o] +error: ['a: o, T: o, 'a: o] --> $DIR/capture-lifetime-not-in-hir.rs:14:30 | LL | fn foo2<'a, T: Bar<'a>>() -> impl Into + 'a { diff --git a/tests/ui/impl-trait/hidden-lifetimes.stderr b/tests/ui/impl-trait/hidden-lifetimes.stderr index bc8f559fdee..70d8c816ecb 100644 --- a/tests/ui/impl-trait/hidden-lifetimes.stderr +++ b/tests/ui/impl-trait/hidden-lifetimes.stderr @@ -8,10 +8,10 @@ LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a { LL | x | ^ | -help: to declare that `impl Swap + 'a` captures `'b`, you can add an explicit `'b` lifetime bound +help: add a `use<...>` bound to explicitly capture `'b` | -LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a + 'b { - | ++++ +LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a + use<'a, 'b, T> { + | ++++++++++++++++ error[E0700]: hidden type for `impl Swap + 'a` captures lifetime that does not appear in bounds --> $DIR/hidden-lifetimes.rs:46:5 @@ -23,10 +23,10 @@ LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc>) -> impl S LL | x | ^ | -help: to declare that `impl Swap + 'a` captures `'b`, you can add an explicit `'b` lifetime bound +help: add a `use<...>` bound to explicitly capture `'b` | -LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc>) -> impl Swap + 'a + 'b { - | ++++ +LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc>) -> impl Swap + 'a + use<'a, 'b, T> { + | ++++++++++++++++ error: aborting due to 2 previous errors diff --git a/tests/ui/impl-trait/implicit-capture-late.stderr b/tests/ui/impl-trait/implicit-capture-late.stderr index 080750f8497..3adf78322d2 100644 --- a/tests/ui/impl-trait/implicit-capture-late.stderr +++ b/tests/ui/impl-trait/implicit-capture-late.stderr @@ -10,7 +10,7 @@ note: lifetime declared here LL | fn foo(x: Vec) -> Box Deref> { | ^^ -error: [o] +error: ['a: o] --> $DIR/implicit-capture-late.rs:10:55 | LL | fn foo(x: Vec) -> Box Deref> { diff --git a/tests/ui/impl-trait/in-trait/cannot-capture-intersection.rs b/tests/ui/impl-trait/in-trait/cannot-capture-intersection.rs index d7b62436d2d..e00214fe8e0 100644 --- a/tests/ui/impl-trait/in-trait/cannot-capture-intersection.rs +++ b/tests/ui/impl-trait/in-trait/cannot-capture-intersection.rs @@ -1,5 +1,3 @@ -#![feature(precise_capturing)] - use std::future::Future; use std::pin::Pin; diff --git a/tests/ui/impl-trait/in-trait/cannot-capture-intersection.stderr b/tests/ui/impl-trait/in-trait/cannot-capture-intersection.stderr index 92ef66c5504..a8f5bfc94c1 100644 --- a/tests/ui/impl-trait/in-trait/cannot-capture-intersection.stderr +++ b/tests/ui/impl-trait/in-trait/cannot-capture-intersection.stderr @@ -1,5 +1,5 @@ error[E0700]: hidden type for `impl Future` captures lifetime that does not appear in bounds - --> $DIR/cannot-capture-intersection.rs:24:9 + --> $DIR/cannot-capture-intersection.rs:22:9 | LL | fn foo<'a, 'b>(&'a self, x: &'b i32) -> impl Future { | ------------------------- opaque type defined here diff --git a/tests/ui/impl-trait/in-trait/refine-err.rs b/tests/ui/impl-trait/in-trait/refine-err.rs new file mode 100644 index 00000000000..7518cee97c4 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/refine-err.rs @@ -0,0 +1,14 @@ +#![deny(refining_impl_trait)] + +trait FromRow { + fn prepare(self) -> impl Fn() -> T; + //~^ ERROR cannot find type `T` in this scope +} + +impl FromRow for T { + fn prepare(self) -> impl Fn() -> T { + || todo!() + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/refine-err.stderr b/tests/ui/impl-trait/in-trait/refine-err.stderr new file mode 100644 index 00000000000..6b4ef74d50a --- /dev/null +++ b/tests/ui/impl-trait/in-trait/refine-err.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `T` in this scope + --> $DIR/refine-err.rs:4:38 + | +LL | fn prepare(self) -> impl Fn() -> T; + | ^ not found in this scope + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/impl-trait/in-trait/span-bug-issue-121457.rs b/tests/ui/impl-trait/in-trait/span-bug-issue-121457.rs index 7a51037324f..ab21dae7dc5 100644 --- a/tests/ui/impl-trait/in-trait/span-bug-issue-121457.rs +++ b/tests/ui/impl-trait/in-trait/span-bug-issue-121457.rs @@ -14,7 +14,6 @@ impl<'a, I: 'a + Iterable> Iterable for &'a I { //~^ ERROR binding for associated type `Item` references lifetime `'missing` //~| ERROR binding for associated type `Item` references lifetime `'missing` //~| ERROR `()` is not an iterator - //~| WARNING impl trait in impl method signature does not match trait method signature } fn main() {} diff --git a/tests/ui/impl-trait/in-trait/span-bug-issue-121457.stderr b/tests/ui/impl-trait/in-trait/span-bug-issue-121457.stderr index 67c4df0f3a9..d8a2eef94a1 100644 --- a/tests/ui/impl-trait/in-trait/span-bug-issue-121457.stderr +++ b/tests/ui/impl-trait/in-trait/span-bug-issue-121457.stderr @@ -32,24 +32,7 @@ LL | fn iter(&self) -> impl for<'missing> Iterator $DIR/span-bug-issue-121457.rs:13:51 - | -LL | fn iter(&self) -> impl Iterator; - | ------------- return type from trait method defined here -... -LL | fn iter(&self) -> impl for<'missing> Iterator> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ this bound is stronger than that defined on the trait - | - = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate - = note: we are soliciting feedback, see issue #121718 for more information - = note: `#[warn(refining_impl_trait_reachable)]` on by default -help: replace the return type so that it matches the trait - | -LL | fn iter(&self) -> impl Iterator {} - | ~~~~~~~~~~~~~ - -error: aborting due to 4 previous errors; 1 warning emitted +error: aborting due to 4 previous errors Some errors have detailed explanations: E0195, E0277, E0582. For more information about an error, try `rustc --explain E0195`. diff --git a/tests/ui/impl-trait/in-trait/variance.rs b/tests/ui/impl-trait/in-trait/variance.rs index 65565dcc2a6..0ac44bf7546 100644 --- a/tests/ui/impl-trait/in-trait/variance.rs +++ b/tests/ui/impl-trait/in-trait/variance.rs @@ -7,14 +7,16 @@ impl Captures<'_> for T {} trait Foo<'i> { fn implicit_capture_early<'a: 'a>() -> impl Sized {} - //~^ [o, *, *, o, o] - // Self, 'i, 'a, 'i_duplicated, 'a_duplicated + //~^ [Self: o, 'i: *, 'a: *, 'a: o, 'i: o] - fn explicit_capture_early<'a: 'a>() -> impl Sized + Captures<'a> {} //~ [o, *, *, o, o] + fn explicit_capture_early<'a: 'a>() -> impl Sized + Captures<'a> {} + //~^ [Self: o, 'i: *, 'a: *, 'a: o, 'i: o] - fn implicit_capture_late<'a>(_: &'a ()) -> impl Sized {} //~ [o, *, o, o] + fn implicit_capture_late<'a>(_: &'a ()) -> impl Sized {} + //~^ [Self: o, 'i: *, 'a: o, 'i: o] - fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} //~ [o, *, o, o] + fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} + //~^ [Self: o, 'i: *, 'a: o, 'i: o] } fn main() {} diff --git a/tests/ui/impl-trait/in-trait/variance.stderr b/tests/ui/impl-trait/in-trait/variance.stderr index 8cae5a92f0d..54e0afbaa95 100644 --- a/tests/ui/impl-trait/in-trait/variance.stderr +++ b/tests/ui/impl-trait/in-trait/variance.stderr @@ -1,23 +1,23 @@ -error: [o, *, *, o, o] +error: [Self: o, 'i: *, 'a: *, 'a: o, 'i: o] --> $DIR/variance.rs:9:44 | LL | fn implicit_capture_early<'a: 'a>() -> impl Sized {} | ^^^^^^^^^^ -error: [o, *, *, o, o] - --> $DIR/variance.rs:13:44 +error: [Self: o, 'i: *, 'a: *, 'a: o, 'i: o] + --> $DIR/variance.rs:12:44 | LL | fn explicit_capture_early<'a: 'a>() -> impl Sized + Captures<'a> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [o, *, o, o] +error: [Self: o, 'i: *, 'a: o, 'i: o] --> $DIR/variance.rs:15:48 | LL | fn implicit_capture_late<'a>(_: &'a ()) -> impl Sized {} | ^^^^^^^^^^ -error: [o, *, o, o] - --> $DIR/variance.rs:17:48 +error: [Self: o, 'i: *, 'a: o, 'i: o] + --> $DIR/variance.rs:18:48 | LL | fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr index 273f51ddbe3..f620bf6dc38 100644 --- a/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -7,10 +7,10 @@ LL | fn elided(x: &i32) -> impl Copy { x } | | opaque type defined here | hidden type `&i32` captures the anonymous lifetime defined here | -help: to declare that `impl Copy` captures `'_`, you can add an explicit `'_` lifetime bound +help: add a `use<...>` bound to explicitly capture `'_` | -LL | fn elided(x: &i32) -> impl Copy + '_ { x } - | ++++ +LL | fn elided(x: &i32) -> impl Copy + use<'_> { x } + | +++++++++ error[E0700]: hidden type for `impl Copy` captures lifetime that does not appear in bounds --> $DIR/must_outlive_least_region_or_bound.rs:6:44 @@ -21,10 +21,10 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } | | opaque type defined here | hidden type `&'a i32` captures the lifetime `'a` as defined here | -help: to declare that `impl Copy` captures `'a`, you can add an explicit `'a` lifetime bound +help: add a `use<...>` bound to explicitly capture `'a` | -LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x } - | ++++ +LL | fn explicit<'a>(x: &'a i32) -> impl Copy + use<'a> { x } + | +++++++++ error: lifetime may not live long enough --> $DIR/must_outlive_least_region_or_bound.rs:9:46 @@ -108,10 +108,10 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32 LL | move |_| println!("{}", y) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: to declare that `impl Fn(&'a u32)` captures `'b`, you can add an explicit `'b` lifetime bound +help: add a `use<...>` bound to explicitly capture `'b` | -LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) + 'b { - | ++++ +LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) + use<'a, 'b> { + | +++++++++++++ error[E0310]: the parameter type `T` may not live long enough --> $DIR/must_outlive_least_region_or_bound.rs:47:5 diff --git a/tests/ui/impl-trait/nested-return-type4.stderr b/tests/ui/impl-trait/nested-return-type4.stderr index f1e3b97be02..407800eff18 100644 --- a/tests/ui/impl-trait/nested-return-type4.stderr +++ b/tests/ui/impl-trait/nested-return-type4.stderr @@ -8,14 +8,10 @@ LL | fn test<'s: 's>(s: &'s str) -> impl std::future::Future` captures `'s`, you can add an explicit `'s` lifetime bound +help: add a `use<...>` bound to explicitly capture `'s` | -LL | fn test<'s: 's>(s: &'s str) -> impl std::future::Future + 's { - | ++++ -help: to declare that `impl Sized` captures `'s`, you can add an explicit `'s` lifetime bound - | -LL | fn test<'s: 's>(s: &'s str) -> impl std::future::Future { - | ++++ +LL | fn test<'s: 's>(s: &'s str) -> impl std::future::Future + use<'s> { + | +++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/precise-capturing/apit.rs b/tests/ui/impl-trait/precise-capturing/apit.rs index 64c15d6df96..447d8fdf2cd 100644 --- a/tests/ui/impl-trait/precise-capturing/apit.rs +++ b/tests/ui/impl-trait/precise-capturing/apit.rs @@ -1,5 +1,3 @@ -#![feature(precise_capturing)] - fn hello(_: impl Sized + use<>) {} //~^ ERROR `use<...>` precise capturing syntax not allowed in argument-position `impl Trait` diff --git a/tests/ui/impl-trait/precise-capturing/apit.stderr b/tests/ui/impl-trait/precise-capturing/apit.stderr index 1d6225a1ff8..7573e0838ab 100644 --- a/tests/ui/impl-trait/precise-capturing/apit.stderr +++ b/tests/ui/impl-trait/precise-capturing/apit.stderr @@ -1,5 +1,5 @@ error: `use<...>` precise capturing syntax not allowed in argument-position `impl Trait` - --> $DIR/apit.rs:3:26 + --> $DIR/apit.rs:1:26 | LL | fn hello(_: impl Sized + use<>) {} | ^^^^^ diff --git a/tests/ui/impl-trait/precise-capturing/bad-lifetimes.rs b/tests/ui/impl-trait/precise-capturing/bad-lifetimes.rs index d2d4570c570..161fe23c899 100644 --- a/tests/ui/impl-trait/precise-capturing/bad-lifetimes.rs +++ b/tests/ui/impl-trait/precise-capturing/bad-lifetimes.rs @@ -1,5 +1,3 @@ -#![feature(precise_capturing)] - fn no_elided_lt() -> impl Sized + use<'_> {} //~^ ERROR missing lifetime specifier //~| ERROR expected lifetime parameter in `use<...>` precise captures list, found `'_` diff --git a/tests/ui/impl-trait/precise-capturing/bad-lifetimes.stderr b/tests/ui/impl-trait/precise-capturing/bad-lifetimes.stderr index 550996ab5e5..a8acecf10c7 100644 --- a/tests/ui/impl-trait/precise-capturing/bad-lifetimes.stderr +++ b/tests/ui/impl-trait/precise-capturing/bad-lifetimes.stderr @@ -1,5 +1,5 @@ error[E0106]: missing lifetime specifier - --> $DIR/bad-lifetimes.rs:3:39 + --> $DIR/bad-lifetimes.rs:1:39 | LL | fn no_elided_lt() -> impl Sized + use<'_> {} | ^^ expected named lifetime parameter @@ -11,7 +11,7 @@ LL | fn no_elided_lt() -> impl Sized + use<'static> {} | ~~~~~~~ error[E0261]: use of undeclared lifetime name `'missing` - --> $DIR/bad-lifetimes.rs:10:37 + --> $DIR/bad-lifetimes.rs:8:37 | LL | fn missing_lt() -> impl Sized + use<'missing> {} | - ^^^^^^^^ undeclared lifetime @@ -19,13 +19,13 @@ LL | fn missing_lt() -> impl Sized + use<'missing> {} | help: consider introducing lifetime `'missing` here: `<'missing>` error: expected lifetime parameter in `use<...>` precise captures list, found `'_` - --> $DIR/bad-lifetimes.rs:3:39 + --> $DIR/bad-lifetimes.rs:1:39 | LL | fn no_elided_lt() -> impl Sized + use<'_> {} | ^^ error: expected lifetime parameter in `use<...>` precise captures list, found `'static` - --> $DIR/bad-lifetimes.rs:7:36 + --> $DIR/bad-lifetimes.rs:5:36 | LL | fn static_lt() -> impl Sized + use<'static> {} | ^^^^^^^ diff --git a/tests/ui/impl-trait/precise-capturing/bad-params.rs b/tests/ui/impl-trait/precise-capturing/bad-params.rs index 08eee67c0e5..17b517abd74 100644 --- a/tests/ui/impl-trait/precise-capturing/bad-params.rs +++ b/tests/ui/impl-trait/precise-capturing/bad-params.rs @@ -1,5 +1,3 @@ -#![feature(precise_capturing)] - fn missing() -> impl Sized + use {} //~^ ERROR cannot find type `T` in this scope diff --git a/tests/ui/impl-trait/precise-capturing/bad-params.stderr b/tests/ui/impl-trait/precise-capturing/bad-params.stderr index e104f115aa3..06ccf356948 100644 --- a/tests/ui/impl-trait/precise-capturing/bad-params.stderr +++ b/tests/ui/impl-trait/precise-capturing/bad-params.stderr @@ -1,5 +1,5 @@ error[E0412]: cannot find type `T` in this scope - --> $DIR/bad-params.rs:3:34 + --> $DIR/bad-params.rs:1:34 | LL | fn missing() -> impl Sized + use {} | ^ not found in this scope @@ -10,7 +10,7 @@ LL | fn missing() -> impl Sized + use {} | +++ error[E0411]: cannot find type `Self` in this scope - --> $DIR/bad-params.rs:6:39 + --> $DIR/bad-params.rs:4:39 | LL | fn missing_self() -> impl Sized + use {} | ------------ ^^^^ `Self` is only available in impls, traits, and type definitions @@ -18,7 +18,7 @@ LL | fn missing_self() -> impl Sized + use {} | `Self` not allowed in a function error: `Self` can't be captured in `use<...>` precise captures list, since it is an alias - --> $DIR/bad-params.rs:11:48 + --> $DIR/bad-params.rs:9:48 | LL | impl MyType { | ----------- `Self` is not a generic argument, but an alias to the type of the implementation @@ -26,7 +26,7 @@ LL | fn self_is_not_param() -> impl Sized + use {} | ^^^^ error: expected type or const parameter in `use<...>` precise captures list, found function - --> $DIR/bad-params.rs:15:32 + --> $DIR/bad-params.rs:13:32 | LL | fn hello() -> impl Sized + use {} | ^^^^^ diff --git a/tests/ui/impl-trait/precise-capturing/bound-modifiers.rs b/tests/ui/impl-trait/precise-capturing/bound-modifiers.rs index 15f21882628..47695814668 100644 --- a/tests/ui/impl-trait/precise-capturing/bound-modifiers.rs +++ b/tests/ui/impl-trait/precise-capturing/bound-modifiers.rs @@ -1,7 +1,5 @@ //@ edition: 2021 -#![feature(precise_capturing)] - fn polarity() -> impl Sized + ?use<> {} //~^ ERROR expected identifier, found keyword `use` //~| ERROR cannot find trait `r#use` in this scope diff --git a/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr b/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr index 4602225e7b9..aaebfe2a86e 100644 --- a/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr +++ b/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr @@ -1,53 +1,53 @@ error: expected identifier, found keyword `use` - --> $DIR/bound-modifiers.rs:5:32 + --> $DIR/bound-modifiers.rs:3:32 | LL | fn polarity() -> impl Sized + ?use<> {} | ^^^ expected identifier, found keyword error: expected identifier, found keyword `use` - --> $DIR/bound-modifiers.rs:11:38 + --> $DIR/bound-modifiers.rs:9:38 | LL | fn asyncness() -> impl Sized + async use<> {} | ^^^ expected identifier, found keyword error: expected identifier, found keyword `use` - --> $DIR/bound-modifiers.rs:16:38 + --> $DIR/bound-modifiers.rs:14:38 | LL | fn constness() -> impl Sized + const use<> {} | ^^^ expected identifier, found keyword error: expected identifier, found keyword `use` - --> $DIR/bound-modifiers.rs:21:37 + --> $DIR/bound-modifiers.rs:19:37 | LL | fn binder() -> impl Sized + for<'a> use<> {} | ^^^ expected identifier, found keyword error[E0405]: cannot find trait `r#use` in this scope - --> $DIR/bound-modifiers.rs:5:32 + --> $DIR/bound-modifiers.rs:3:32 | LL | fn polarity() -> impl Sized + ?use<> {} | ^^^ not found in this scope error[E0405]: cannot find trait `r#use` in this scope - --> $DIR/bound-modifiers.rs:11:38 + --> $DIR/bound-modifiers.rs:9:38 | LL | fn asyncness() -> impl Sized + async use<> {} | ^^^ not found in this scope error[E0405]: cannot find trait `r#use` in this scope - --> $DIR/bound-modifiers.rs:16:38 + --> $DIR/bound-modifiers.rs:14:38 | LL | fn constness() -> impl Sized + const use<> {} | ^^^ not found in this scope error[E0405]: cannot find trait `r#use` in this scope - --> $DIR/bound-modifiers.rs:21:37 + --> $DIR/bound-modifiers.rs:19:37 | LL | fn binder() -> impl Sized + for<'a> use<> {} | ^^^ not found in this scope error[E0658]: async closures are unstable - --> $DIR/bound-modifiers.rs:11:32 + --> $DIR/bound-modifiers.rs:9:32 | LL | fn asyncness() -> impl Sized + async use<> {} | ^^^^^ @@ -58,7 +58,7 @@ LL | fn asyncness() -> impl Sized + async use<> {} = help: to use an async block, remove the `||`: `async {` error[E0658]: const trait impls are experimental - --> $DIR/bound-modifiers.rs:16:32 + --> $DIR/bound-modifiers.rs:14:32 | LL | fn constness() -> impl Sized + const use<> {} | ^^^^^ @@ -68,13 +68,13 @@ LL | fn constness() -> impl Sized + const use<> {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default - --> $DIR/bound-modifiers.rs:5:31 + --> $DIR/bound-modifiers.rs:3:31 | LL | fn polarity() -> impl Sized + ?use<> {} | ^^^^^^ warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default - --> $DIR/bound-modifiers.rs:5:31 + --> $DIR/bound-modifiers.rs:3:31 | LL | fn polarity() -> impl Sized + ?use<> {} | ^^^^^^ diff --git a/tests/ui/impl-trait/precise-capturing/capture-parent-arg.rs b/tests/ui/impl-trait/precise-capturing/capture-parent-arg.rs index 82b953bfed4..c41f136b96f 100644 --- a/tests/ui/impl-trait/precise-capturing/capture-parent-arg.rs +++ b/tests/ui/impl-trait/precise-capturing/capture-parent-arg.rs @@ -1,5 +1,3 @@ -#![feature(precise_capturing)] - trait Tr { type Assoc; } diff --git a/tests/ui/impl-trait/precise-capturing/capture-parent-arg.stderr b/tests/ui/impl-trait/precise-capturing/capture-parent-arg.stderr index b521ee0a902..f02b8d7c850 100644 --- a/tests/ui/impl-trait/precise-capturing/capture-parent-arg.stderr +++ b/tests/ui/impl-trait/precise-capturing/capture-parent-arg.stderr @@ -1,5 +1,5 @@ error: `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list - --> $DIR/capture-parent-arg.rs:27:31 + --> $DIR/capture-parent-arg.rs:25:31 | LL | impl<'a> W<'a> { | -- this lifetime parameter is captured @@ -7,7 +7,7 @@ LL | fn bad1() -> impl Into< as Tr>::Assoc> + use<> {} | -------------^^------------------------ lifetime captured due to being mentioned in the bounds of the `impl Trait` error: `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list - --> $DIR/capture-parent-arg.rs:33:18 + --> $DIR/capture-parent-arg.rs:31:18 | LL | impl<'a> W<'a> { | -- this lifetime parameter is captured diff --git a/tests/ui/impl-trait/precise-capturing/duplicated-use.real.stderr b/tests/ui/impl-trait/precise-capturing/duplicated-use.real.stderr index d8edd672b48..95132c611e5 100644 --- a/tests/ui/impl-trait/precise-capturing/duplicated-use.real.stderr +++ b/tests/ui/impl-trait/precise-capturing/duplicated-use.real.stderr @@ -1,5 +1,5 @@ error: duplicate `use<...>` precise capturing syntax - --> $DIR/duplicated-use.rs:7:32 + --> $DIR/duplicated-use.rs:5:32 | LL | fn hello<'a>() -> impl Sized + use<'a> + use<'a> {} | ^^^^^^^ ------- second `use<...>` here diff --git a/tests/ui/impl-trait/precise-capturing/duplicated-use.rs b/tests/ui/impl-trait/precise-capturing/duplicated-use.rs index bfbdcdbf311..b5632dc1577 100644 --- a/tests/ui/impl-trait/precise-capturing/duplicated-use.rs +++ b/tests/ui/impl-trait/precise-capturing/duplicated-use.rs @@ -1,8 +1,6 @@ //@ revisions: real pre_expansion //@[pre_expansion] check-pass -#![feature(precise_capturing)] - #[cfg(real)] fn hello<'a>() -> impl Sized + use<'a> + use<'a> {} //[real]~^ ERROR duplicate `use<...>` precise capturing syntax diff --git a/tests/ui/impl-trait/precise-capturing/dyn-use.rs b/tests/ui/impl-trait/precise-capturing/dyn-use.rs index ce7a0f3c7b2..fb2f83e2d21 100644 --- a/tests/ui/impl-trait/precise-capturing/dyn-use.rs +++ b/tests/ui/impl-trait/precise-capturing/dyn-use.rs @@ -1,4 +1,2 @@ -#![feature(precise_capturing)] - fn dyn() -> &'static dyn use<> { &() } //~^ ERROR expected one of `!`, `(`, `::`, `<`, `where`, or `{`, found keyword `use` diff --git a/tests/ui/impl-trait/precise-capturing/dyn-use.stderr b/tests/ui/impl-trait/precise-capturing/dyn-use.stderr index 5519633de1f..d8903fc4129 100644 --- a/tests/ui/impl-trait/precise-capturing/dyn-use.stderr +++ b/tests/ui/impl-trait/precise-capturing/dyn-use.stderr @@ -1,5 +1,5 @@ error: expected one of `!`, `(`, `::`, `<`, `where`, or `{`, found keyword `use` - --> $DIR/dyn-use.rs:3:26 + --> $DIR/dyn-use.rs:1:26 | LL | fn dyn() -> &'static dyn use<> { &() } | ^^^ expected one of `!`, `(`, `::`, `<`, `where`, or `{` diff --git a/tests/ui/impl-trait/precise-capturing/elided.rs b/tests/ui/impl-trait/precise-capturing/elided.rs index 34d1ba620dc..472bac9d722 100644 --- a/tests/ui/impl-trait/precise-capturing/elided.rs +++ b/tests/ui/impl-trait/precise-capturing/elided.rs @@ -1,7 +1,5 @@ //@ check-pass -#![feature(precise_capturing)] - fn elided(x: &()) -> impl Sized + use<'_> { x } fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-const.rs b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-const.rs index 26d29e456ea..2bf2e5fef18 100644 --- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-const.rs +++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-const.rs @@ -1,5 +1,3 @@ -#![feature(precise_capturing)] - fn constant() -> impl Sized + use<> {} //~^ ERROR `impl Trait` must mention all const parameters in scope diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-const.stderr b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-const.stderr index 989ed136d4c..e8fab0a8ad6 100644 --- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-const.stderr +++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-const.stderr @@ -1,5 +1,5 @@ error: `impl Trait` must mention all const parameters in scope in `use<...>` - --> $DIR/forgot-to-capture-const.rs:3:34 + --> $DIR/forgot-to-capture-const.rs:1:34 | LL | fn constant() -> impl Sized + use<> {} | -------------- ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-lifetime.rs b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-lifetime.rs index f18dbca6c5e..64bac0c8aca 100644 --- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-lifetime.rs +++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-lifetime.rs @@ -1,5 +1,3 @@ -#![feature(precise_capturing)] - fn lifetime_in_bounds<'a>(x: &'a ()) -> impl Into<&'a ()> + use<> { x } //~^ ERROR `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-lifetime.stderr b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-lifetime.stderr index 979c0ca6d7b..907ed00f8c0 100644 --- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-lifetime.stderr +++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-lifetime.stderr @@ -1,5 +1,5 @@ error: `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list - --> $DIR/forgot-to-capture-lifetime.rs:3:52 + --> $DIR/forgot-to-capture-lifetime.rs:1:52 | LL | fn lifetime_in_bounds<'a>(x: &'a ()) -> impl Into<&'a ()> + use<> { x } | -- -----------^^------------ @@ -8,7 +8,7 @@ LL | fn lifetime_in_bounds<'a>(x: &'a ()) -> impl Into<&'a ()> + use<> { x } | this lifetime parameter is captured error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds - --> $DIR/forgot-to-capture-lifetime.rs:6:62 + --> $DIR/forgot-to-capture-lifetime.rs:4:62 | LL | fn lifetime_in_hidden<'a>(x: &'a ()) -> impl Sized + use<> { x } | -- ------------------ ^ diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs index 0028a45cbf3..9d68819f657 100644 --- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs +++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs @@ -1,5 +1,3 @@ -#![feature(precise_capturing)] - fn type_param() -> impl Sized + use<> {} //~^ ERROR `impl Trait` must mention all type parameters in scope diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr index 89bd4df4431..d9be9d543e4 100644 --- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr +++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr @@ -1,5 +1,5 @@ error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits - --> $DIR/forgot-to-capture-type.rs:7:30 + --> $DIR/forgot-to-capture-type.rs:5:30 | LL | fn bar() -> impl Sized + use<>; | ^^^^^ @@ -7,7 +7,7 @@ LL | fn bar() -> impl Sized + use<>; = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope error: `impl Trait` must mention all type parameters in scope in `use<...>` - --> $DIR/forgot-to-capture-type.rs:3:23 + --> $DIR/forgot-to-capture-type.rs:1:23 | LL | fn type_param() -> impl Sized + use<> {} | - ^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | fn type_param() -> impl Sized + use<> {} = note: currently, all type parameters are required to be mentioned in the precise captures list error: `impl Trait` must mention the `Self` type of the trait in `use<...>` - --> $DIR/forgot-to-capture-type.rs:7:17 + --> $DIR/forgot-to-capture-type.rs:5:17 | LL | trait Foo { | --------- `Self` type parameter is implicitly captured by this `impl Trait` diff --git a/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.rs b/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.rs index b50780643f1..d34c6135596 100644 --- a/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.rs +++ b/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.rs @@ -1,5 +1,3 @@ -#![feature(precise_capturing)] - fn lifetime<'a, 'b>(x: &'a ()) -> impl Sized + use<'b> { //~^ HELP add `'a` to the `use<...>` bound x diff --git a/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.stderr b/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.stderr index 1007a835894..b0c4cc2fea0 100644 --- a/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.stderr +++ b/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.stderr @@ -1,5 +1,5 @@ error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds - --> $DIR/hidden-type-suggestion.rs:5:5 + --> $DIR/hidden-type-suggestion.rs:3:5 | LL | fn lifetime<'a, 'b>(x: &'a ()) -> impl Sized + use<'b> { | -- -------------------- opaque type defined here @@ -15,7 +15,7 @@ LL | fn lifetime<'a, 'b>(x: &'a ()) -> impl Sized + use<'b, 'a> { | ++++ error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds - --> $DIR/hidden-type-suggestion.rs:11:5 + --> $DIR/hidden-type-suggestion.rs:9:5 | LL | fn param<'a, T>(x: &'a ()) -> impl Sized + use { | -- ------------------- opaque type defined here @@ -31,7 +31,7 @@ LL | fn param<'a, T>(x: &'a ()) -> impl Sized + use<'a, T> { | +++ error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds - --> $DIR/hidden-type-suggestion.rs:17:5 + --> $DIR/hidden-type-suggestion.rs:15:5 | LL | fn empty<'a>(x: &'a ()) -> impl Sized + use<> { | -- ------------------ opaque type defined here @@ -47,7 +47,7 @@ LL | fn empty<'a>(x: &'a ()) -> impl Sized + use<'a> { | ++ error[E0700]: hidden type for `impl Captures<'captured>` captures lifetime that does not appear in bounds - --> $DIR/hidden-type-suggestion.rs:26:5 + --> $DIR/hidden-type-suggestion.rs:24:5 | LL | fn missing<'a, 'captured, 'not_captured, Captured>(x: &'a ()) -> impl Captures<'captured> { | -- ------------------------ opaque type defined here @@ -63,7 +63,7 @@ LL | fn missing<'a, 'captured, 'not_captured, Captured>(x: &'a ()) -> impl Captu | ++++++++++++++++++++++++++++++ error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds - --> $DIR/hidden-type-suggestion.rs:32:5 + --> $DIR/hidden-type-suggestion.rs:30:5 | LL | fn no_params_yet(_: impl Sized, y: &()) -> impl Sized { | --- ---------- opaque type defined here @@ -74,7 +74,7 @@ LL | y | ^ | note: you could use a `use<...>` bound to explicitly capture `'_`, but argument-position `impl Trait`s are not nameable - --> $DIR/hidden-type-suggestion.rs:30:21 + --> $DIR/hidden-type-suggestion.rs:28:21 | LL | fn no_params_yet(_: impl Sized, y: &()) -> impl Sized { | ^^^^^^^^^^ @@ -84,7 +84,7 @@ LL | fn no_params_yet(_: T, y: &()) -> impl Sized + use<'_, T> { | ++++++++++ ~ ++++++++++++ error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds - --> $DIR/hidden-type-suggestion.rs:38:5 + --> $DIR/hidden-type-suggestion.rs:36:5 | LL | fn yes_params_yet<'a, T>(_: impl Sized, y: &'a ()) -> impl Sized { | -- ---------- opaque type defined here @@ -95,7 +95,7 @@ LL | y | ^ | note: you could use a `use<...>` bound to explicitly capture `'a`, but argument-position `impl Trait`s are not nameable - --> $DIR/hidden-type-suggestion.rs:36:29 + --> $DIR/hidden-type-suggestion.rs:34:29 | LL | fn yes_params_yet<'a, T>(_: impl Sized, y: &'a ()) -> impl Sized { | ^^^^^^^^^^ diff --git a/tests/ui/impl-trait/precise-capturing/higher-ranked.rs b/tests/ui/impl-trait/precise-capturing/higher-ranked.rs index 21ac19640bc..3dc8523e963 100644 --- a/tests/ui/impl-trait/precise-capturing/higher-ranked.rs +++ b/tests/ui/impl-trait/precise-capturing/higher-ranked.rs @@ -2,7 +2,7 @@ // Show how precise captures allow us to skip capturing a higher-ranked lifetime -#![feature(lifetime_capture_rules_2024, precise_capturing)] +#![feature(lifetime_capture_rules_2024)] trait Trait<'a> { type Item; diff --git a/tests/ui/impl-trait/precise-capturing/illegal-positions.real.stderr b/tests/ui/impl-trait/precise-capturing/illegal-positions.real.stderr index 2b234bcb6a5..95eb49daf28 100644 --- a/tests/ui/impl-trait/precise-capturing/illegal-positions.real.stderr +++ b/tests/ui/impl-trait/precise-capturing/illegal-positions.real.stderr @@ -1,53 +1,53 @@ error: `use<...>` precise capturing syntax not allowed in supertrait bounds - --> $DIR/illegal-positions.rs:8:12 + --> $DIR/illegal-positions.rs:6:12 | LL | trait Foo: use<> { | ^^^^^ error: `use<...>` precise capturing syntax not allowed in bounds - --> $DIR/illegal-positions.rs:10:33 + --> $DIR/illegal-positions.rs:8:33 | LL | type Assoc: use<> where (): use<>; | ^^^^^ error: `use<...>` precise capturing syntax not allowed in bounds - --> $DIR/illegal-positions.rs:10:17 + --> $DIR/illegal-positions.rs:8:17 | LL | type Assoc: use<> where (): use<>; | ^^^^^ error: `use<...>` precise capturing syntax not allowed in bounds - --> $DIR/illegal-positions.rs:16:11 + --> $DIR/illegal-positions.rs:14:11 | LL | fn fun>(_: impl use<>) where (): use<> {} | ^^^^^ error: `use<...>` precise capturing syntax not allowed in bounds - --> $DIR/illegal-positions.rs:16:43 + --> $DIR/illegal-positions.rs:14:43 | LL | fn fun>(_: impl use<>) where (): use<> {} | ^^^^^ error: at least one trait must be specified - --> $DIR/illegal-positions.rs:16:21 + --> $DIR/illegal-positions.rs:14:21 | LL | fn fun>(_: impl use<>) where (): use<> {} | ^^^^^^^^^^ error: `use<...>` precise capturing syntax not allowed in `dyn` trait object bounds - --> $DIR/illegal-positions.rs:23:25 + --> $DIR/illegal-positions.rs:21:25 | LL | fn dynamic() -> Box> {} | ^^^^^ error: `use<...>` precise capturing syntax not allowed in argument-position `impl Trait` - --> $DIR/illegal-positions.rs:16:26 + --> $DIR/illegal-positions.rs:14:26 | LL | fn fun>(_: impl use<>) where (): use<> {} | ^^^^^ error[E0224]: at least one trait is required for an object type - --> $DIR/illegal-positions.rs:23:21 + --> $DIR/illegal-positions.rs:21:21 | LL | fn dynamic() -> Box> {} | ^^^^^^^^^ diff --git a/tests/ui/impl-trait/precise-capturing/illegal-positions.rs b/tests/ui/impl-trait/precise-capturing/illegal-positions.rs index 681458e25f8..d446a50d92d 100644 --- a/tests/ui/impl-trait/precise-capturing/illegal-positions.rs +++ b/tests/ui/impl-trait/precise-capturing/illegal-positions.rs @@ -2,8 +2,6 @@ //@[pre_expansion] check-pass //@ edition: 2021 -#![feature(precise_capturing)] - #[cfg(real)] trait Foo: use<> { //[real]~^ ERROR `use<...>` precise capturing syntax not allowed diff --git a/tests/ui/impl-trait/precise-capturing/ordering.rs b/tests/ui/impl-trait/precise-capturing/ordering.rs index eb570a120cc..20638e0a623 100644 --- a/tests/ui/impl-trait/precise-capturing/ordering.rs +++ b/tests/ui/impl-trait/precise-capturing/ordering.rs @@ -1,5 +1,3 @@ -#![feature(precise_capturing)] - fn lt<'a>() -> impl Sized + use<'a, 'a> {} //~^ ERROR cannot capture parameter `'a` twice diff --git a/tests/ui/impl-trait/precise-capturing/ordering.stderr b/tests/ui/impl-trait/precise-capturing/ordering.stderr index ecd47159059..05dec2d5c5a 100644 --- a/tests/ui/impl-trait/precise-capturing/ordering.stderr +++ b/tests/ui/impl-trait/precise-capturing/ordering.stderr @@ -1,23 +1,23 @@ error: cannot capture parameter `'a` twice - --> $DIR/ordering.rs:3:33 + --> $DIR/ordering.rs:1:33 | LL | fn lt<'a>() -> impl Sized + use<'a, 'a> {} | ^^ -- parameter captured again here error: cannot capture parameter `T` twice - --> $DIR/ordering.rs:6:32 + --> $DIR/ordering.rs:4:32 | LL | fn ty() -> impl Sized + use {} | ^ - parameter captured again here error: cannot capture parameter `N` twice - --> $DIR/ordering.rs:9:45 + --> $DIR/ordering.rs:7:45 | LL | fn ct() -> impl Sized + use {} | ^ - parameter captured again here error: lifetime parameter `'a` must be listed before non-lifetime parameters - --> $DIR/ordering.rs:12:45 + --> $DIR/ordering.rs:10:45 | LL | fn ordering<'a, T>() -> impl Sized + use {} | - ^^ diff --git a/tests/ui/impl-trait/precise-capturing/outlives.rs b/tests/ui/impl-trait/precise-capturing/outlives.rs index 26ac922b5b9..f86a61be1e0 100644 --- a/tests/ui/impl-trait/precise-capturing/outlives.rs +++ b/tests/ui/impl-trait/precise-capturing/outlives.rs @@ -2,7 +2,7 @@ // Show that precise captures allow us to skip a lifetime param for outlives -#![feature(lifetime_capture_rules_2024, precise_capturing)] +#![feature(lifetime_capture_rules_2024)] fn hello<'a: 'a, 'b: 'b>() -> impl Sized + use<'a> { } diff --git a/tests/ui/impl-trait/precise-capturing/overcaptures-2024.fixed b/tests/ui/impl-trait/precise-capturing/overcaptures-2024.fixed index 5ac296a9cbd..89a3f3136c8 100644 --- a/tests/ui/impl-trait/precise-capturing/overcaptures-2024.fixed +++ b/tests/ui/impl-trait/precise-capturing/overcaptures-2024.fixed @@ -1,19 +1,21 @@ //@ run-rustfix -#![feature(precise_capturing)] -#![allow(unused, incomplete_features)] +#![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 implicit(x: &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 struct W; impl W { fn hello(&self, x: &i32) -> impl Sized + '_ + use<'_> { self } //~^ ERROR `impl Sized + '_` will capture more lifetimes than possibly intended in edition 2024 + //~| WARN this changes meaning in Rust 2024 } trait Higher<'a> { @@ -25,5 +27,6 @@ impl Higher<'_> for () { 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 main() {} diff --git a/tests/ui/impl-trait/precise-capturing/overcaptures-2024.rs b/tests/ui/impl-trait/precise-capturing/overcaptures-2024.rs index e4b7828d60f..18c04f9f799 100644 --- a/tests/ui/impl-trait/precise-capturing/overcaptures-2024.rs +++ b/tests/ui/impl-trait/precise-capturing/overcaptures-2024.rs @@ -1,19 +1,21 @@ //@ run-rustfix -#![feature(precise_capturing)] -#![allow(unused, incomplete_features)] +#![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 implicit(x: &i32) -> impl Sized { *x } //~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024 +//~| WARN this changes meaning in Rust 2024 struct W; impl W { fn hello(&self, x: &i32) -> impl Sized + '_ { self } //~^ ERROR `impl Sized + '_` will capture more lifetimes than possibly intended in edition 2024 + //~| WARN this changes meaning in Rust 2024 } trait Higher<'a> { @@ -25,5 +27,6 @@ impl Higher<'_> for () { 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 main() {} diff --git a/tests/ui/impl-trait/precise-capturing/overcaptures-2024.stderr b/tests/ui/impl-trait/precise-capturing/overcaptures-2024.stderr index f8bb7f099af..94dafb04d64 100644 --- a/tests/ui/impl-trait/precise-capturing/overcaptures-2024.stderr +++ b/tests/ui/impl-trait/precise-capturing/overcaptures-2024.stderr @@ -1,17 +1,19 @@ error: `impl Sized` will capture more lifetimes than possibly intended in edition 2024 - --> $DIR/overcaptures-2024.rs:7:29 + --> $DIR/overcaptures-2024.rs:6: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.rs:7:10 + --> $DIR/overcaptures-2024.rs:6: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:5:9 + --> $DIR/overcaptures-2024.rs:4:9 | LL | #![deny(impl_trait_overcaptures)] | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -26,6 +28,8 @@ error: `impl Sized` will capture more lifetimes than possibly intended in editio 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 | @@ -38,13 +42,15 @@ 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:15:33 + --> $DIR/overcaptures-2024.rs:16:33 | 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:15:24 + --> $DIR/overcaptures-2024.rs:16:24 | LL | fn hello(&self, x: &i32) -> impl Sized + '_ { self } | ^ @@ -55,13 +61,15 @@ 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:26:47 + --> $DIR/overcaptures-2024.rs:28:47 | 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:26:23 + --> $DIR/overcaptures-2024.rs:28:23 | LL | fn hrtb() -> impl for<'a> Higher<'a, Output = impl Sized> {} | ^^ diff --git a/tests/ui/impl-trait/precise-capturing/redundant.normal.stderr b/tests/ui/impl-trait/precise-capturing/redundant.normal.stderr index 44bc9f7daad..d1bcbaa33ae 100644 --- a/tests/ui/impl-trait/precise-capturing/redundant.normal.stderr +++ b/tests/ui/impl-trait/precise-capturing/redundant.normal.stderr @@ -1,5 +1,5 @@ warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant - --> $DIR/redundant.rs:7:19 + --> $DIR/redundant.rs:5:19 | LL | fn hello<'a>() -> impl Sized + use<'a> {} | ^^^^^^^^^^^^^------- @@ -9,7 +9,7 @@ LL | fn hello<'a>() -> impl Sized + use<'a> {} = note: `#[warn(impl_trait_redundant_captures)]` on by default warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant - --> $DIR/redundant.rs:12:27 + --> $DIR/redundant.rs:10:27 | LL | fn inherent(&self) -> impl Sized + use<'_> {} | ^^^^^^^^^^^^^------- diff --git a/tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr b/tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr index 9aa73353126..213888356e5 100644 --- a/tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr +++ b/tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr @@ -1,5 +1,5 @@ error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits - --> $DIR/redundant.rs:18:35 + --> $DIR/redundant.rs:16:35 | LL | fn in_trait() -> impl Sized + use<'a, Self>; | ^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | fn in_trait() -> impl Sized + use<'a, Self>; = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits - --> $DIR/redundant.rs:23:35 + --> $DIR/redundant.rs:21:35 | LL | fn in_trait() -> impl Sized + use<'a> {} | ^^^^^^^ diff --git a/tests/ui/impl-trait/precise-capturing/redundant.rs b/tests/ui/impl-trait/precise-capturing/redundant.rs index ef4f05bd7e4..4a08ffb61be 100644 --- a/tests/ui/impl-trait/precise-capturing/redundant.rs +++ b/tests/ui/impl-trait/precise-capturing/redundant.rs @@ -2,8 +2,6 @@ //@ revisions: normal rpitit //@[normal] check-pass -#![feature(precise_capturing)] - fn hello<'a>() -> impl Sized + use<'a> {} //[normal]~^ WARN all possible in-scope parameters are already captured diff --git a/tests/ui/impl-trait/precise-capturing/rpitit.rs b/tests/ui/impl-trait/precise-capturing/rpitit.rs index 4eb053573e1..feeeb1461e8 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit.rs +++ b/tests/ui/impl-trait/precise-capturing/rpitit.rs @@ -5,8 +5,6 @@ // To fix this soundly, we need to make sure that all the trait header args // remain captured, since they affect trait selection. -#![feature(precise_capturing)] - trait Foo<'a> { fn hello() -> impl PartialEq + use; } diff --git a/tests/ui/impl-trait/precise-capturing/rpitit.stderr b/tests/ui/impl-trait/precise-capturing/rpitit.stderr index 45eceef2f49..5a120df9f04 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit.stderr +++ b/tests/ui/impl-trait/precise-capturing/rpitit.stderr @@ -1,5 +1,5 @@ error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits - --> $DIR/rpitit.rs:11:36 + --> $DIR/rpitit.rs:9:36 | LL | fn hello() -> impl PartialEq + use; | ^^^^^^^^^ @@ -7,7 +7,7 @@ LL | fn hello() -> impl PartialEq + use; = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope error: `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list - --> $DIR/rpitit.rs:11:19 + --> $DIR/rpitit.rs:9:19 | LL | trait Foo<'a> { | -- this lifetime parameter is captured @@ -15,7 +15,7 @@ LL | fn hello() -> impl PartialEq + use; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime captured due to being mentioned in the bounds of the `impl Trait` error: lifetime may not live long enough - --> $DIR/rpitit.rs:15:5 + --> $DIR/rpitit.rs:13:5 | LL | fn test<'a, 'b, T: for<'r> Foo<'r>>() { | -- -- lifetime `'b` defined here @@ -30,7 +30,7 @@ LL | | ); = help: consider adding the following bound: `'a: 'b` error: lifetime may not live long enough - --> $DIR/rpitit.rs:15:5 + --> $DIR/rpitit.rs:13:5 | LL | fn test<'a, 'b, T: for<'r> Foo<'r>>() { | -- -- lifetime `'b` defined here diff --git a/tests/ui/impl-trait/precise-capturing/self-capture.rs b/tests/ui/impl-trait/precise-capturing/self-capture.rs index 07bb417f9f7..a61a7f06edc 100644 --- a/tests/ui/impl-trait/precise-capturing/self-capture.rs +++ b/tests/ui/impl-trait/precise-capturing/self-capture.rs @@ -1,5 +1,3 @@ -#![feature(precise_capturing)] - trait Foo { fn bar<'a>() -> impl Sized + use; //~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits diff --git a/tests/ui/impl-trait/precise-capturing/self-capture.stderr b/tests/ui/impl-trait/precise-capturing/self-capture.stderr index 351de86dd5f..c1974600f30 100644 --- a/tests/ui/impl-trait/precise-capturing/self-capture.stderr +++ b/tests/ui/impl-trait/precise-capturing/self-capture.stderr @@ -1,5 +1,5 @@ error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits - --> $DIR/self-capture.rs:4:34 + --> $DIR/self-capture.rs:2:34 | LL | fn bar<'a>() -> impl Sized + use; | ^^^^^^^^^ diff --git a/tests/ui/impl-trait/recursive-ice-101862.stderr b/tests/ui/impl-trait/recursive-ice-101862.stderr index f4148720c33..970373422e8 100644 --- a/tests/ui/impl-trait/recursive-ice-101862.stderr +++ b/tests/ui/impl-trait/recursive-ice-101862.stderr @@ -11,13 +11,13 @@ LL | vec![].append(&mut ice(x.as_ref())); = note: `#[warn(unconditional_recursion)]` on by default error[E0792]: expected generic type parameter, found `&str` - --> $DIR/recursive-ice-101862.rs:6:5 + --> $DIR/recursive-ice-101862.rs:6:19 | LL | pub fn ice(x: impl AsRef) -> impl IntoIterator { | --------------- this generic parameter must be used with a generic type parameter LL | LL | vec![].append(&mut ice(x.as_ref())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/impl-trait/region-escape-via-bound.stderr b/tests/ui/impl-trait/region-escape-via-bound.stderr index 43f0eeeb558..0518231cfe9 100644 --- a/tests/ui/impl-trait/region-escape-via-bound.stderr +++ b/tests/ui/impl-trait/region-escape-via-bound.stderr @@ -9,10 +9,10 @@ LL | fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y> LL | x | ^ | -help: to declare that `impl Trait<'y>` captures `'x`, you can add an explicit `'x` lifetime bound +help: add a `use<...>` bound to explicitly capture `'x` | -LL | fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y> + 'x - | ++++ +LL | fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y> + use<'y, 'x> + | +++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/static-return-lifetime-infered.stderr b/tests/ui/impl-trait/static-return-lifetime-infered.stderr index 4be244068d2..21e3187d019 100644 --- a/tests/ui/impl-trait/static-return-lifetime-infered.stderr +++ b/tests/ui/impl-trait/static-return-lifetime-infered.stderr @@ -8,10 +8,10 @@ LL | fn iter_values_anon(&self) -> impl Iterator { LL | self.x.iter().map(|a| a.0) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: to declare that `impl Iterator` captures `'_`, you can add an explicit `'_` lifetime bound +help: add a `use<...>` bound to explicitly capture `'_` | -LL | fn iter_values_anon(&self) -> impl Iterator + '_ { - | ++++ +LL | fn iter_values_anon(&self) -> impl Iterator + use<'_> { + | +++++++++ error[E0700]: hidden type for `impl Iterator` captures lifetime that does not appear in bounds --> $DIR/static-return-lifetime-infered.rs:11:9 @@ -23,10 +23,10 @@ LL | fn iter_values<'a>(&'a self) -> impl Iterator { LL | self.x.iter().map(|a| a.0) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: to declare that `impl Iterator` captures `'a`, you can add an explicit `'a` lifetime bound +help: add a `use<...>` bound to explicitly capture `'a` | -LL | fn iter_values<'a>(&'a self) -> impl Iterator + 'a { - | ++++ +LL | fn iter_values<'a>(&'a self) -> impl Iterator + use<'a> { + | +++++++++ error: aborting due to 2 previous errors diff --git a/tests/ui/impl-trait/variance.e2024.stderr b/tests/ui/impl-trait/variance.e2024.stderr index 17245055744..011ab3259c4 100644 --- a/tests/ui/impl-trait/variance.e2024.stderr +++ b/tests/ui/impl-trait/variance.e2024.stderr @@ -1,22 +1,22 @@ -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:14:36 | LL | fn not_captured_early<'a: 'a>() -> impl Sized {} | ^^^^^^^^^^ -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:19:32 | LL | fn captured_early<'a: 'a>() -> impl Sized + Captures<'a> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [o] +error: ['a: o] --> $DIR/variance.rs:21:40 | LL | fn not_captured_late<'a>(_: &'a ()) -> impl Sized {} | ^^^^^^^^^^ -error: [o] +error: ['a: o] --> $DIR/variance.rs:26:36 | LL | fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} diff --git a/tests/ui/impl-trait/variance.new.stderr b/tests/ui/impl-trait/variance.new.stderr index 17245055744..011ab3259c4 100644 --- a/tests/ui/impl-trait/variance.new.stderr +++ b/tests/ui/impl-trait/variance.new.stderr @@ -1,22 +1,22 @@ -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:14:36 | LL | fn not_captured_early<'a: 'a>() -> impl Sized {} | ^^^^^^^^^^ -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:19:32 | LL | fn captured_early<'a: 'a>() -> impl Sized + Captures<'a> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [o] +error: ['a: o] --> $DIR/variance.rs:21:40 | LL | fn not_captured_late<'a>(_: &'a ()) -> impl Sized {} | ^^^^^^^^^^ -error: [o] +error: ['a: o] --> $DIR/variance.rs:26:36 | LL | fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} diff --git a/tests/ui/impl-trait/variance.old.stderr b/tests/ui/impl-trait/variance.old.stderr index 9410b54b491..ac3bcd2723f 100644 --- a/tests/ui/impl-trait/variance.old.stderr +++ b/tests/ui/impl-trait/variance.old.stderr @@ -1,10 +1,10 @@ -error: [*] +error: ['a: *] --> $DIR/variance.rs:14:36 | LL | fn not_captured_early<'a: 'a>() -> impl Sized {} | ^^^^^^^^^^ -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:19:32 | LL | fn captured_early<'a: 'a>() -> impl Sized + Captures<'a> {} @@ -16,7 +16,7 @@ error: [] LL | fn not_captured_late<'a>(_: &'a ()) -> impl Sized {} | ^^^^^^^^^^ -error: [o] +error: ['a: o] --> $DIR/variance.rs:26:36 | LL | fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} diff --git a/tests/ui/impl-trait/variance.rs b/tests/ui/impl-trait/variance.rs index 72b4a831bad..43f7207a904 100644 --- a/tests/ui/impl-trait/variance.rs +++ b/tests/ui/impl-trait/variance.rs @@ -12,17 +12,17 @@ trait Captures<'a> {} impl Captures<'_> for T {} fn not_captured_early<'a: 'a>() -> impl Sized {} -//[old]~^ [*] -//[new]~^^ [*, o] -//[e2024]~^^^ [*, o] +//[old]~^ ['a: *] +//[new]~^^ ['a: *, 'a: o] +//[e2024]~^^^ ['a: *, 'a: o] -fn captured_early<'a: 'a>() -> impl Sized + Captures<'a> {} //~ [*, o] +fn captured_early<'a: 'a>() -> impl Sized + Captures<'a> {} //~ ['a: *, 'a: o] fn not_captured_late<'a>(_: &'a ()) -> impl Sized {} //[old]~^ [] -//[new]~^^ [o] -//[e2024]~^^^ [o] +//[new]~^^ ['a: o] +//[e2024]~^^^ ['a: o] -fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} //~ [o] +fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} //~ ['a: o] fn main() {} diff --git a/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr b/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr index c8d1614a7f3..f498257e12f 100644 --- a/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr +++ b/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr @@ -5,9 +5,9 @@ LL | fn get<'s>(s: &'s str, _: <&'static &'s () as Project>::Ty) -> &'static | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first, the lifetime cannot outlive the lifetime `'s` as defined here... - --> $DIR/impl-implied-bounds-compatibility-unnormalized.rs:11:12 + --> $DIR/impl-implied-bounds-compatibility-unnormalized.rs:8:12 | -LL | fn get<'s>(s: &'s str, _: <&'static &'s () as Project>::Ty) -> &'static str { +LL | fn get<'s>(s: &'s str, _: ()) -> &'static str; | ^^ note: ...so that the method type is compatible with trait --> $DIR/impl-implied-bounds-compatibility-unnormalized.rs:11:5 diff --git a/tests/ui/imports/auxiliary/issue-85992-extern-2.rs b/tests/ui/imports/auxiliary/empty.rs similarity index 100% rename from tests/ui/imports/auxiliary/issue-85992-extern-2.rs rename to tests/ui/imports/auxiliary/empty.rs diff --git a/tests/ui/imports/auxiliary/issue-85992-extern-1.rs b/tests/ui/imports/auxiliary/issue-85992-extern.rs similarity index 54% rename from tests/ui/imports/auxiliary/issue-85992-extern-1.rs rename to tests/ui/imports/auxiliary/issue-85992-extern.rs index a2d0e206065..076d6045190 100644 --- a/tests/ui/imports/auxiliary/issue-85992-extern-1.rs +++ b/tests/ui/imports/auxiliary/issue-85992-extern.rs @@ -1,6 +1,6 @@ #[macro_export] macro_rules! m { () => { - use issue_85992_extern_2::Outcome; + use empty::Outcome; } } diff --git a/tests/ui/imports/issue-85992.rs b/tests/ui/imports/issue-85992.rs index 321c3a9218d..38cf0384501 100644 --- a/tests/ui/imports/issue-85992.rs +++ b/tests/ui/imports/issue-85992.rs @@ -1,11 +1,11 @@ //@ edition: 2021 -//@ compile-flags: --extern issue_85992_extern_1 --extern issue_85992_extern_2 -//@ aux-build: issue-85992-extern-1.rs -//@ aux-build: issue-85992-extern-2.rs +//@ compile-flags: --extern issue_85992_extern --extern empty +//@ aux-build: issue-85992-extern.rs +//@ aux-build: empty.rs -issue_85992_extern_1::m!(); +issue_85992_extern::m!(); -use crate::issue_85992_extern_2; -//~^ ERROR unresolved import `crate::issue_85992_extern_2` +use crate::empty; +//~^ ERROR unresolved import `crate::empty` fn main() {} diff --git a/tests/ui/imports/issue-85992.stderr b/tests/ui/imports/issue-85992.stderr index 6c75b45d926..490b2d4d88b 100644 --- a/tests/ui/imports/issue-85992.stderr +++ b/tests/ui/imports/issue-85992.stderr @@ -1,8 +1,8 @@ -error[E0432]: unresolved import `crate::issue_85992_extern_2` +error[E0432]: unresolved import `crate::empty` --> $DIR/issue-85992.rs:8:5 | -LL | use crate::issue_85992_extern_2; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `issue_85992_extern_2` in the root +LL | use crate::empty; + | ^^^^^^^^^^^^ no `empty` in the root error: aborting due to 1 previous error diff --git a/tests/ui/imports/multiple-extern-by-macro-for-buitlin.rs b/tests/ui/imports/multiple-extern-by-macro-for-buitlin.rs new file mode 100644 index 00000000000..f0e5e4b4325 --- /dev/null +++ b/tests/ui/imports/multiple-extern-by-macro-for-buitlin.rs @@ -0,0 +1,18 @@ +//@ edition: 2021 + +// issue#128813 + +extern crate core; + +macro_rules! m { + () => { + extern crate std as core; + //~^ ERROR: the name `core` is defined multiple times + }; +} + +m!(); + +fn main() { + use ::core; +} diff --git a/tests/ui/imports/multiple-extern-by-macro-for-buitlin.stderr b/tests/ui/imports/multiple-extern-by-macro-for-buitlin.stderr new file mode 100644 index 00000000000..a84a6c42aa8 --- /dev/null +++ b/tests/ui/imports/multiple-extern-by-macro-for-buitlin.stderr @@ -0,0 +1,22 @@ +error[E0259]: the name `core` is defined multiple times + --> $DIR/multiple-extern-by-macro-for-buitlin.rs:9:9 + | +LL | extern crate core; + | ------------------ previous import of the extern crate `core` here +... +LL | extern crate std as core; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ `core` reimported here +... +LL | m!(); + | ---- in this macro invocation + | + = note: `core` must be defined only once in the type namespace of this module + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you can use `as` to change the binding name of the import + | +LL | extern crate std as other_core; + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0259`. diff --git a/tests/ui/imports/multiple-extern-by-macro-for-custom.rs b/tests/ui/imports/multiple-extern-by-macro-for-custom.rs new file mode 100644 index 00000000000..6bf544566e3 --- /dev/null +++ b/tests/ui/imports/multiple-extern-by-macro-for-custom.rs @@ -0,0 +1,19 @@ +//@ edition: 2021 +//@ aux-build: empty.rs + +// issue#128813 + +extern crate empty; + +macro_rules! m { + () => { + extern crate std as empty; + //~^ ERROR: the name `empty` is defined multiple times + }; +} + +m!(); + +fn main() { + use ::empty; +} diff --git a/tests/ui/imports/multiple-extern-by-macro-for-custom.stderr b/tests/ui/imports/multiple-extern-by-macro-for-custom.stderr new file mode 100644 index 00000000000..556d75a4dbb --- /dev/null +++ b/tests/ui/imports/multiple-extern-by-macro-for-custom.stderr @@ -0,0 +1,22 @@ +error[E0259]: the name `empty` is defined multiple times + --> $DIR/multiple-extern-by-macro-for-custom.rs:10:9 + | +LL | extern crate empty; + | ------------------- previous import of the extern crate `empty` here +... +LL | extern crate std as empty; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `empty` reimported here +... +LL | m!(); + | ---- in this macro invocation + | + = note: `empty` must be defined only once in the type namespace of this module + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you can use `as` to change the binding name of the import + | +LL | extern crate std as other_empty; + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0259`. diff --git a/tests/ui/imports/multiple-extern-by-macro-for-inexist.rs b/tests/ui/imports/multiple-extern-by-macro-for-inexist.rs new file mode 100644 index 00000000000..c23f275b9ff --- /dev/null +++ b/tests/ui/imports/multiple-extern-by-macro-for-inexist.rs @@ -0,0 +1,19 @@ +//@ edition: 2021 + +// issue#128813 + +extern crate non_existent; +//~^ ERROR: can't find crate for `non_existent` + +macro_rules! m { + () => { + extern crate std as non_existent; + //~^ ERROR: the name `non_existent` is defined multiple times + }; +} + +m!(); + +fn main() { + use ::non_existent; +} diff --git a/tests/ui/imports/multiple-extern-by-macro-for-inexist.stderr b/tests/ui/imports/multiple-extern-by-macro-for-inexist.stderr new file mode 100644 index 00000000000..ec34489f232 --- /dev/null +++ b/tests/ui/imports/multiple-extern-by-macro-for-inexist.stderr @@ -0,0 +1,29 @@ +error[E0463]: can't find crate for `non_existent` + --> $DIR/multiple-extern-by-macro-for-inexist.rs:5:1 + | +LL | extern crate non_existent; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ can't find crate + +error[E0259]: the name `non_existent` is defined multiple times + --> $DIR/multiple-extern-by-macro-for-inexist.rs:10:9 + | +LL | extern crate non_existent; + | -------------------------- previous import of the extern crate `non_existent` here +... +LL | extern crate std as non_existent; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `non_existent` reimported here +... +LL | m!(); + | ---- in this macro invocation + | + = note: `non_existent` must be defined only once in the type namespace of this module + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you can use `as` to change the binding name of the import + | +LL | extern crate std as other_non_existent; + | + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0259, E0463. +For more information about an error, try `rustc --explain E0259`. diff --git a/tests/ui/imports/multiple-extern-by-macro-for-underscore.rs b/tests/ui/imports/multiple-extern-by-macro-for-underscore.rs new file mode 100644 index 00000000000..ddf735d8947 --- /dev/null +++ b/tests/ui/imports/multiple-extern-by-macro-for-underscore.rs @@ -0,0 +1,18 @@ +//@ edition: 2021 + +// issue#128813 + +extern crate core as _; + +macro_rules! m { + () => { + extern crate std as _; + }; +} + +m!(); + +fn main() { + use ::_; + //~^ ERROR: expected identifier, found reserved identifier `_` +} diff --git a/tests/ui/imports/multiple-extern-by-macro-for-underscore.stderr b/tests/ui/imports/multiple-extern-by-macro-for-underscore.stderr new file mode 100644 index 00000000000..1da5aa87070 --- /dev/null +++ b/tests/ui/imports/multiple-extern-by-macro-for-underscore.stderr @@ -0,0 +1,8 @@ +error: expected identifier, found reserved identifier `_` + --> $DIR/multiple-extern-by-macro-for-underscore.rs:16:11 + | +LL | use ::_; + | ^ expected identifier, found reserved identifier + +error: aborting due to 1 previous error + diff --git a/tests/ui/inference/detect-old-time-version-format_description-parse.rs b/tests/ui/inference/detect-old-time-version-format_description-parse.rs new file mode 100644 index 00000000000..453a795e768 --- /dev/null +++ b/tests/ui/inference/detect-old-time-version-format_description-parse.rs @@ -0,0 +1,8 @@ +#![crate_name = "time"] + +fn main() { + let items = Box::new(vec![]); //~ ERROR E0282 + //~^ NOTE type must be known at this point + //~| NOTE this is an inference error on crate `time` caused by an API change in Rust 1.80.0; update `time` to version `>=0.3.35` + items.into(); +} diff --git a/tests/ui/inference/detect-old-time-version-format_description-parse.stderr b/tests/ui/inference/detect-old-time-version-format_description-parse.stderr new file mode 100644 index 00000000000..2949a5dcfec --- /dev/null +++ b/tests/ui/inference/detect-old-time-version-format_description-parse.stderr @@ -0,0 +1,11 @@ +error[E0282]: type annotations needed for `Box>` + --> $DIR/detect-old-time-version-format_description-parse.rs:4:9 + | +LL | let items = Box::new(vec![]); + | ^^^^^ ---------------- type must be known at this point + | + = note: this is an inference error on crate `time` caused by an API change in Rust 1.80.0; update `time` to version `>=0.3.35` by calling `cargo update` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/internal/internal-unstable-const.rs b/tests/ui/internal/internal-unstable-const.rs deleted file mode 100644 index 4ec2426dfee..00000000000 --- a/tests/ui/internal/internal-unstable-const.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Don't allow unstable features in stable functions without `allow_internal_unstable`. - -#![stable(feature = "rust1", since = "1.0.0")] -#![feature(staged_api)] -#![feature(const_fn_floating_point_arithmetic)] - -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_stable(feature = "rust1", since = "1.0.0")] -pub const fn foo() -> f32 { - 1.0 + 1.0 //~ ERROR const-stable function cannot use `#[feature(const_fn_floating_point_arithmetic)]` -} - -fn main() {} diff --git a/tests/ui/internal/internal-unstable-const.stderr b/tests/ui/internal/internal-unstable-const.stderr deleted file mode 100644 index ed9196d2b63..00000000000 --- a/tests/ui/internal/internal-unstable-const.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error: const-stable function cannot use `#[feature(const_fn_floating_point_arithmetic)]` - --> $DIR/internal-unstable-const.rs:10:5 - | -LL | 1.0 + 1.0 - | ^^^^^^^^^ - | -help: if it is not part of the public API, make this function unstably const - | -LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | pub const fn foo() -> f32 { - | -help: otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks - | -LL + #[rustc_allow_const_fn_unstable(const_fn_floating_point_arithmetic)] -LL | pub const fn foo() -> f32 { - | - -error: aborting due to 1 previous error - diff --git a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs index ab46fd796c5..99f98c3f27a 100644 --- a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs +++ b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs @@ -13,5 +13,13 @@ const RAW_EQ_PTR: bool = unsafe { //~| unable to turn pointer into integer }; +const RAW_EQ_NOT_ALIGNED: bool = unsafe { + let arr = [0u8; 4]; + let aref = &*arr.as_ptr().cast::(); + std::intrinsics::raw_eq(aref, aref) +//~^ ERROR evaluation of constant value failed +//~| alignment +}; + pub fn main() { } diff --git a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr index af16c2bc64a..bedfc8283ea 100644 --- a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr +++ b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr @@ -13,6 +13,12 @@ LL | std::intrinsics::raw_eq(&(&0), &(&1)) = help: this code performed an operation that depends on the underlying bytes representing a pointer = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported -error: aborting due to 2 previous errors +error[E0080]: evaluation of constant value failed + --> $DIR/intrinsic-raw_eq-const-bad.rs:19:5 + | +LL | std::intrinsics::raw_eq(aref, aref) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ accessing memory with alignment 1, but alignment 4 is required + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/intrinsics/reify-intrinsic.stderr b/tests/ui/intrinsics/reify-intrinsic.stderr index 0119a1a6650..21b7bf4e1cb 100644 --- a/tests/ui/intrinsics/reify-intrinsic.stderr +++ b/tests/ui/intrinsics/reify-intrinsic.stderr @@ -7,9 +7,9 @@ LL | let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::tr | expected due to this | = note: expected fn pointer `unsafe extern "rust-intrinsic" fn(isize) -> usize` - found fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}` + found fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}` -error[E0606]: casting `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}` as `unsafe extern "rust-intrinsic" fn(isize) -> usize` is invalid +error[E0606]: casting `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}` as `unsafe extern "rust-intrinsic" fn(isize) -> usize` is invalid --> $DIR/reify-intrinsic.rs:11:13 | LL | let _ = std::mem::transmute as unsafe extern "rust-intrinsic" fn(isize) -> usize; diff --git a/tests/ui/intrinsics/safe-intrinsic-mismatch.effects.stderr b/tests/ui/intrinsics/safe-intrinsic-mismatch.effects.stderr index d9a4960feec..55983a445a4 100644 --- a/tests/ui/intrinsics/safe-intrinsic-mismatch.effects.stderr +++ b/tests/ui/intrinsics/safe-intrinsic-mismatch.effects.stderr @@ -7,13 +7,13 @@ error: intrinsic safety mismatch between list of intrinsics within the compiler --> $DIR/safe-intrinsic-mismatch.rs:11:5 | LL | fn size_of() -> usize; - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `size_of` --> $DIR/safe-intrinsic-mismatch.rs:11:5 | LL | fn size_of() -> usize; - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/intrinsics/safe-intrinsic-mismatch.stock.stderr b/tests/ui/intrinsics/safe-intrinsic-mismatch.stock.stderr index 6864c0f36de..c59e357b275 100644 --- a/tests/ui/intrinsics/safe-intrinsic-mismatch.stock.stderr +++ b/tests/ui/intrinsics/safe-intrinsic-mismatch.stock.stderr @@ -2,13 +2,13 @@ error: intrinsic safety mismatch between list of intrinsics within the compiler --> $DIR/safe-intrinsic-mismatch.rs:11:5 | LL | fn size_of() -> usize; - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `size_of` --> $DIR/safe-intrinsic-mismatch.rs:11:5 | LL | fn size_of() -> usize; - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/issues/issue-16725.stderr b/tests/ui/issues/issue-16725.stderr index a4a406b3d4b..dcb7d58b0f9 100644 --- a/tests/ui/issues/issue-16725.stderr +++ b/tests/ui/issues/issue-16725.stderr @@ -8,7 +8,7 @@ note: the function `bar` is defined here --> $DIR/auxiliary/issue-16725.rs:2:5 | LL | fn bar(); - | ^^^^^^^^ + | ^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-17651.stderr b/tests/ui/issues/issue-17651.stderr index 0c95a3c0c40..9519507320d 100644 --- a/tests/ui/issues/issue-17651.stderr +++ b/tests/ui/issues/issue-17651.stderr @@ -9,6 +9,11 @@ LL | (|| Box::new(*(&[0][..])))(); = help: the trait `Sized` is not implemented for `[{integer}]` note: required by a bound in `Box::::new` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - (|| Box::new(*(&[0][..])))(); +LL + (|| Box::new((&[0][..])))(); + | error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-20831-debruijn.stderr b/tests/ui/issues/issue-20831-debruijn.stderr index 60721f001b7..fe310998f09 100644 --- a/tests/ui/issues/issue-20831-debruijn.stderr +++ b/tests/ui/issues/issue-20831-debruijn.stderr @@ -5,10 +5,10 @@ LL | fn subscribe(&mut self, t : Box $DIR/issue-20831-debruijn.rs:28:18 + --> $DIR/issue-20831-debruijn.rs:28:67 | LL | fn subscribe(&mut self, t : Box::Output> + 'a>) { - | ^ + | ^^^^^^^^^ note: ...but the lifetime must also be valid for the lifetime `'a` as defined here... --> $DIR/issue-20831-debruijn.rs:26:6 | diff --git a/tests/ui/issues/issue-37884.stderr b/tests/ui/issues/issue-37884.stderr index b7c0095d682..17037d2180d 100644 --- a/tests/ui/issues/issue-37884.stderr +++ b/tests/ui/issues/issue-37884.stderr @@ -7,10 +7,7 @@ LL | fn next(&'a mut self) -> Option = note: expected signature `fn(&mut RepeatMut<'_, _>) -> Option<_>` found signature `fn(&'a mut RepeatMut<'_, _>) -> Option<_>` note: the anonymous lifetime as defined here... - --> $DIR/issue-37884.rs:6:5 - | -LL | fn next(&'a mut self) -> Option - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL note: ...does not necessarily outlive the lifetime `'a` as defined here --> $DIR/issue-37884.rs:3:6 | diff --git a/tests/ui/issues/issue-47094.stderr b/tests/ui/issues/issue-47094.stderr index 970e3184710..1c6693403b8 100644 --- a/tests/ui/issues/issue-47094.stderr +++ b/tests/ui/issues/issue-47094.stderr @@ -23,3 +23,28 @@ LL | #[repr(u8)] error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0566`. +Future incompatibility report: Future breakage diagnostic: +error[E0566]: conflicting representation hints + --> $DIR/issue-47094.rs:1:8 + | +LL | #[repr(C, u8)] + | ^ ^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #68585 + = note: `#[deny(conflicting_repr_hints)]` on by default + +Future breakage diagnostic: +error[E0566]: conflicting representation hints + --> $DIR/issue-47094.rs:8:8 + | +LL | #[repr(C)] + | ^ +LL | +LL | #[repr(u8)] + | ^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #68585 + = note: `#[deny(conflicting_repr_hints)]` on by default + diff --git a/tests/ui/lifetimes/issue-105227.fixed b/tests/ui/lifetimes/issue-105227.fixed deleted file mode 100644 index ef64e1e6541..00000000000 --- a/tests/ui/lifetimes/issue-105227.fixed +++ /dev/null @@ -1,26 +0,0 @@ -// Regression test for issue #105227. - -//@ run-rustfix -#![allow(warnings)] -fn chars0<'a>(v :(&'a str, &'a str)) -> impl Iterator + 'a { -//~^ HELP to declare that `impl Iterator` captures `'_`, you can introduce a named lifetime parameter `'a` - v.0.chars().chain(v.1.chars()) - //~^ ERROR hidden type for `impl Iterator` captures lifetime that does not appear in bounds -} - -fn chars1<'a>(v0 : &'a str, v1 : &'a str) -> impl Iterator + 'a { -//~^ HELP to declare that `impl Iterator` captures `'_`, you can introduce a named lifetime parameter `'a` - v0.chars().chain(v1.chars()) - //~^ ERROR hidden type for `impl Iterator` captures lifetime that does not appear in bound -} - -fn chars2<'b>(v0 : &'b str, v1 : &'b str, v2 : &'b str) -> -//~^ HELP to declare that `impl Iterator` captures `'_`, you can use the named lifetime parameter `'b` - (impl Iterator + 'b , &'b str) -{ - (v0.chars().chain(v1.chars()), v2) - //~^ ERROR hidden type for `impl Iterator` captures lifetime that does not appear in bound -} - -fn main() { -} diff --git a/tests/ui/lifetimes/issue-105227.rs b/tests/ui/lifetimes/issue-105227.rs index f37765ffafa..8a0a49e8f0c 100644 --- a/tests/ui/lifetimes/issue-105227.rs +++ b/tests/ui/lifetimes/issue-105227.rs @@ -1,23 +1,23 @@ // Regression test for issue #105227. -//@ run-rustfix -#![allow(warnings)] +// FIXME(precise_capturing): Add rustfix here after dealing w/ elided lifetimes + +#![allow(unused)] + fn chars0(v :(& str, &str)) -> impl Iterator { -//~^ HELP to declare that `impl Iterator` captures `'_`, you can introduce a named lifetime parameter `'a` + //~^ HELP add a `use<...>` bound v.0.chars().chain(v.1.chars()) //~^ ERROR hidden type for `impl Iterator` captures lifetime that does not appear in bounds } fn chars1(v0 : & str, v1 : &str) -> impl Iterator { -//~^ HELP to declare that `impl Iterator` captures `'_`, you can introduce a named lifetime parameter `'a` + //~^ HELP add a `use<...>` bound v0.chars().chain(v1.chars()) //~^ ERROR hidden type for `impl Iterator` captures lifetime that does not appear in bound } -fn chars2<'b>(v0 : &str, v1 : &'_ str, v2 : &'b str) -> -//~^ HELP to declare that `impl Iterator` captures `'_`, you can use the named lifetime parameter `'b` - (impl Iterator, &'b str) -{ +fn chars2<'b>(v0 : &str, v1 : &'_ str, v2 : &'b str) -> (impl Iterator, &'b str) { + //~^ HELP add a `use<...>` bound (v0.chars().chain(v1.chars()), v2) //~^ ERROR hidden type for `impl Iterator` captures lifetime that does not appear in bound } diff --git a/tests/ui/lifetimes/issue-105227.stderr b/tests/ui/lifetimes/issue-105227.stderr index b514db461b4..35c05f28854 100644 --- a/tests/ui/lifetimes/issue-105227.stderr +++ b/tests/ui/lifetimes/issue-105227.stderr @@ -1,5 +1,5 @@ error[E0700]: hidden type for `impl Iterator` captures lifetime that does not appear in bounds - --> $DIR/issue-105227.rs:7:5 + --> $DIR/issue-105227.rs:9:5 | LL | fn chars0(v :(& str, &str)) -> impl Iterator { | ----- -------------------------- opaque type defined here @@ -9,13 +9,13 @@ LL | LL | v.0.chars().chain(v.1.chars()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: to declare that `impl Iterator` captures `'_`, you can introduce a named lifetime parameter `'a` +help: add a `use<...>` bound to explicitly capture `'_` | -LL | fn chars0<'a>(v :(&'a str, &'a str)) -> impl Iterator + 'a { - | ++++ ++ ++ ++++ +LL | fn chars0(v :(& str, &str)) -> impl Iterator + use<'_> { + | +++++++++ error[E0700]: hidden type for `impl Iterator` captures lifetime that does not appear in bounds - --> $DIR/issue-105227.rs:13:5 + --> $DIR/issue-105227.rs:15:5 | LL | fn chars1(v0 : & str, v1 : &str) -> impl Iterator { | ----- -------------------------- opaque type defined here @@ -25,29 +25,26 @@ LL | LL | v0.chars().chain(v1.chars()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: to declare that `impl Iterator` captures `'_`, you can introduce a named lifetime parameter `'a` +help: add a `use<...>` bound to explicitly capture `'_` | -LL | fn chars1<'a>(v0 : &'a str, v1 : &'a str) -> impl Iterator + 'a { - | ++++ ++ ++ ++++ +LL | fn chars1(v0 : & str, v1 : &str) -> impl Iterator + use<'_> { + | +++++++++ error[E0700]: hidden type for `impl Iterator` captures lifetime that does not appear in bounds --> $DIR/issue-105227.rs:21:5 | -LL | fn chars2<'b>(v0 : &str, v1 : &'_ str, v2 : &'b str) -> - | ---- hidden type `std::iter::Chain, Chars<'_>>` captures the anonymous lifetime defined here +LL | fn chars2<'b>(v0 : &str, v1 : &'_ str, v2 : &'b str) -> (impl Iterator, &'b str) { + | ---- -------------------------- opaque type defined here + | | + | hidden type `std::iter::Chain, Chars<'_>>` captures the anonymous lifetime defined here LL | -LL | (impl Iterator, &'b str) - | -------------------------- opaque type defined here -LL | { LL | (v0.chars().chain(v1.chars()), v2) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: to declare that `impl Iterator` captures `'_`, you can use the named lifetime parameter `'b` - | -LL ~ fn chars2<'b>(v0 : &'b str, v1 : &'b str, v2 : &'b str) -> -LL | -LL ~ (impl Iterator + 'b , &'b str) +help: add a `use<...>` bound to explicitly capture `'_` | +LL | fn chars2<'b>(v0 : &str, v1 : &'_ str, v2 : &'b str) -> (impl Iterator + use<'_>, &'b str) { + | +++++++++ error: aborting due to 3 previous errors diff --git a/tests/ui/lifetimes/issue-95023.rs b/tests/ui/lifetimes/issue-95023.rs index bcacd01474f..8461d92fc33 100644 --- a/tests/ui/lifetimes/issue-95023.rs +++ b/tests/ui/lifetimes/issue-95023.rs @@ -2,12 +2,13 @@ struct ErrorKind; struct Error(ErrorKind); impl Fn(&isize) for Error { //~^ ERROR manual implementations of `Fn` are experimental [E0183] - //~^^ ERROR associated item constraints are not allowed here [E0229] + //~| ERROR associated item constraints are not allowed here [E0229] //~| ERROR not all trait items implemented //~| ERROR expected a `FnMut(&isize)` closure, found `Error` fn foo(&self) -> Self::B<{ N }>; //~^ ERROR associated function in `impl` without body - //~^^ ERROR method `foo` is not a member of trait `Fn` [E0407] - //~^^^ ERROR associated type `B` not found for `Self` [E0220] + //~| ERROR method `foo` is not a member of trait `Fn` [E0407] + //~| ERROR associated type `B` not found for `Self` [E0220] + //~| ERROR: associated type `B` not found for `Self` } fn main() {} diff --git a/tests/ui/lifetimes/issue-95023.stderr b/tests/ui/lifetimes/issue-95023.stderr index cbc0eeebee1..310dee51406 100644 --- a/tests/ui/lifetimes/issue-95023.stderr +++ b/tests/ui/lifetimes/issue-95023.stderr @@ -56,7 +56,15 @@ error[E0220]: associated type `B` not found for `Self` LL | fn foo(&self) -> Self::B<{ N }>; | ^ help: `Self` has the following associated type: `Output` -error: aborting due to 7 previous errors +error[E0220]: associated type `B` not found for `Self` + --> $DIR/issue-95023.rs:8:44 + | +LL | fn foo(&self) -> Self::B<{ N }>; + | ^ help: `Self` has the following associated type: `Output` + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 8 previous errors Some errors have detailed explanations: E0046, E0183, E0220, E0229, E0277, E0407. For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/lint/clashing-extern-fn.stderr b/tests/ui/lint/clashing-extern-fn.stderr index 43c8cdead9f..f75ff6d05a1 100644 --- a/tests/ui/lint/clashing-extern-fn.stderr +++ b/tests/ui/lint/clashing-extern-fn.stderr @@ -21,10 +21,10 @@ warning: `clash` redeclared with a different signature --> $DIR/clashing-extern-fn.rs:14:13 | LL | fn clash(x: u8); - | --------------- `clash` previously declared here + | ---------------- `clash` previously declared here ... LL | fn clash(x: u64); - | ^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | ^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn(u8)` found `unsafe extern "C" fn(u64)` @@ -41,7 +41,7 @@ LL | #[link_name = "extern_link_name"] | --------------------------------- `extern_link_name` previously declared here ... LL | fn extern_link_name(x: u32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn(i16)` found `unsafe extern "C" fn(u32)` @@ -50,7 +50,7 @@ warning: `some_other_extern_link_name` redeclares `some_other_new_name` with a d --> $DIR/clashing-extern-fn.rs:55:9 | LL | fn some_other_new_name(x: i16); - | ------------------------------ `some_other_new_name` previously declared here + | ------------------------------- `some_other_new_name` previously declared here ... LL | #[link_name = "some_other_new_name"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration @@ -74,10 +74,10 @@ warning: `different_mod` redeclared with a different signature --> $DIR/clashing-extern-fn.rs:72:9 | LL | fn different_mod(x: u8); - | ----------------------- `different_mod` previously declared here + | ------------------------ `different_mod` previously declared here ... LL | fn different_mod(x: u64); - | ^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | ^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn(u8)` found `unsafe extern "C" fn(u64)` @@ -86,10 +86,10 @@ warning: `variadic_decl` redeclared with a different signature --> $DIR/clashing-extern-fn.rs:82:9 | LL | fn variadic_decl(x: u8, ...); - | ---------------------------- `variadic_decl` previously declared here + | ----------------------------- `variadic_decl` previously declared here ... LL | fn variadic_decl(x: u8); - | ^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | ^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn(u8, ...)` found `unsafe extern "C" fn(u8)` @@ -98,10 +98,10 @@ warning: `weigh_banana` redeclared with a different signature --> $DIR/clashing-extern-fn.rs:142:13 | LL | fn weigh_banana(count: *const Banana) -> u64; - | -------------------------------------------- `weigh_banana` previously declared here + | --------------------------------------------- `weigh_banana` previously declared here ... LL | fn weigh_banana(count: *const Banana) -> u64; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn(*const one::Banana) -> u64` found `unsafe extern "C" fn(*const three::Banana) -> u64` @@ -110,10 +110,10 @@ warning: `draw_point` redeclared with a different signature --> $DIR/clashing-extern-fn.rs:171:13 | LL | fn draw_point(p: Point); - | ----------------------- `draw_point` previously declared here + | ------------------------ `draw_point` previously declared here ... LL | fn draw_point(p: Point); - | ^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | ^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn(sameish_members::a::Point)` found `unsafe extern "C" fn(sameish_members::b::Point)` @@ -122,10 +122,10 @@ warning: `origin` redeclared with a different signature --> $DIR/clashing-extern-fn.rs:197:13 | LL | fn origin() -> Point3; - | --------------------- `origin` previously declared here + | ---------------------- `origin` previously declared here ... LL | fn origin() -> Point3; - | ^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | ^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn() -> same_sized_members_clash::a::Point3` found `unsafe extern "C" fn() -> same_sized_members_clash::b::Point3` @@ -134,10 +134,10 @@ warning: `transparent_incorrect` redeclared with a different signature --> $DIR/clashing-extern-fn.rs:220:13 | LL | fn transparent_incorrect() -> T; - | ------------------------------- `transparent_incorrect` previously declared here + | -------------------------------- `transparent_incorrect` previously declared here ... LL | fn transparent_incorrect() -> isize; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn() -> T` found `unsafe extern "C" fn() -> isize` @@ -146,10 +146,10 @@ warning: `missing_return_type` redeclared with a different signature --> $DIR/clashing-extern-fn.rs:259:13 | LL | fn missing_return_type() -> usize; - | --------------------------------- `missing_return_type` previously declared here + | ---------------------------------- `missing_return_type` previously declared here ... LL | fn missing_return_type(); - | ^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | ^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn() -> usize` found `unsafe extern "C" fn()` @@ -158,10 +158,10 @@ warning: `non_zero_usize` redeclared with a different signature --> $DIR/clashing-extern-fn.rs:277:13 | LL | fn non_zero_usize() -> core::num::NonZero; - | ------------------------------------------------ `non_zero_usize` previously declared here + | ------------------------------------------------- `non_zero_usize` previously declared here ... LL | fn non_zero_usize() -> usize; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn() -> NonZero` found `unsafe extern "C" fn() -> usize` @@ -170,10 +170,10 @@ warning: `non_null_ptr` redeclared with a different signature --> $DIR/clashing-extern-fn.rs:279:13 | LL | fn non_null_ptr() -> core::ptr::NonNull; - | ---------------------------------------------- `non_null_ptr` previously declared here + | ----------------------------------------------- `non_null_ptr` previously declared here ... LL | fn non_null_ptr() -> *const usize; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn() -> NonNull` found `unsafe extern "C" fn() -> *const usize` @@ -182,10 +182,10 @@ warning: `option_non_zero_usize_incorrect` redeclared with a different signature --> $DIR/clashing-extern-fn.rs:373:13 | LL | fn option_non_zero_usize_incorrect() -> usize; - | --------------------------------------------- `option_non_zero_usize_incorrect` previously declared here + | ---------------------------------------------- `option_non_zero_usize_incorrect` previously declared here ... LL | fn option_non_zero_usize_incorrect() -> isize; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn() -> usize` found `unsafe extern "C" fn() -> isize` @@ -194,10 +194,10 @@ warning: `option_non_null_ptr_incorrect` redeclared with a different signature --> $DIR/clashing-extern-fn.rs:375:13 | LL | fn option_non_null_ptr_incorrect() -> *const usize; - | -------------------------------------------------- `option_non_null_ptr_incorrect` previously declared here + | --------------------------------------------------- `option_non_null_ptr_incorrect` previously declared here ... LL | fn option_non_null_ptr_incorrect() -> *const isize; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn() -> *const usize` found `unsafe extern "C" fn() -> *const isize` @@ -206,10 +206,10 @@ warning: `hidden_niche_transparent_no_niche` redeclared with a different signatu --> $DIR/clashing-extern-fn.rs:429:13 | LL | fn hidden_niche_transparent_no_niche() -> usize; - | ----------------------------------------------- `hidden_niche_transparent_no_niche` previously declared here + | ------------------------------------------------ `hidden_niche_transparent_no_niche` previously declared here ... LL | fn hidden_niche_transparent_no_niche() -> Option; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn() -> usize` found `unsafe extern "C" fn() -> Option` @@ -218,10 +218,10 @@ warning: `hidden_niche_unsafe_cell` redeclared with a different signature --> $DIR/clashing-extern-fn.rs:433:13 | LL | fn hidden_niche_unsafe_cell() -> usize; - | -------------------------------------- `hidden_niche_unsafe_cell` previously declared here + | --------------------------------------- `hidden_niche_unsafe_cell` previously declared here ... LL | fn hidden_niche_unsafe_cell() -> Option>>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn() -> usize` found `unsafe extern "C" fn() -> Option>>` diff --git a/tests/ui/lint/dropping_copy_types-macros.fixed b/tests/ui/lint/dropping_copy_types-macros.fixed new file mode 100644 index 00000000000..a8ceedadc80 --- /dev/null +++ b/tests/ui/lint/dropping_copy_types-macros.fixed @@ -0,0 +1,12 @@ +//@ check-fail +//@ run-rustfix + +#![deny(dropping_copy_types)] + +use std::fmt::Write; + +fn main() { + let mut msg = String::new(); + let _ = writeln!(&mut msg, "test"); + //~^ ERROR calls to `std::mem::drop` +} diff --git a/tests/ui/lint/dropping_copy_types-macros.rs b/tests/ui/lint/dropping_copy_types-macros.rs new file mode 100644 index 00000000000..b249b0c868f --- /dev/null +++ b/tests/ui/lint/dropping_copy_types-macros.rs @@ -0,0 +1,12 @@ +//@ check-fail +//@ run-rustfix + +#![deny(dropping_copy_types)] + +use std::fmt::Write; + +fn main() { + let mut msg = String::new(); + drop(writeln!(&mut msg, "test")); + //~^ ERROR calls to `std::mem::drop` +} diff --git a/tests/ui/lint/dropping_copy_types-macros.stderr b/tests/ui/lint/dropping_copy_types-macros.stderr new file mode 100644 index 00000000000..117e9f4fe09 --- /dev/null +++ b/tests/ui/lint/dropping_copy_types-macros.stderr @@ -0,0 +1,21 @@ +error: calls to `std::mem::drop` with a value that implements `Copy` does nothing + --> $DIR/dropping_copy_types-macros.rs:10:5 + | +LL | drop(writeln!(&mut msg, "test")); + | ^^^^^--------------------------^ + | | + | argument has type `Result<(), std::fmt::Error>` + | +note: the lint level is defined here + --> $DIR/dropping_copy_types-macros.rs:4:9 + | +LL | #![deny(dropping_copy_types)] + | ^^^^^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(writeln!(&mut msg, "test")); +LL + let _ = writeln!(&mut msg, "test"); + | + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/issue-1866.stderr b/tests/ui/lint/issue-1866.stderr index 36d323825a4..d19a1349668 100644 --- a/tests/ui/lint/issue-1866.stderr +++ b/tests/ui/lint/issue-1866.stderr @@ -2,10 +2,10 @@ warning: `rust_task_is_unwinding` redeclared with a different signature --> $DIR/issue-1866.rs:23:13 | LL | pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool; - | ----------------------------------------------------------- `rust_task_is_unwinding` previously declared here + | ------------------------------------------------------------ `rust_task_is_unwinding` previously declared here ... LL | pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn(*const usize) -> bool` found `unsafe extern "C" fn(*const bool) -> bool` diff --git a/tests/ui/lint/issue-30302.stderr b/tests/ui/lint/issue-30302.stderr index baf6c0d7a59..317fefee466 100644 --- a/tests/ui/lint/issue-30302.stderr +++ b/tests/ui/lint/issue-30302.stderr @@ -13,7 +13,7 @@ LL | Nil => true, | --- matches any value LL | LL | _ => false - | ^ unreachable pattern + | ^ no value can reach this | note: the lint level is defined here --> $DIR/issue-30302.rs:4:9 diff --git a/tests/ui/lint/lint-attr-everywhere-late.stderr b/tests/ui/lint/lint-attr-everywhere-late.stderr index ddc31905afb..1937b618236 100644 --- a/tests/ui/lint/lint-attr-everywhere-late.stderr +++ b/tests/ui/lint/lint-attr-everywhere-late.stderr @@ -406,10 +406,10 @@ error: `clashing1` redeclared with a different signature --> $DIR/lint-attr-everywhere-late.rs:123:5 | LL | fn clashing1(); - | -------------- `clashing1` previously declared here + | --------------- `clashing1` previously declared here ... LL | fn clashing1(_: i32); - | ^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | ^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn()` found `unsafe extern "C" fn(i32)` @@ -423,10 +423,10 @@ error: `clashing2` redeclared with a different signature --> $DIR/lint-attr-everywhere-late.rs:128:5 | LL | fn clashing2(); - | -------------- `clashing2` previously declared here + | --------------- `clashing2` previously declared here ... LL | fn clashing2(_: i32); - | ^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | ^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn()` found `unsafe extern "C" fn(i32)` diff --git a/tests/ui/lint/lint-ctypes-cstr.rs b/tests/ui/lint/lint-ctypes-cstr.rs new file mode 100644 index 00000000000..b04decd0bca --- /dev/null +++ b/tests/ui/lint/lint-ctypes-cstr.rs @@ -0,0 +1,36 @@ +#![crate_type = "lib"] +#![deny(improper_ctypes, improper_ctypes_definitions)] + +use std::ffi::{CStr, CString}; + +extern "C" { + fn take_cstr(s: CStr); + //~^ ERROR `extern` block uses type `CStr`, which is not FFI-safe + //~| HELP consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + fn take_cstr_ref(s: &CStr); + //~^ ERROR `extern` block uses type `CStr`, which is not FFI-safe + //~| HELP consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + fn take_cstring(s: CString); + //~^ ERROR `extern` block uses type `CString`, which is not FFI-safe + //~| HELP consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + fn take_cstring_ref(s: &CString); + //~^ ERROR `extern` block uses type `CString`, which is not FFI-safe + //~| HELP consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + + fn no_special_help_for_mut_cstring(s: *mut CString); + //~^ ERROR `extern` block uses type `CString`, which is not FFI-safe + //~| HELP consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + + fn no_special_help_for_mut_cstring_ref(s: &mut CString); + //~^ ERROR `extern` block uses type `CString`, which is not FFI-safe + //~| HELP consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct +} + +extern "C" fn rust_take_cstr_ref(s: &CStr) {} +//~^ ERROR `extern` fn uses type `CStr`, which is not FFI-safe +//~| HELP consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` +extern "C" fn rust_take_cstring(s: CString) {} +//~^ ERROR `extern` fn uses type `CString`, which is not FFI-safe +//~| HELP consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` +extern "C" fn rust_no_special_help_for_mut_cstring(s: *mut CString) {} +extern "C" fn rust_no_special_help_for_mut_cstring_ref(s: &mut CString) {} diff --git a/tests/ui/lint/lint-ctypes-cstr.stderr b/tests/ui/lint/lint-ctypes-cstr.stderr new file mode 100644 index 00000000000..8957758d577 --- /dev/null +++ b/tests/ui/lint/lint-ctypes-cstr.stderr @@ -0,0 +1,84 @@ +error: `extern` block uses type `CStr`, which is not FFI-safe + --> $DIR/lint-ctypes-cstr.rs:7:21 + | +LL | fn take_cstr(s: CStr); + | ^^^^ not FFI-safe + | + = help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + = note: `CStr`/`CString` do not have a guaranteed layout +note: the lint level is defined here + --> $DIR/lint-ctypes-cstr.rs:2:9 + | +LL | #![deny(improper_ctypes, improper_ctypes_definitions)] + | ^^^^^^^^^^^^^^^ + +error: `extern` block uses type `CStr`, which is not FFI-safe + --> $DIR/lint-ctypes-cstr.rs:10:25 + | +LL | fn take_cstr_ref(s: &CStr); + | ^^^^^ not FFI-safe + | + = help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + = note: `CStr`/`CString` do not have a guaranteed layout + +error: `extern` block uses type `CString`, which is not FFI-safe + --> $DIR/lint-ctypes-cstr.rs:13:24 + | +LL | fn take_cstring(s: CString); + | ^^^^^^^ not FFI-safe + | + = help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + = note: `CStr`/`CString` do not have a guaranteed layout + +error: `extern` block uses type `CString`, which is not FFI-safe + --> $DIR/lint-ctypes-cstr.rs:16:28 + | +LL | fn take_cstring_ref(s: &CString); + | ^^^^^^^^ not FFI-safe + | + = help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + = note: `CStr`/`CString` do not have a guaranteed layout + +error: `extern` block uses type `CString`, which is not FFI-safe + --> $DIR/lint-ctypes-cstr.rs:20:43 + | +LL | fn no_special_help_for_mut_cstring(s: *mut CString); + | ^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout + +error: `extern` block uses type `CString`, which is not FFI-safe + --> $DIR/lint-ctypes-cstr.rs:24:47 + | +LL | fn no_special_help_for_mut_cstring_ref(s: &mut CString); + | ^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout + +error: `extern` fn uses type `CStr`, which is not FFI-safe + --> $DIR/lint-ctypes-cstr.rs:29:37 + | +LL | extern "C" fn rust_take_cstr_ref(s: &CStr) {} + | ^^^^^ not FFI-safe + | + = help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + = note: `CStr`/`CString` do not have a guaranteed layout +note: the lint level is defined here + --> $DIR/lint-ctypes-cstr.rs:2:26 + | +LL | #![deny(improper_ctypes, improper_ctypes_definitions)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `extern` fn uses type `CString`, which is not FFI-safe + --> $DIR/lint-ctypes-cstr.rs:32:36 + | +LL | extern "C" fn rust_take_cstring(s: CString) {} + | ^^^^^^^ not FFI-safe + | + = help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + = note: `CStr`/`CString` do not have a guaranteed layout + +error: aborting due to 8 previous errors + diff --git a/tests/ui/lint/lint-missing-doc.stderr b/tests/ui/lint/lint-missing-doc.stderr index 4e9ee4f2769..5165ccc3fd0 100644 --- a/tests/ui/lint/lint-missing-doc.stderr +++ b/tests/ui/lint/lint-missing-doc.stderr @@ -116,7 +116,7 @@ error: missing documentation for a function --> $DIR/lint-missing-doc.rs:196:5 | LL | pub fn extern_fn_undocumented(f: f32) -> f32; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a static --> $DIR/lint-missing-doc.rs:201:5 diff --git a/tests/ui/lint/lint-unnecessary-parens.fixed b/tests/ui/lint/lint-unnecessary-parens.fixed index 089aa1b7ab7..a8c8dd1d512 100644 --- a/tests/ui/lint/lint-unnecessary-parens.fixed +++ b/tests/ui/lint/lint-unnecessary-parens.fixed @@ -1,7 +1,6 @@ //@ run-rustfix #![deny(unused_parens)] -#![feature(raw_ref_op)] #![allow(while_true)] // for rustfix #[derive(Eq, PartialEq)] diff --git a/tests/ui/lint/lint-unnecessary-parens.rs b/tests/ui/lint/lint-unnecessary-parens.rs index dc77ee00352..02aa78283c7 100644 --- a/tests/ui/lint/lint-unnecessary-parens.rs +++ b/tests/ui/lint/lint-unnecessary-parens.rs @@ -1,7 +1,6 @@ //@ run-rustfix #![deny(unused_parens)] -#![feature(raw_ref_op)] #![allow(while_true)] // for rustfix #[derive(Eq, PartialEq)] diff --git a/tests/ui/lint/lint-unnecessary-parens.stderr b/tests/ui/lint/lint-unnecessary-parens.stderr index c9422437a9f..f2e5debd6e0 100644 --- a/tests/ui/lint/lint-unnecessary-parens.stderr +++ b/tests/ui/lint/lint-unnecessary-parens.stderr @@ -1,5 +1,5 @@ error: unnecessary parentheses around `return` value - --> $DIR/lint-unnecessary-parens.rs:14:12 + --> $DIR/lint-unnecessary-parens.rs:13:12 | LL | return (1); | ^ ^ @@ -16,7 +16,7 @@ LL + return 1; | error: unnecessary parentheses around `return` value - --> $DIR/lint-unnecessary-parens.rs:17:12 + --> $DIR/lint-unnecessary-parens.rs:16:12 | LL | return (X { y }); | ^ ^ @@ -28,7 +28,7 @@ LL + return X { y }; | error: unnecessary parentheses around type - --> $DIR/lint-unnecessary-parens.rs:20:46 + --> $DIR/lint-unnecessary-parens.rs:19:46 | LL | pub fn unused_parens_around_return_type() -> (u32) { | ^ ^ @@ -40,7 +40,7 @@ LL + pub fn unused_parens_around_return_type() -> u32 { | error: unnecessary parentheses around block return value - --> $DIR/lint-unnecessary-parens.rs:26:9 + --> $DIR/lint-unnecessary-parens.rs:25:9 | LL | (5) | ^ ^ @@ -52,7 +52,7 @@ LL + 5 | error: unnecessary parentheses around block return value - --> $DIR/lint-unnecessary-parens.rs:28:5 + --> $DIR/lint-unnecessary-parens.rs:27:5 | LL | (5) | ^ ^ @@ -64,7 +64,7 @@ LL + 5 | error: unnecessary parentheses around `if` condition - --> $DIR/lint-unnecessary-parens.rs:40:7 + --> $DIR/lint-unnecessary-parens.rs:39:7 | LL | if(true) {} | ^ ^ @@ -76,7 +76,7 @@ LL + if true {} | error: unnecessary parentheses around `while` condition - --> $DIR/lint-unnecessary-parens.rs:41:10 + --> $DIR/lint-unnecessary-parens.rs:40:10 | LL | while(true) {} | ^ ^ @@ -88,7 +88,7 @@ LL + while true {} | error: unnecessary parentheses around `for` iterator expression - --> $DIR/lint-unnecessary-parens.rs:42:13 + --> $DIR/lint-unnecessary-parens.rs:41:13 | LL | for _ in(e) {} | ^ ^ @@ -100,7 +100,7 @@ LL + for _ in e {} | error: unnecessary parentheses around `match` scrutinee expression - --> $DIR/lint-unnecessary-parens.rs:43:10 + --> $DIR/lint-unnecessary-parens.rs:42:10 | LL | match(1) { _ => ()} | ^ ^ @@ -112,7 +112,7 @@ LL + match 1 { _ => ()} | error: unnecessary parentheses around `return` value - --> $DIR/lint-unnecessary-parens.rs:44:11 + --> $DIR/lint-unnecessary-parens.rs:43:11 | LL | return(1); | ^ ^ @@ -124,7 +124,7 @@ LL + return 1; | error: unnecessary parentheses around assigned value - --> $DIR/lint-unnecessary-parens.rs:75:31 + --> $DIR/lint-unnecessary-parens.rs:74:31 | LL | pub const CONST_ITEM: usize = (10); | ^ ^ @@ -136,7 +136,7 @@ LL + pub const CONST_ITEM: usize = 10; | error: unnecessary parentheses around assigned value - --> $DIR/lint-unnecessary-parens.rs:76:33 + --> $DIR/lint-unnecessary-parens.rs:75:33 | LL | pub static STATIC_ITEM: usize = (10); | ^ ^ @@ -148,7 +148,7 @@ LL + pub static STATIC_ITEM: usize = 10; | error: unnecessary parentheses around function argument - --> $DIR/lint-unnecessary-parens.rs:80:9 + --> $DIR/lint-unnecessary-parens.rs:79:9 | LL | bar((true)); | ^ ^ @@ -160,7 +160,7 @@ LL + bar(true); | error: unnecessary parentheses around `if` condition - --> $DIR/lint-unnecessary-parens.rs:82:8 + --> $DIR/lint-unnecessary-parens.rs:81:8 | LL | if (true) {} | ^ ^ @@ -172,7 +172,7 @@ LL + if true {} | error: unnecessary parentheses around `while` condition - --> $DIR/lint-unnecessary-parens.rs:83:11 + --> $DIR/lint-unnecessary-parens.rs:82:11 | LL | while (true) {} | ^ ^ @@ -184,7 +184,7 @@ LL + while true {} | error: unnecessary parentheses around `match` scrutinee expression - --> $DIR/lint-unnecessary-parens.rs:84:11 + --> $DIR/lint-unnecessary-parens.rs:83:11 | LL | match (true) { | ^ ^ @@ -196,7 +196,7 @@ LL + match true { | error: unnecessary parentheses around `let` scrutinee expression - --> $DIR/lint-unnecessary-parens.rs:87:16 + --> $DIR/lint-unnecessary-parens.rs:86:16 | LL | if let 1 = (1) {} | ^ ^ @@ -208,7 +208,7 @@ LL + if let 1 = 1 {} | error: unnecessary parentheses around `let` scrutinee expression - --> $DIR/lint-unnecessary-parens.rs:88:19 + --> $DIR/lint-unnecessary-parens.rs:87:19 | LL | while let 1 = (2) {} | ^ ^ @@ -220,7 +220,7 @@ LL + while let 1 = 2 {} | error: unnecessary parentheses around method argument - --> $DIR/lint-unnecessary-parens.rs:104:24 + --> $DIR/lint-unnecessary-parens.rs:103:24 | LL | X { y: false }.foo((true)); | ^ ^ @@ -232,7 +232,7 @@ LL + X { y: false }.foo(true); | error: unnecessary parentheses around assigned value - --> $DIR/lint-unnecessary-parens.rs:106:18 + --> $DIR/lint-unnecessary-parens.rs:105:18 | LL | let mut _a = (0); | ^ ^ @@ -244,7 +244,7 @@ LL + let mut _a = 0; | error: unnecessary parentheses around assigned value - --> $DIR/lint-unnecessary-parens.rs:107:10 + --> $DIR/lint-unnecessary-parens.rs:106:10 | LL | _a = (0); | ^ ^ @@ -256,7 +256,7 @@ LL + _a = 0; | error: unnecessary parentheses around assigned value - --> $DIR/lint-unnecessary-parens.rs:108:11 + --> $DIR/lint-unnecessary-parens.rs:107:11 | LL | _a += (1); | ^ ^ @@ -268,7 +268,7 @@ LL + _a += 1; | error: unnecessary parentheses around pattern - --> $DIR/lint-unnecessary-parens.rs:110:8 + --> $DIR/lint-unnecessary-parens.rs:109:8 | LL | let(mut _a) = 3; | ^ ^ @@ -280,7 +280,7 @@ LL + let mut _a = 3; | error: unnecessary parentheses around pattern - --> $DIR/lint-unnecessary-parens.rs:111:9 + --> $DIR/lint-unnecessary-parens.rs:110:9 | LL | let (mut _a) = 3; | ^ ^ @@ -292,7 +292,7 @@ LL + let mut _a = 3; | error: unnecessary parentheses around pattern - --> $DIR/lint-unnecessary-parens.rs:112:8 + --> $DIR/lint-unnecessary-parens.rs:111:8 | LL | let( mut _a) = 3; | ^^ ^ @@ -304,7 +304,7 @@ LL + let mut _a = 3; | error: unnecessary parentheses around pattern - --> $DIR/lint-unnecessary-parens.rs:114:8 + --> $DIR/lint-unnecessary-parens.rs:113:8 | LL | let(_a) = 3; | ^ ^ @@ -316,7 +316,7 @@ LL + let _a = 3; | error: unnecessary parentheses around pattern - --> $DIR/lint-unnecessary-parens.rs:115:9 + --> $DIR/lint-unnecessary-parens.rs:114:9 | LL | let (_a) = 3; | ^ ^ @@ -328,7 +328,7 @@ LL + let _a = 3; | error: unnecessary parentheses around pattern - --> $DIR/lint-unnecessary-parens.rs:116:8 + --> $DIR/lint-unnecessary-parens.rs:115:8 | LL | let( _a) = 3; | ^^ ^ @@ -340,7 +340,7 @@ LL + let _a = 3; | error: unnecessary parentheses around block return value - --> $DIR/lint-unnecessary-parens.rs:122:9 + --> $DIR/lint-unnecessary-parens.rs:121:9 | LL | (unit!() - One) | ^ ^ @@ -352,7 +352,7 @@ LL + unit!() - One | error: unnecessary parentheses around block return value - --> $DIR/lint-unnecessary-parens.rs:124:9 + --> $DIR/lint-unnecessary-parens.rs:123:9 | LL | (unit![] - One) | ^ ^ @@ -364,7 +364,7 @@ LL + unit![] - One | error: unnecessary parentheses around block return value - --> $DIR/lint-unnecessary-parens.rs:127:9 + --> $DIR/lint-unnecessary-parens.rs:126:9 | LL | (unit! {} - One) | ^ ^ @@ -376,7 +376,7 @@ LL + unit! {} - One | error: unnecessary parentheses around assigned value - --> $DIR/lint-unnecessary-parens.rs:132:14 + --> $DIR/lint-unnecessary-parens.rs:131:14 | LL | let _r = (&x); | ^ ^ @@ -388,7 +388,7 @@ LL + let _r = &x; | error: unnecessary parentheses around assigned value - --> $DIR/lint-unnecessary-parens.rs:133:14 + --> $DIR/lint-unnecessary-parens.rs:132:14 | LL | let _r = (&mut x); | ^ ^ diff --git a/tests/ui/lint/must_not_suspend/other_items.stderr b/tests/ui/lint/must_not_suspend/other_items.stderr index e6c36b78951..dff5210b7e4 100644 --- a/tests/ui/lint/must_not_suspend/other_items.stderr +++ b/tests/ui/lint/must_not_suspend/other_items.stderr @@ -1,10 +1,10 @@ -error: `must_not_suspend` attribute should be applied to a struct, enum, or trait +error: `must_not_suspend` attribute should be applied to a struct, enum, union, or trait --> $DIR/other_items.rs:5:1 | LL | #[must_not_suspend] | ^^^^^^^^^^^^^^^^^^^ LL | mod inner {} - | ------------ is not a struct, enum, or trait + | ------------ is not a struct, enum, union, or trait error: aborting due to 1 previous error diff --git a/tests/ui/lint/must_not_suspend/return.stderr b/tests/ui/lint/must_not_suspend/return.stderr index 5a73064c787..440f8165686 100644 --- a/tests/ui/lint/must_not_suspend/return.stderr +++ b/tests/ui/lint/must_not_suspend/return.stderr @@ -1,4 +1,4 @@ -error: `must_not_suspend` attribute should be applied to a struct, enum, or trait +error: `must_not_suspend` attribute should be applied to a struct, enum, union, or trait --> $DIR/return.rs:5:1 | LL | #[must_not_suspend] @@ -6,7 +6,7 @@ LL | #[must_not_suspend] LL | / fn foo() -> i32 { LL | | 0 LL | | } - | |_- is not a struct, enum, or trait + | |_- is not a struct, enum, union, or trait error: aborting due to 1 previous error diff --git a/tests/ui/lint/unreachable_pub.stderr b/tests/ui/lint/unreachable_pub.stderr index 705a537a3f1..65f45fbd816 100644 --- a/tests/ui/lint/unreachable_pub.stderr +++ b/tests/ui/lint/unreachable_pub.stderr @@ -130,7 +130,7 @@ warning: unreachable `pub` item --> $DIR/unreachable_pub.rs:48:9 | LL | pub fn catalyze() -> bool; - | ---^^^^^^^^^^^^^^^^^^^^^^ + | ---^^^^^^^^^^^^^^^^^^^^^^^ | | | help: consider restricting its visibility: `pub(crate)` | diff --git a/tests/ui/lint/unused/lint-unused-mut-variables.rs b/tests/ui/lint/unused/lint-unused-mut-variables.rs index f0c7dff666e..bc38af9867c 100644 --- a/tests/ui/lint/unused/lint-unused-mut-variables.rs +++ b/tests/ui/lint/unused/lint-unused-mut-variables.rs @@ -3,7 +3,7 @@ // Exercise the unused_mut attribute in some positive and negative cases #![warn(unused_mut)] -#![feature(async_closure, raw_ref_op)] +#![feature(async_closure)] async fn baz_async( mut a: i32, diff --git a/tests/ui/lint/unused/lint-unused-variables.stderr b/tests/ui/lint/unused/lint-unused-variables.stderr index 09729eeba79..ef590d85aef 100644 --- a/tests/ui/lint/unused/lint-unused-variables.stderr +++ b/tests/ui/lint/unused/lint-unused-variables.stderr @@ -16,6 +16,12 @@ error: unused variable: `a` LL | a: i32, | ^ help: if this is intentional, prefix it with an underscore: `_a` +error: unused variable: `a` + --> $DIR/lint-unused-variables.rs:68:9 + | +LL | a: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_a` + error: unused variable: `b` --> $DIR/lint-unused-variables.rs:14:5 | @@ -58,12 +64,6 @@ error: unused variable: `b` LL | b: i32, | ^ help: if this is intentional, prefix it with an underscore: `_b` -error: unused variable: `a` - --> $DIR/lint-unused-variables.rs:68:9 - | -LL | a: i32, - | ^ help: if this is intentional, prefix it with an underscore: `_a` - error: unused variable: `b` --> $DIR/lint-unused-variables.rs:74:9 | diff --git a/tests/ui/macros/macro-match-nonterminal.stderr b/tests/ui/macros/macro-match-nonterminal.stderr index 831579c4fef..f221f92c3cd 100644 --- a/tests/ui/macros/macro-match-nonterminal.stderr +++ b/tests/ui/macros/macro-match-nonterminal.stderr @@ -1,14 +1,14 @@ error: missing fragment specifier - --> $DIR/macro-match-nonterminal.rs:2:8 + --> $DIR/macro-match-nonterminal.rs:2:6 | LL | ($a, $b) => { - | ^ + | ^^ error: missing fragment specifier - --> $DIR/macro-match-nonterminal.rs:2:8 + --> $DIR/macro-match-nonterminal.rs:2:6 | LL | ($a, $b) => { - | ^ + | ^^ | = 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 #40107 @@ -27,10 +27,10 @@ error: aborting due to 3 previous errors Future incompatibility report: Future breakage diagnostic: error: missing fragment specifier - --> $DIR/macro-match-nonterminal.rs:2:8 + --> $DIR/macro-match-nonterminal.rs:2:6 | LL | ($a, $b) => { - | ^ + | ^^ | = 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 #40107 diff --git a/tests/ui/macros/stringify.rs b/tests/ui/macros/stringify.rs index f06c1f99069..f405cd253de 100644 --- a/tests/ui/macros/stringify.rs +++ b/tests/ui/macros/stringify.rs @@ -14,7 +14,6 @@ #![feature(let_chains)] #![feature(more_qualified_paths)] #![feature(never_patterns)] -#![feature(raw_ref_op)] #![feature(trait_alias)] #![feature(try_blocks)] #![feature(type_ascription)] @@ -33,8 +32,6 @@ macro_rules! stmt { ($stmt:stmt) => { stringify!($stmt) }; } macro_rules! ty { ($ty:ty) => { stringify!($ty) }; } macro_rules! vis { ($vis:vis) => { stringify!($vis) }; } -// Use this when AST pretty-printing and TokenStream pretty-printing give -// the same result (which is preferable.) macro_rules! c1 { ($frag:ident, [$($tt:tt)*], $s:literal) => { // Prior to #125174: @@ -66,6 +63,8 @@ fn test_block() { } ], "{ let _; true }" ); + + // Attributes are not allowed on vanilla blocks. } #[test] @@ -332,6 +331,20 @@ fn test_expr() { // ExprKind::FormatArgs: untestable because this test works pre-expansion. // ExprKind::Err: untestable. + + // Ones involving attributes. + c1!(expr, [ #[aa] 1 ], "#[aa] 1"); + c1!(expr, [ #[aa] #[bb] x ], "#[aa] #[bb] x"); + c1!(expr, [ #[aa] 1 + 2 ], "#[aa] 1 + 2"); + c1!(expr, [ #[aa] x + 2 ], "#[aa] x + 2"); + c1!(expr, [ #[aa] 1 / #[bb] 2 ], "#[aa] 1 / #[bb] 2"); + c1!(expr, [ #[aa] x / #[bb] 2 ], "#[aa] x / #[bb] 2"); + c1!(expr, [ 1 << #[bb] 2 ], "1 << #[bb] 2"); + c1!(expr, [ x << #[bb] 2 ], "x << #[bb] 2"); + c1!(expr, [ #[aa] (1 + 2) ], "#[aa] (1 + 2)"); + c1!(expr, [ #[aa] #[bb] (x + 2) ], "#[aa] #[bb] (x + 2)"); + c1!(expr, [ #[aa] x[0].p ], "#[aa] x[0].p"); + c1!(expr, [ #[aa] { #![bb] 0 } ], "#[aa] { #![bb] 0 }"); } #[test] @@ -484,6 +497,11 @@ fn test_item() { "macro_rules! stringify { () => {}; }" ); c1!(item, [ pub macro stringify() {} ], "pub macro stringify() {}"); + + // Ones involving attributes. + c1!(item, [ #[aa] mod m; ], "#[aa] mod m;"); + c1!(item, [ mod m { #![bb] } ], "mod m { #![bb] }"); + c1!(item, [ #[aa] mod m { #![bb] } ], "#[aa] mod m { #![bb] }"); } #[test] @@ -492,6 +510,8 @@ fn test_meta() { c1!(meta, [ k = "v" ], "k = \"v\""); c1!(meta, [ list(k1, k2 = "v") ], "list(k1, k2 = \"v\")"); c1!(meta, [ serde::k ], "serde::k"); + + // Attributes are not allowed on metas. } #[test] @@ -580,6 +600,8 @@ fn test_pat() { c1!(pat, [ mac!(...) ], "mac!(...)"); c1!(pat, [ mac![...] ], "mac![...]"); c1!(pat, [ mac! { ... } ], "mac! { ... }"); + + // Attributes are not allowed on patterns. } #[test] @@ -593,6 +615,8 @@ fn test_path() { c1!(path, [ Self::<'static> ], "Self::<'static>"); c1!(path, [ Self() ], "Self()"); c1!(path, [ Self() -> () ], "Self() -> ()"); + + // Attributes are not allowed on paths. } #[test] @@ -622,6 +646,20 @@ fn test_stmt() { c1!(stmt, [ mac!(...) ], "mac!(...)"); c1!(stmt, [ mac![...] ], "mac![...]"); c1!(stmt, [ mac! { ... } ], "mac! { ... }"); + + // Ones involving attributes. + c1!(stmt, [ #[aa] 1 ], "#[aa] 1"); + c1!(stmt, [ #[aa] #[bb] x ], "#[aa] #[bb] x"); + c1!(stmt, [ #[aa] 1 as u32 ], "#[aa] 1 as u32"); + c1!(stmt, [ #[aa] x as u32 ], "#[aa] x as u32"); + c1!(stmt, [ #[aa] 1 .. #[bb] 2 ], "#[aa] 1 .. #[bb] 2"); + c1!(stmt, [ #[aa] x .. #[bb] 2 ], "#[aa] x .. #[bb] 2"); + c1!(stmt, [ 1 || #[bb] 2 ], "1 || #[bb] 2"); + c1!(stmt, [ x || #[bb] 2 ], "x || #[bb] 2"); + c1!(stmt, [ #[aa] (1 + 2) ], "#[aa] (1 + 2)"); + c1!(stmt, [ #[aa] #[bb] (x + 2) ], "#[aa] #[bb] (x + 2)"); + c1!(stmt, [ #[aa] x[0].p ], "#[aa] x[0].p"); + c1!(stmt, [ #[aa] { #![bb] 0 } ], "#[aa] { #![bb] 0 }"); } #[test] @@ -708,6 +746,8 @@ fn test_ty() { // TyKind::CVarArgs // FIXME: todo + + // Attributes are not allowed on types. } #[test] @@ -732,6 +772,8 @@ fn test_vis() { macro_rules! inherited_vis { ($vis:vis struct) => { vis!($vis) }; } assert_eq!(inherited_vis!(struct), ""); assert_eq!(stringify!(), ""); + + // Attributes are not allowed on visibilities. } macro_rules! p { diff --git a/tests/ui/methods/missing-method-on-type-parameter.rs b/tests/ui/methods/missing-method-on-type-parameter.rs new file mode 100644 index 00000000000..cbcbeea4d4c --- /dev/null +++ b/tests/ui/methods/missing-method-on-type-parameter.rs @@ -0,0 +1,6 @@ +// Regression test for https://github.com/rust-lang/rust/issues/129205 +fn x() { + T::try_from(); //~ ERROR E0599 +} + +fn main() {} diff --git a/tests/ui/methods/missing-method-on-type-parameter.stderr b/tests/ui/methods/missing-method-on-type-parameter.stderr new file mode 100644 index 00000000000..c53d7afe4e2 --- /dev/null +++ b/tests/ui/methods/missing-method-on-type-parameter.stderr @@ -0,0 +1,19 @@ +error[E0599]: no function or associated item named `try_from` found for type parameter `T` in the current scope + --> $DIR/missing-method-on-type-parameter.rs:3:8 + | +LL | fn x() { + | - function or associated item `try_from` not found for this type parameter +LL | T::try_from(); + | ^^^^^^^^ function or associated item not found in `T` + | + = help: items from traits can only be used if the trait is in scope +help: there is an associated function `from` with a similar name + --> $SRC_DIR/core/src/convert/mod.rs:LL:COL +help: trait `TryFrom` which provides `try_from` is implemented but not in scope; perhaps you want to import it + | +LL + use std::convert::TryFrom; + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/mir/mir_raw_fat_ptr.rs b/tests/ui/mir/mir_raw_fat_ptr.rs index a5a48587e3b..96c030b70e5 100644 --- a/tests/ui/mir/mir_raw_fat_ptr.rs +++ b/tests/ui/mir/mir_raw_fat_ptr.rs @@ -2,7 +2,6 @@ // check raw fat pointer ops in mir // FIXME: please improve this when we get monomorphization support -#![feature(raw_ref_op)] #![allow(ambiguous_wide_pointer_comparisons)] use std::mem; diff --git a/tests/ui/mir/mir_raw_fat_ptr.stderr b/tests/ui/mir/mir_raw_fat_ptr.stderr index a9e9dd66ebd..cd99d566654 100644 --- a/tests/ui/mir/mir_raw_fat_ptr.stderr +++ b/tests/ui/mir/mir_raw_fat_ptr.stderr @@ -1,5 +1,5 @@ warning: method `foo` is never used - --> $DIR/mir_raw_fat_ptr.rs:101:16 + --> $DIR/mir_raw_fat_ptr.rs:100:16 | LL | trait Foo { fn foo(&self) -> usize; } | --- ^^^ diff --git a/tests/ui/nll/issue-73159-rpit-static.stderr b/tests/ui/nll/issue-73159-rpit-static.stderr index 472db30fbeb..7c564b84a56 100644 --- a/tests/ui/nll/issue-73159-rpit-static.stderr +++ b/tests/ui/nll/issue-73159-rpit-static.stderr @@ -7,6 +7,11 @@ LL | fn make_it(&self) -> impl Iterator { | ------------------------ opaque type defined here LL | self.0.iter().copied() | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: add a `use<...>` bound to explicitly capture `'a` + | +LL | fn make_it(&self) -> impl Iterator + use<'a> { + | +++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/nll/member-constraints/min-choice-reject-ambiguous.stderr b/tests/ui/nll/member-constraints/min-choice-reject-ambiguous.stderr index cab75e630a7..911ddd3dc80 100644 --- a/tests/ui/nll/member-constraints/min-choice-reject-ambiguous.stderr +++ b/tests/ui/nll/member-constraints/min-choice-reject-ambiguous.stderr @@ -37,10 +37,10 @@ LL | fn test_ambiguous<'a, 'b, 'c>(s: &'a u8) -> impl Cap<'b> + Cap<'c> LL | s | ^ | -help: to declare that `impl Cap<'b> + Cap<'c>` captures `'a`, you can add an explicit `'a` lifetime bound +help: add a `use<...>` bound to explicitly capture `'a` | -LL | fn test_ambiguous<'a, 'b, 'c>(s: &'a u8) -> impl Cap<'b> + Cap<'c> + 'a - | ++++ +LL | fn test_ambiguous<'a, 'b, 'c>(s: &'a u8) -> impl Cap<'b> + Cap<'c> + use<'b, 'c, 'a> + | +++++++++++++++++ error: aborting due to 3 previous errors diff --git a/tests/ui/nll/member-constraints/nested-impl-trait-fail.stderr b/tests/ui/nll/member-constraints/nested-impl-trait-fail.stderr index 483b5822b9d..1a0611e715e 100644 --- a/tests/ui/nll/member-constraints/nested-impl-trait-fail.stderr +++ b/tests/ui/nll/member-constraints/nested-impl-trait-fail.stderr @@ -9,14 +9,10 @@ LL | fn fail_early_bound<'s, 'a, 'b>(a: &'s u8) -> impl IntoIterator + Cap<'b>>` captures `'s`, you can add an explicit `'s` lifetime bound +help: add a `use<...>` bound to explicitly capture `'s` | -LL | fn fail_early_bound<'s, 'a, 'b>(a: &'s u8) -> impl IntoIterator + Cap<'b>> + 's - | ++++ -help: to declare that `impl Cap<'a> + Cap<'b>` captures `'s`, you can add an explicit `'s` lifetime bound - | -LL | fn fail_early_bound<'s, 'a, 'b>(a: &'s u8) -> impl IntoIterator + Cap<'b> + 's> - | ++++ +LL | fn fail_early_bound<'s, 'a, 'b>(a: &'s u8) -> impl IntoIterator + Cap<'b>> + use<'a, 'b, 's> + | +++++++++++++++++ error[E0700]: hidden type for `impl Cap<'a> + Cap<'b>` captures lifetime that does not appear in bounds --> $DIR/nested-impl-trait-fail.rs:17:5 @@ -29,14 +25,10 @@ LL | fn fail_early_bound<'s, 'a, 'b>(a: &'s u8) -> impl IntoIterator + Cap<'b>>` captures `'s`, you can add an explicit `'s` lifetime bound +help: add a `use<...>` bound to explicitly capture `'s` | -LL | fn fail_early_bound<'s, 'a, 'b>(a: &'s u8) -> impl IntoIterator + Cap<'b>> + 's - | ++++ -help: to declare that `impl Cap<'a> + Cap<'b>` captures `'s`, you can add an explicit `'s` lifetime bound - | -LL | fn fail_early_bound<'s, 'a, 'b>(a: &'s u8) -> impl IntoIterator + Cap<'b> + 's> - | ++++ +LL | fn fail_early_bound<'s, 'a, 'b>(a: &'s u8) -> impl IntoIterator + Cap<'b> + use<'a, 'b, 's>> + | +++++++++++++++++ error[E0700]: hidden type for `impl IntoIterator + Cap<'b>>` captures lifetime that does not appear in bounds --> $DIR/nested-impl-trait-fail.rs:28:5 @@ -49,14 +41,10 @@ LL | ) -> impl IntoIterator + Cap<'b>> { LL | [a] | ^^^ | -help: to declare that `impl IntoIterator + Cap<'b>>` captures `'s`, you can add an explicit `'s` lifetime bound +help: add a `use<...>` bound to explicitly capture `'s` | -LL | ) -> impl IntoIterator + Cap<'b>> + 's { - | ++++ -help: to declare that `impl Cap<'a> + Cap<'b>` captures `'s`, you can add an explicit `'s` lifetime bound - | -LL | ) -> impl IntoIterator + Cap<'b> + 's> { - | ++++ +LL | ) -> impl IntoIterator + Cap<'b>> + use<'a, 'b, 's> { + | +++++++++++++++++ error[E0700]: hidden type for `impl Cap<'a> + Cap<'b>` captures lifetime that does not appear in bounds --> $DIR/nested-impl-trait-fail.rs:28:5 @@ -69,14 +57,10 @@ LL | ) -> impl IntoIterator + Cap<'b>> { LL | [a] | ^^^ | -help: to declare that `impl IntoIterator + Cap<'b>>` captures `'s`, you can add an explicit `'s` lifetime bound +help: add a `use<...>` bound to explicitly capture `'s` | -LL | ) -> impl IntoIterator + Cap<'b>> + 's { - | ++++ -help: to declare that `impl Cap<'a> + Cap<'b>` captures `'s`, you can add an explicit `'s` lifetime bound - | -LL | ) -> impl IntoIterator + Cap<'b> + 's> { - | ++++ +LL | ) -> impl IntoIterator + Cap<'b> + use<'a, 'b, 's>> { + | +++++++++++++++++ error: aborting due to 4 previous errors diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-116657.nll.stderr b/tests/ui/nll/polonius/location-insensitive-scopes-issue-116657.nll.stderr index 6f9b3303163..cdf394505a2 100644 --- a/tests/ui/nll/polonius/location-insensitive-scopes-issue-116657.nll.stderr +++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-116657.nll.stderr @@ -25,10 +25,10 @@ LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne { LL | <&mut i32 as Callable>::call(y) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: to declare that `impl PlusOne` captures `'a`, you can add an explicit `'a` lifetime bound +help: add a `use<...>` bound to explicitly capture `'a` | -LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne + 'a { - | ++++ +LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne + use<'a> { + | +++++++++ error: aborting due to 3 previous errors diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-116657.polonius.stderr b/tests/ui/nll/polonius/location-insensitive-scopes-issue-116657.polonius.stderr index 6f9b3303163..cdf394505a2 100644 --- a/tests/ui/nll/polonius/location-insensitive-scopes-issue-116657.polonius.stderr +++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-116657.polonius.stderr @@ -25,10 +25,10 @@ LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne { LL | <&mut i32 as Callable>::call(y) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: to declare that `impl PlusOne` captures `'a`, you can add an explicit `'a` lifetime bound +help: add a `use<...>` bound to explicitly capture `'a` | -LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne + 'a { - | ++++ +LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne + use<'a> { + | +++++++++ error: aborting due to 3 previous errors diff --git a/tests/ui/nll/ty-outlives/impl-trait-captures.stderr b/tests/ui/nll/ty-outlives/impl-trait-captures.stderr index 48569d1446d..3ceefbc4066 100644 --- a/tests/ui/nll/ty-outlives/impl-trait-captures.stderr +++ b/tests/ui/nll/ty-outlives/impl-trait-captures.stderr @@ -8,10 +8,10 @@ LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> { LL | x | ^ | -help: to declare that `Opaque(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::{opaque#0}), ['a/#0, T, 'a/#2])` captures `ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_))`, you can add an explicit `ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_))` lifetime bound +help: add a `use<...>` bound to explicitly capture `ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_))` | -LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_)) { - | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + use<'a, ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_)), T> { + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr b/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr index 5570390b21c..6ddc0595665 100644 --- a/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr +++ b/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr @@ -2,9 +2,9 @@ error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:8:9 | LL | (1 | 2,) => {} - | -------- matches all the values already + | -------- matches all the relevant values LL | (1,) => {} - | ^^^^ unreachable pattern + | ^^^^ no value can reach this | note: the lint level is defined here --> $DIR/exhaustiveness-unreachable-pattern.rs:1:9 @@ -16,17 +16,17 @@ error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:13:9 | LL | (1 | 2,) => {} - | -------- matches all the values already + | -------- matches all the relevant values LL | (2,) => {} - | ^^^^ unreachable pattern + | ^^^^ no value can reach this error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:19:9 | LL | (1 | 2,) => {} - | ^^^^^^^^ unreachable pattern + | ^^^^^^^^ no value can reach this | -note: these patterns collectively make the last one unreachable +note: multiple earlier patterns match some of the same values --> $DIR/exhaustiveness-unreachable-pattern.rs:19:9 | LL | (1,) => {} @@ -40,44 +40,44 @@ error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:24:9 | LL | (1 | 2, 3 | 4) => {} - | -------------- matches all the values already + | -------------- matches all the relevant values LL | (1, 3) => {} - | ^^^^^^ unreachable pattern + | ^^^^^^ no value can reach this error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:25:9 | LL | (1 | 2, 3 | 4) => {} - | -------------- matches all the values already + | -------------- matches all the relevant values LL | (1, 3) => {} LL | (1, 4) => {} - | ^^^^^^ unreachable pattern + | ^^^^^^ no value can reach this error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:26:9 | LL | (1 | 2, 3 | 4) => {} - | -------------- matches all the values already + | -------------- matches all the relevant values ... LL | (2, 4) => {} - | ^^^^^^ unreachable pattern + | ^^^^^^ no value can reach this error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:27:9 | LL | (1 | 2, 3 | 4) => {} - | -------------- matches all the values already + | -------------- matches all the relevant values ... LL | (2 | 1, 4) => {} - | ^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:29:9 | LL | (1, 4 | 5) => {} - | ^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^ no value can reach this | -note: these patterns collectively make the last one unreachable +note: multiple earlier patterns match some of the same values --> $DIR/exhaustiveness-unreachable-pattern.rs:29:9 | LL | (1 | 2, 3 | 4) => {} @@ -92,107 +92,107 @@ error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:34:13 | LL | (0, 0, 0) => {} - | - matches all the values already + | - matches all the relevant values LL | (0, 0 | 1, 0) => {} - | ^ unreachable pattern + | ^ no value can reach this error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:42:9 | LL | (None | Some(1 | 2),) => {} - | --------------------- matches all the values already + | --------------------- matches all the relevant values LL | (Some(1),) => {} - | ^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:43:9 | LL | (None | Some(1 | 2),) => {} - | --------------------- matches all the values already + | --------------------- matches all the relevant values LL | (Some(1),) => {} LL | (None,) => {} - | ^^^^^^^ unreachable pattern + | ^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:48:9 | LL | ((1 | 2,) | (3 | 4,),) => {} - | ---------------------- matches all the values already + | ---------------------- matches all the relevant values LL | ((1..=4,),) => {} - | ^^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:53:14 | LL | (1 | 1,) => {} - | - ^ unreachable pattern + | - ^ no value can reach this | | - | matches all the values already + | matches all the relevant values error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:57:19 | LL | (0 | 1) | 1 => {} - | - ^ unreachable pattern + | - ^ no value can reach this | | - | matches all the values already + | matches all the relevant values error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:63:14 | LL | 0 | (0 | 0) => {} - | - ^ unreachable pattern + | - ^ no value can reach this | | - | matches all the values already + | matches all the relevant values error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:63:18 | LL | 0 | (0 | 0) => {} - | - ^ unreachable pattern + | - ^ no value can reach this | | - | matches all the values already + | matches all the relevant values error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:71:13 | LL | Some(0) | - | ------- matches all the values already + | ------- matches all the relevant values LL | / Some( LL | | 0 | 0) => {} - | |______________________^ unreachable pattern + | |______________________^ no value can reach this error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:77:15 | LL | [0 - | - matches all the values already + | - matches all the relevant values LL | | 0 - | ^ unreachable pattern + | ^ no value can reach this error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:79:15 | LL | , 0 - | - matches all the values already + | - matches all the relevant values LL | | 0] => {} - | ^ unreachable pattern + | ^ no value can reach this error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:83:20 | LL | (true, 0 | 0) => {} - | - ^ unreachable pattern + | - ^ no value can reach this | | - | matches all the values already + | matches all the relevant values error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:84:17 | LL | (_, 0 | 0) => {} - | ^ unreachable pattern + | ^ no value can reach this | -note: these patterns collectively make the last one unreachable +note: multiple earlier patterns match some of the same values --> $DIR/exhaustiveness-unreachable-pattern.rs:84:17 | LL | (true, 0 | 0) => {} @@ -206,25 +206,25 @@ error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:92:10 | LL | [1, ..] => {} - | - matches all the values already + | - matches all the relevant values LL | [1 - | ^ unreachable pattern + | ^ no value can reach this error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:104:10 | LL | [true, ..] => {} - | ---- matches all the values already + | ---- matches all the relevant values LL | [true - | ^^^^ unreachable pattern + | ^^^^ no value can reach this error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:111:36 | LL | (true | false, None | Some(true - | ^^^^ unreachable pattern + | ^^^^ no value can reach this | -note: these patterns collectively make the last one unreachable +note: multiple earlier patterns match some of the same values --> $DIR/exhaustiveness-unreachable-pattern.rs:111:36 | LL | (true, Some(_)) => {} @@ -238,12 +238,12 @@ error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:116:14 | LL | (true - | ^^^^ unreachable pattern + | ^^^^ no value can reach this ... LL | (true | false, None | Some(t_or_f!())) => {} | --------- in this macro invocation | -note: these patterns collectively make the last one unreachable +note: multiple earlier patterns match some of the same values --> $DIR/exhaustiveness-unreachable-pattern.rs:116:14 | LL | (true @@ -261,26 +261,26 @@ error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:127:14 | LL | Some(0) => {} - | - matches all the values already + | - matches all the relevant values LL | Some(0 - | ^ unreachable pattern + | ^ no value can reach this error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:146:19 | LL | Some(false) => {} - | ----- matches all the values already + | ----- matches all the relevant values LL | None | Some(true LL | | false) => {} - | ^^^^^ unreachable pattern + | ^^^^^ no value can reach this error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:154:15 | LL | | true) => {} - | ^^^^ unreachable pattern + | ^^^^ no value can reach this | -note: these patterns collectively make the last one unreachable +note: multiple earlier patterns match some of the same values --> $DIR/exhaustiveness-unreachable-pattern.rs:154:15 | LL | (false, true) => {} @@ -295,9 +295,9 @@ error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:160:15 | LL | | true, - | ^^^^ unreachable pattern + | ^^^^ no value can reach this | -note: these patterns collectively make the last one unreachable +note: multiple earlier patterns match some of the same values --> $DIR/exhaustiveness-unreachable-pattern.rs:160:15 | LL | (true, false) => {} @@ -314,13 +314,13 @@ error: unreachable pattern LL | (x, y) | ------ matches any value LL | | (y, x) => {} - | ^^^^^^ unreachable pattern + | ^^^^^^ no value can reach this error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:169:30 | LL | fn unreachable_in_param((_ | (_, _)): (bool, bool)) {} - | - ^^^^^^ unreachable pattern + | - ^^^^^^ no value can reach this | | | matches any value @@ -328,7 +328,7 @@ error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:176:14 | LL | let (_ | (_, _)) = bool_pair; - | - ^^^^^^ unreachable pattern + | - ^^^^^^ no value can reach this | | | matches any value @@ -336,7 +336,7 @@ error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:178:14 | LL | for (_ | (_, _)) in [bool_pair] {} - | - ^^^^^^ unreachable pattern + | - ^^^^^^ no value can reach this | | | matches any value @@ -344,25 +344,25 @@ error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:181:20 | LL | let (Some(_) | Some(true)) = bool_option else { return }; - | ------- ^^^^^^^^^^ unreachable pattern + | ------- ^^^^^^^^^^ no value can reach this | | - | matches all the values already + | matches all the relevant values error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:183:22 | LL | if let Some(_) | Some(true) = bool_option {} - | ------- ^^^^^^^^^^ unreachable pattern + | ------- ^^^^^^^^^^ no value can reach this | | - | matches all the values already + | matches all the relevant values error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:185:25 | LL | while let Some(_) | Some(true) = bool_option {} - | ------- ^^^^^^^^^^ unreachable pattern + | ------- ^^^^^^^^^^ no value can reach this | | - | matches all the values already + | matches all the relevant values error: aborting due to 36 previous errors diff --git a/tests/ui/packed/packed-struct-address-of-element.rs b/tests/ui/packed/packed-struct-address-of-element.rs index 3fc27d4a96a..5d7c0b3d8b1 100644 --- a/tests/ui/packed/packed-struct-address-of-element.rs +++ b/tests/ui/packed/packed-struct-address-of-element.rs @@ -1,6 +1,5 @@ //@ run-pass #![allow(dead_code)] -#![feature(raw_ref_op)] //@ ignore-emscripten weird assertion? #[repr(packed)] diff --git a/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr index 1ba130e20b5..bd860841b80 100644 --- a/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr +++ b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr @@ -359,11 +359,6 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); } | previous outer attribute | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files -help: to annotate the item macro invocation, change the attribute from inner to outer style - | -LL - #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); } -LL + #[cfg(FALSE)] fn s() { #[attr] #[attr] foo!(); } - | error: an inner attribute is not permitted following an outer attribute --> $DIR/attr-stmt-expr-attr-bad.rs:77:32 @@ -375,11 +370,6 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; } | previous outer attribute | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files -help: to annotate the item macro invocation, change the attribute from inner to outer style - | -LL - #[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; } -LL + #[cfg(FALSE)] fn s() { #[attr] #[attr] foo![]; } - | error: an inner attribute is not permitted following an outer attribute --> $DIR/attr-stmt-expr-attr-bad.rs:79:32 @@ -391,11 +381,6 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; } | previous outer attribute | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files -help: to annotate the item macro invocation, change the attribute from inner to outer style - | -LL - #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; } -LL + #[cfg(FALSE)] fn s() { #[attr] #[attr] foo!{}; } - | error[E0586]: inclusive range with no end --> $DIR/attr-stmt-expr-attr-bad.rs:85:35 diff --git a/tests/ui/parser/attribute/attr.stderr b/tests/ui/parser/attribute/attr.stderr index 2e0b16efb6c..a79a5246c2a 100644 --- a/tests/ui/parser/attribute/attr.stderr +++ b/tests/ui/parser/attribute/attr.stderr @@ -7,11 +7,6 @@ LL | fn foo() {} | ----------- the inner attribute doesn't annotate this function | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files -help: to annotate the function, change the attribute from inner to outer style - | -LL - #![lang = "foo"] -LL + #[lang = "foo"] - | error: aborting due to 1 previous error diff --git a/tests/ui/parser/inner-attr-after-doc-comment.stderr b/tests/ui/parser/inner-attr-after-doc-comment.stderr index 6dbc0fd93fd..f087c2e4d65 100644 --- a/tests/ui/parser/inner-attr-after-doc-comment.stderr +++ b/tests/ui/parser/inner-attr-after-doc-comment.stderr @@ -13,11 +13,6 @@ LL | fn main() {} | ------------ the inner attribute doesn't annotate this function | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files -help: to annotate the function, change the attribute from inner to outer style - | -LL - #![recursion_limit="100"] -LL + #[recursion_limit="100"] - | error: aborting due to 1 previous error diff --git a/tests/ui/parser/inner-attr.stderr b/tests/ui/parser/inner-attr.stderr index 57ca164fc15..18a82ea4c38 100644 --- a/tests/ui/parser/inner-attr.stderr +++ b/tests/ui/parser/inner-attr.stderr @@ -10,11 +10,6 @@ LL | fn main() {} | ------------ the inner attribute doesn't annotate this function | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files -help: to annotate the function, change the attribute from inner to outer style - | -LL - #![recursion_limit="100"] -LL + #[recursion_limit="100"] - | error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/isgg-invalid-outer-attttr-issue-127930.rs b/tests/ui/parser/issues/isgg-invalid-outer-attttr-issue-127930.rs new file mode 100644 index 00000000000..26541a89a56 --- /dev/null +++ b/tests/ui/parser/issues/isgg-invalid-outer-attttr-issue-127930.rs @@ -0,0 +1,10 @@ +#![allow(dead_code)] +fn foo() {} + +#![feature(iter_array_chunks)] //~ ERROR an inner attribute is not permitted in this context +fn bar() {} + +fn main() { + foo(); + bar(); +} diff --git a/tests/ui/parser/issues/isgg-invalid-outer-attttr-issue-127930.stderr b/tests/ui/parser/issues/isgg-invalid-outer-attttr-issue-127930.stderr new file mode 100644 index 00000000000..d6daa21e741 --- /dev/null +++ b/tests/ui/parser/issues/isgg-invalid-outer-attttr-issue-127930.stderr @@ -0,0 +1,12 @@ +error: an inner attribute is not permitted in this context + --> $DIR/isgg-invalid-outer-attttr-issue-127930.rs:4:1 + | +LL | #![feature(iter_array_chunks)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn bar() {} + | ----------- the inner attribute doesn't annotate this function + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/issues/issue-30318.fixed b/tests/ui/parser/issues/issue-30318.fixed index d1661be5193..d4720834746 100644 --- a/tests/ui/parser/issues/issue-30318.fixed +++ b/tests/ui/parser/issues/issue-30318.fixed @@ -6,7 +6,7 @@ fn foo() { } //~^ ERROR expected outer doc comment fn bar() { } //~ NOTE the inner doc comment doesn't annotate this function -#[test] //~ ERROR an inner attribute is not permitted in this context +#[cfg(test)] //~ ERROR an inner attribute is not permitted in this context fn baz() { } //~ NOTE the inner attribute doesn't annotate this function //~^^ NOTE inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually diff --git a/tests/ui/parser/issues/issue-30318.rs b/tests/ui/parser/issues/issue-30318.rs index 6f055cd4f7e..0555379836a 100644 --- a/tests/ui/parser/issues/issue-30318.rs +++ b/tests/ui/parser/issues/issue-30318.rs @@ -6,7 +6,7 @@ fn foo() { } //~^ ERROR expected outer doc comment fn bar() { } //~ NOTE the inner doc comment doesn't annotate this function -#![test] //~ ERROR an inner attribute is not permitted in this context +#![cfg(test)] //~ ERROR an inner attribute is not permitted in this context fn baz() { } //~ NOTE the inner attribute doesn't annotate this function //~^^ NOTE inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually diff --git a/tests/ui/parser/issues/issue-30318.stderr b/tests/ui/parser/issues/issue-30318.stderr index c441a92abad..56bc200db1d 100644 --- a/tests/ui/parser/issues/issue-30318.stderr +++ b/tests/ui/parser/issues/issue-30318.stderr @@ -15,16 +15,16 @@ LL | /// Misplaced comment... error: an inner attribute is not permitted in this context --> $DIR/issue-30318.rs:9:1 | -LL | #![test] - | ^^^^^^^^ +LL | #![cfg(test)] + | ^^^^^^^^^^^^^ LL | fn baz() { } | ------------ the inner attribute doesn't annotate this function | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files help: to annotate the function, change the attribute from inner to outer style | -LL - #![test] -LL + #[test] +LL - #![cfg(test)] +LL + #[cfg(test)] | error[E0753]: expected outer doc comment diff --git a/tests/ui/pattern/issue-14221.stderr b/tests/ui/pattern/issue-14221.stderr index 7ea51b5f804..44b2923d606 100644 --- a/tests/ui/pattern/issue-14221.stderr +++ b/tests/ui/pattern/issue-14221.stderr @@ -19,7 +19,7 @@ LL | A => "A", | - matches any value LL | LL | B => "B", - | ^ unreachable pattern + | ^ no value can reach this | note: the lint level is defined here --> $DIR/issue-14221.rs:1:9 diff --git a/tests/ui/pattern/usefulness/consts-opaque.stderr b/tests/ui/pattern/usefulness/consts-opaque.stderr index 9d3a35321ca..32d385eecb4 100644 --- a/tests/ui/pattern/usefulness/consts-opaque.stderr +++ b/tests/ui/pattern/usefulness/consts-opaque.stderr @@ -52,7 +52,7 @@ error: unreachable pattern LL | Bar => {} | --- matches any value LL | BAR => {} - | ^^^ unreachable pattern + | ^^^ no value can reach this | note: the lint level is defined here --> $DIR/consts-opaque.rs:6:9 @@ -67,7 +67,7 @@ LL | Bar => {} | --- matches any value ... LL | _ => {} - | ^ unreachable pattern + | ^ no value can reach this error: unreachable pattern --> $DIR/consts-opaque.rs:56:9 @@ -75,7 +75,7 @@ error: unreachable pattern LL | BAR => {} | --- matches any value LL | Bar => {} - | ^^^ unreachable pattern + | ^^^ no value can reach this error: unreachable pattern --> $DIR/consts-opaque.rs:58:9 @@ -84,7 +84,7 @@ LL | BAR => {} | --- matches any value ... LL | _ => {} - | ^ unreachable pattern + | ^ no value can reach this error: unreachable pattern --> $DIR/consts-opaque.rs:64:9 @@ -92,7 +92,7 @@ error: unreachable pattern LL | BAR => {} | --- matches any value LL | BAR => {} // should not be emitting unreachable warning - | ^^^ unreachable pattern + | ^^^ no value can reach this error: unreachable pattern --> $DIR/consts-opaque.rs:66:9 @@ -101,31 +101,31 @@ LL | BAR => {} | --- matches any value ... LL | _ => {} // should not be emitting unreachable warning - | ^ unreachable pattern + | ^ no value can reach this error: unreachable pattern --> $DIR/consts-opaque.rs:72:9 | LL | BAZ => {} - | --- matches all the values already + | --- matches all the relevant values LL | Baz::Baz1 => {} // should not be emitting unreachable warning - | ^^^^^^^^^ unreachable pattern + | ^^^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/consts-opaque.rs:79:9 | LL | Baz::Baz1 => {} - | --------- matches all the values already + | --------- matches all the relevant values LL | BAZ => {} - | ^^^ unreachable pattern + | ^^^ no value can reach this error: unreachable pattern --> $DIR/consts-opaque.rs:87:9 | LL | _ => {} // should not be emitting unreachable warning - | ^ unreachable pattern + | ^ no value can reach this | -note: these patterns collectively make the last one unreachable +note: multiple earlier patterns match some of the same values --> $DIR/consts-opaque.rs:87:9 | LL | BAZ => {} diff --git a/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr index 1b65ff7aa57..60ab4d52c30 100644 --- a/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr +++ b/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr @@ -2,9 +2,9 @@ error: unreachable pattern --> $DIR/empty-match-check-notes.rs:17:9 | LL | _ => {} - | ^ + | ^ matches no values because `EmptyEnum` is uninhabited | - = note: this pattern matches no values because `EmptyEnum` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here --> $DIR/empty-match-check-notes.rs:7:9 | @@ -12,31 +12,31 @@ LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/empty-match-check-notes.rs:21:9 + --> $DIR/empty-match-check-notes.rs:22:9 | LL | _ if false => {} - | ^ + | ^ matches no values because `EmptyEnum` is uninhabited | - = note: this pattern matches no values because `EmptyEnum` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-match-check-notes.rs:29:9 + --> $DIR/empty-match-check-notes.rs:31:9 | LL | _ => {} - | ^ + | ^ matches no values because `EmptyForeignEnum` is uninhabited | - = note: this pattern matches no values because `EmptyForeignEnum` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-match-check-notes.rs:33:9 + --> $DIR/empty-match-check-notes.rs:36:9 | LL | _ if false => {} - | ^ + | ^ matches no values because `EmptyForeignEnum` is uninhabited | - = note: this pattern matches no values because `EmptyForeignEnum` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0005]: refutable pattern in local binding - --> $DIR/empty-match-check-notes.rs:39:9 + --> $DIR/empty-match-check-notes.rs:43:9 | LL | let None = *x; | ^^^^ pattern `Some(_)` not covered @@ -51,7 +51,7 @@ LL | if let None = *x { todo!() }; | ++ +++++++++++ error[E0004]: non-exhaustive patterns: `0_u8..=u8::MAX` not covered - --> $DIR/empty-match-check-notes.rs:49:11 + --> $DIR/empty-match-check-notes.rs:53:11 | LL | match 0u8 { | ^^^ pattern `0_u8..=u8::MAX` not covered diff --git a/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr b/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr index 1b65ff7aa57..60ab4d52c30 100644 --- a/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr +++ b/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr @@ -2,9 +2,9 @@ error: unreachable pattern --> $DIR/empty-match-check-notes.rs:17:9 | LL | _ => {} - | ^ + | ^ matches no values because `EmptyEnum` is uninhabited | - = note: this pattern matches no values because `EmptyEnum` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here --> $DIR/empty-match-check-notes.rs:7:9 | @@ -12,31 +12,31 @@ LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/empty-match-check-notes.rs:21:9 + --> $DIR/empty-match-check-notes.rs:22:9 | LL | _ if false => {} - | ^ + | ^ matches no values because `EmptyEnum` is uninhabited | - = note: this pattern matches no values because `EmptyEnum` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-match-check-notes.rs:29:9 + --> $DIR/empty-match-check-notes.rs:31:9 | LL | _ => {} - | ^ + | ^ matches no values because `EmptyForeignEnum` is uninhabited | - = note: this pattern matches no values because `EmptyForeignEnum` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-match-check-notes.rs:33:9 + --> $DIR/empty-match-check-notes.rs:36:9 | LL | _ if false => {} - | ^ + | ^ matches no values because `EmptyForeignEnum` is uninhabited | - = note: this pattern matches no values because `EmptyForeignEnum` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0005]: refutable pattern in local binding - --> $DIR/empty-match-check-notes.rs:39:9 + --> $DIR/empty-match-check-notes.rs:43:9 | LL | let None = *x; | ^^^^ pattern `Some(_)` not covered @@ -51,7 +51,7 @@ LL | if let None = *x { todo!() }; | ++ +++++++++++ error[E0004]: non-exhaustive patterns: `0_u8..=u8::MAX` not covered - --> $DIR/empty-match-check-notes.rs:49:11 + --> $DIR/empty-match-check-notes.rs:53:11 | LL | match 0u8 { | ^^^ pattern `0_u8..=u8::MAX` not covered diff --git a/tests/ui/pattern/usefulness/empty-match-check-notes.rs b/tests/ui/pattern/usefulness/empty-match-check-notes.rs index 61a75e6c801..48d20fd2d5c 100644 --- a/tests/ui/pattern/usefulness/empty-match-check-notes.rs +++ b/tests/ui/pattern/usefulness/empty-match-check-notes.rs @@ -16,10 +16,12 @@ fn empty_enum(x: EmptyEnum) { match x { _ => {} //~ ERROR unreachable pattern //~^ NOTE matches no values + //~| NOTE to learn more about uninhabited types, see } match x { _ if false => {} //~ ERROR unreachable pattern //~^ NOTE matches no values + //~| NOTE to learn more about uninhabited types, see } } @@ -28,10 +30,12 @@ fn empty_foreign_enum(x: empty::EmptyForeignEnum) { match x { _ => {} //~ ERROR unreachable pattern //~^ NOTE matches no values + //~| NOTE to learn more about uninhabited types, see } match x { _ if false => {} //~ ERROR unreachable pattern //~^ NOTE matches no values + //~| NOTE to learn more about uninhabited types, see } } diff --git a/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr index 17cb6fbd94b..9decddfe5de 100644 --- a/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr +++ b/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr @@ -2,9 +2,9 @@ error: unreachable pattern --> $DIR/empty-types.rs:49:9 | LL | _ => {} - | ^ + | ^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here --> $DIR/empty-types.rs:15:9 | @@ -15,9 +15,9 @@ error: unreachable pattern --> $DIR/empty-types.rs:52:9 | LL | _x => {} - | ^^ + | ^^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: type `&!` is non-empty --> $DIR/empty-types.rs:56:11 @@ -38,33 +38,33 @@ error: unreachable pattern --> $DIR/empty-types.rs:70:9 | LL | (_, _) => {} - | ^^^^^^ + | ^^^^^^ matches no values because `(u32, !)` is uninhabited | - = note: this pattern matches no values because `(u32, !)` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:76:9 | LL | _ => {} - | ^ + | ^ matches no values because `(!, !)` is uninhabited | - = note: this pattern matches no values because `(!, !)` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:79:9 | LL | (_, _) => {} - | ^^^^^^ + | ^^^^^^ matches no values because `(!, !)` is uninhabited | - = note: this pattern matches no values because `(!, !)` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:83:9 | LL | _ => {} - | ^ + | ^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: `Ok(_)` not covered --> $DIR/empty-types.rs:87:11 @@ -89,17 +89,17 @@ error: unreachable pattern --> $DIR/empty-types.rs:94:9 | LL | Err(_) => {} - | ^^^^^^ + | ^^^^^^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:99:9 | LL | Err(_) => {} - | ^^^^^^ + | ^^^^^^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered --> $DIR/empty-types.rs:96:11 @@ -137,156 +137,156 @@ error: unreachable pattern --> $DIR/empty-types.rs:112:9 | LL | _ => {} - | ^ + | ^ matches no values because `Result` is uninhabited | - = note: this pattern matches no values because `Result` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:115:9 | LL | Ok(_) => {} - | ^^^^^ + | ^^^^^ matches no values because `Result` is uninhabited | - = note: this pattern matches no values because `Result` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:118:9 | LL | Ok(_) => {} - | ^^^^^ + | ^^^^^ matches no values because `Result` is uninhabited | - = note: this pattern matches no values because `Result` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:119:9 | LL | _ => {} - | ^ + | ^ matches no values because `Result` is uninhabited | - = note: this pattern matches no values because `Result` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:122:9 | LL | Ok(_) => {} - | ^^^^^ + | ^^^^^ matches no values because `Result` is uninhabited | - = note: this pattern matches no values because `Result` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:123:9 | LL | Err(_) => {} - | ^^^^^^ + | ^^^^^^ matches no values because `Result` is uninhabited | - = note: this pattern matches no values because `Result` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:132:13 | LL | _ => {} - | ^ + | ^ matches no values because `Void` is uninhabited | - = note: this pattern matches no values because `Void` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:135:13 | LL | _ if false => {} - | ^ + | ^ matches no values because `Void` is uninhabited | - = note: this pattern matches no values because `Void` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:143:13 | LL | Some(_) => {} - | ^^^^^^^ + | ^^^^^^^ matches no values because `Void` is uninhabited | - = note: this pattern matches no values because `Void` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:147:13 | LL | None => {} - | ---- matches all the values already + | ---- matches all the relevant values LL | _ => {} - | ^ unreachable pattern + | ^ no value can reach this error: unreachable pattern --> $DIR/empty-types.rs:199:13 | LL | _ => {} - | ^ + | ^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:204:13 | LL | _ => {} - | ^ + | ^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:209:13 | LL | _ => {} - | ^ + | ^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:214:13 | LL | _ => {} - | ^ + | ^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:220:13 | LL | _ => {} - | ^ + | ^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:279:9 + --> $DIR/empty-types.rs:281:9 | LL | _ => {} - | ^ + | ^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:282:9 + --> $DIR/empty-types.rs:284:9 | LL | (_, _) => {} - | ^^^^^^ + | ^^^^^^ matches no values because `(!, !)` is uninhabited | - = note: this pattern matches no values because `(!, !)` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:285:9 + --> $DIR/empty-types.rs:287:9 | LL | Ok(_) => {} - | ^^^^^ + | ^^^^^ matches no values because `Result` is uninhabited | - = note: this pattern matches no values because `Result` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:286:9 + --> $DIR/empty-types.rs:288:9 | LL | Err(_) => {} - | ^^^^^^ + | ^^^^^^ matches no values because `Result` is uninhabited | - = note: this pattern matches no values because `Result` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty - --> $DIR/empty-types.rs:318:11 + --> $DIR/empty-types.rs:327:11 | LL | match slice_never {} | ^^^^^^^^^^^ @@ -300,7 +300,7 @@ LL + } | error[E0004]: non-exhaustive patterns: `&[]` not covered - --> $DIR/empty-types.rs:329:11 + --> $DIR/empty-types.rs:338:11 | LL | match slice_never { | ^^^^^^^^^^^ pattern `&[]` not covered @@ -313,7 +313,7 @@ LL + &[] => todo!() | error[E0004]: non-exhaustive patterns: `&[]` not covered - --> $DIR/empty-types.rs:343:11 + --> $DIR/empty-types.rs:352:11 | LL | match slice_never { | ^^^^^^^^^^^ pattern `&[]` not covered @@ -327,7 +327,7 @@ LL + &[] => todo!() | error[E0004]: non-exhaustive patterns: type `[!]` is non-empty - --> $DIR/empty-types.rs:350:11 + --> $DIR/empty-types.rs:359:11 | LL | match *slice_never {} | ^^^^^^^^^^^^ @@ -341,31 +341,31 @@ LL + } | error: unreachable pattern - --> $DIR/empty-types.rs:359:9 + --> $DIR/empty-types.rs:368:9 | LL | _ => {} - | ^ + | ^ matches no values because `[!; 3]` is uninhabited | - = note: this pattern matches no values because `[!; 3]` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:362:9 + --> $DIR/empty-types.rs:371:9 | LL | [_, _, _] => {} - | ^^^^^^^^^ + | ^^^^^^^^^ matches no values because `[!; 3]` is uninhabited | - = note: this pattern matches no values because `[!; 3]` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:365:9 + --> $DIR/empty-types.rs:374:9 | LL | [_, ..] => {} - | ^^^^^^^ + | ^^^^^^^ matches no values because `[!; 3]` is uninhabited | - = note: this pattern matches no values because `[!; 3]` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty - --> $DIR/empty-types.rs:379:11 + --> $DIR/empty-types.rs:388:11 | LL | match array_0_never {} | ^^^^^^^^^^^^^ @@ -379,15 +379,15 @@ LL + } | error: unreachable pattern - --> $DIR/empty-types.rs:386:9 + --> $DIR/empty-types.rs:395:9 | LL | [] => {} - | -- matches all the values already + | -- matches all the relevant values LL | _ => {} - | ^ unreachable pattern + | ^ no value can reach this error[E0004]: non-exhaustive patterns: `[]` not covered - --> $DIR/empty-types.rs:388:11 + --> $DIR/empty-types.rs:397:11 | LL | match array_0_never { | ^^^^^^^^^^^^^ pattern `[]` not covered @@ -401,70 +401,70 @@ LL + [] => todo!() | error: unreachable pattern - --> $DIR/empty-types.rs:407:9 + --> $DIR/empty-types.rs:416:9 | LL | Some(_) => {} - | ^^^^^^^ + | ^^^^^^^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:412:9 + --> $DIR/empty-types.rs:421:9 | LL | Some(_a) => {} - | ^^^^^^^^ + | ^^^^^^^^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:417:9 + --> $DIR/empty-types.rs:426:9 | LL | None => {} - | ---- matches all the values already + | ---- matches all the relevant values LL | // !useful, !reachable LL | _ => {} - | ^ unreachable pattern + | ^ no value can reach this error: unreachable pattern - --> $DIR/empty-types.rs:422:9 + --> $DIR/empty-types.rs:431:9 | LL | None => {} - | ---- matches all the values already + | ---- matches all the relevant values LL | // !useful, !reachable LL | _a => {} - | ^^ unreachable pattern - -error: unreachable pattern - --> $DIR/empty-types.rs:594:9 - | -LL | _ => {} - | ^ - | - = note: this pattern matches no values because `!` is uninhabited - -error: unreachable pattern - --> $DIR/empty-types.rs:597:9 - | -LL | _x => {} - | ^^ - | - = note: this pattern matches no values because `!` is uninhabited - -error: unreachable pattern - --> $DIR/empty-types.rs:600:9 - | -LL | _ if false => {} - | ^ - | - = note: this pattern matches no values because `!` is uninhabited + | ^^ no value can reach this error: unreachable pattern --> $DIR/empty-types.rs:603:9 | -LL | _x if false => {} - | ^^ +LL | _ => {} + | ^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types + +error: unreachable pattern + --> $DIR/empty-types.rs:606:9 + | +LL | _x => {} + | ^^ matches no values because `!` is uninhabited + | + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types + +error: unreachable pattern + --> $DIR/empty-types.rs:609:9 + | +LL | _ if false => {} + | ^ matches no values because `!` is uninhabited + | + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types + +error: unreachable pattern + --> $DIR/empty-types.rs:612:9 + | +LL | _x if false => {} + | ^^ matches no values because `!` is uninhabited + | + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: aborting due to 49 previous errors diff --git a/tests/ui/pattern/usefulness/empty-types.never_pats.stderr b/tests/ui/pattern/usefulness/empty-types.never_pats.stderr index 1ecb15f2cae..68213a2d661 100644 --- a/tests/ui/pattern/usefulness/empty-types.never_pats.stderr +++ b/tests/ui/pattern/usefulness/empty-types.never_pats.stderr @@ -11,9 +11,9 @@ error: unreachable pattern --> $DIR/empty-types.rs:49:9 | LL | _ => {} - | ^ + | ^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here --> $DIR/empty-types.rs:15:9 | @@ -24,9 +24,9 @@ error: unreachable pattern --> $DIR/empty-types.rs:52:9 | LL | _x => {} - | ^^ + | ^^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: type `&!` is non-empty --> $DIR/empty-types.rs:56:11 @@ -47,33 +47,33 @@ error: unreachable pattern --> $DIR/empty-types.rs:70:9 | LL | (_, _) => {} - | ^^^^^^ + | ^^^^^^ matches no values because `(u32, !)` is uninhabited | - = note: this pattern matches no values because `(u32, !)` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:76:9 | LL | _ => {} - | ^ + | ^ matches no values because `(!, !)` is uninhabited | - = note: this pattern matches no values because `(!, !)` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:79:9 | LL | (_, _) => {} - | ^^^^^^ + | ^^^^^^ matches no values because `(!, !)` is uninhabited | - = note: this pattern matches no values because `(!, !)` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:83:9 | LL | _ => {} - | ^ + | ^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: `Ok(_)` not covered --> $DIR/empty-types.rs:87:11 @@ -98,17 +98,17 @@ error: unreachable pattern --> $DIR/empty-types.rs:94:9 | LL | Err(_) => {} - | ^^^^^^ + | ^^^^^^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:99:9 | LL | Err(_) => {} - | ^^^^^^ + | ^^^^^^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered --> $DIR/empty-types.rs:96:11 @@ -160,81 +160,81 @@ error: unreachable pattern --> $DIR/empty-types.rs:112:9 | LL | _ => {} - | ^ + | ^ matches no values because `Result` is uninhabited | - = note: this pattern matches no values because `Result` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:115:9 | LL | Ok(_) => {} - | ^^^^^ + | ^^^^^ matches no values because `Result` is uninhabited | - = note: this pattern matches no values because `Result` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:118:9 | LL | Ok(_) => {} - | ^^^^^ + | ^^^^^ matches no values because `Result` is uninhabited | - = note: this pattern matches no values because `Result` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:119:9 | LL | _ => {} - | ^ + | ^ matches no values because `Result` is uninhabited | - = note: this pattern matches no values because `Result` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:122:9 | LL | Ok(_) => {} - | ^^^^^ + | ^^^^^ matches no values because `Result` is uninhabited | - = note: this pattern matches no values because `Result` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:123:9 | LL | Err(_) => {} - | ^^^^^^ + | ^^^^^^ matches no values because `Result` is uninhabited | - = note: this pattern matches no values because `Result` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:132:13 | LL | _ => {} - | ^ + | ^ matches no values because `Void` is uninhabited | - = note: this pattern matches no values because `Void` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:135:13 | LL | _ if false => {} - | ^ + | ^ matches no values because `Void` is uninhabited | - = note: this pattern matches no values because `Void` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:143:13 | LL | Some(_) => {} - | ^^^^^^^ + | ^^^^^^^ matches no values because `Void` is uninhabited | - = note: this pattern matches no values because `Void` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:147:13 | LL | None => {} - | ---- matches all the values already + | ---- matches all the relevant values LL | _ => {} - | ^ unreachable pattern + | ^ no value can reach this error[E0004]: non-exhaustive patterns: `Some(!)` not covered --> $DIR/empty-types.rs:156:15 @@ -259,76 +259,90 @@ error: unreachable pattern --> $DIR/empty-types.rs:199:13 | LL | _ => {} - | ^ + | ^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:204:13 | LL | _ => {} - | ^ + | ^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:209:13 | LL | _ => {} - | ^ + | ^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:214:13 | LL | _ => {} - | ^ + | ^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:220:13 | LL | _ => {} - | ^ + | ^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:279:9 + --> $DIR/empty-types.rs:281:9 | LL | _ => {} - | ^ + | ^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:282:9 + --> $DIR/empty-types.rs:284:9 | LL | (_, _) => {} - | ^^^^^^ + | ^^^^^^ matches no values because `(!, !)` is uninhabited | - = note: this pattern matches no values because `(!, !)` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:285:9 + --> $DIR/empty-types.rs:287:9 | LL | Ok(_) => {} - | ^^^^^ + | ^^^^^ matches no values because `Result` is uninhabited | - = note: this pattern matches no values because `Result` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:286:9 + --> $DIR/empty-types.rs:288:9 | LL | Err(_) => {} - | ^^^^^^ + | ^^^^^^ matches no values because `Result` is uninhabited | - = note: this pattern matches no values because `Result` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types + +error[E0005]: refutable pattern in local binding + --> $DIR/empty-types.rs:297:13 + | +LL | let Ok(_) = *ptr_result_never_err; + | ^^^^^ pattern `Err(!)` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `Result` +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let Ok(_) = *ptr_result_never_err { todo!() }; + | ++ +++++++++++ error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty - --> $DIR/empty-types.rs:307:11 + --> $DIR/empty-types.rs:316:11 | LL | match *x {} | ^^ @@ -342,7 +356,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: type `(!, !)` is non-empty - --> $DIR/empty-types.rs:309:11 + --> $DIR/empty-types.rs:318:11 | LL | match *x {} | ^^ @@ -356,7 +370,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: `Ok(!)` and `Err(!)` not covered - --> $DIR/empty-types.rs:311:11 + --> $DIR/empty-types.rs:320:11 | LL | match *x {} | ^^ patterns `Ok(!)` and `Err(!)` not covered @@ -378,7 +392,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: type `[!; 3]` is non-empty - --> $DIR/empty-types.rs:313:11 + --> $DIR/empty-types.rs:322:11 | LL | match *x {} | ^^ @@ -392,7 +406,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty - --> $DIR/empty-types.rs:318:11 + --> $DIR/empty-types.rs:327:11 | LL | match slice_never {} | ^^^^^^^^^^^ @@ -406,7 +420,7 @@ LL + } | error[E0004]: non-exhaustive patterns: `&[!, ..]` not covered - --> $DIR/empty-types.rs:320:11 + --> $DIR/empty-types.rs:329:11 | LL | match slice_never { | ^^^^^^^^^^^ pattern `&[!, ..]` not covered @@ -420,7 +434,7 @@ LL + &[!, ..] | error[E0004]: non-exhaustive patterns: `&[]`, `&[!]` and `&[!, !]` not covered - --> $DIR/empty-types.rs:329:11 + --> $DIR/empty-types.rs:338:11 | LL | match slice_never { | ^^^^^^^^^^^ patterns `&[]`, `&[!]` and `&[!, !]` not covered @@ -433,7 +447,7 @@ LL + &[] | &[!] | &[!, !] => todo!() | error[E0004]: non-exhaustive patterns: `&[]` and `&[!, ..]` not covered - --> $DIR/empty-types.rs:343:11 + --> $DIR/empty-types.rs:352:11 | LL | match slice_never { | ^^^^^^^^^^^ patterns `&[]` and `&[!, ..]` not covered @@ -447,7 +461,7 @@ LL + &[] | &[!, ..] => todo!() | error[E0004]: non-exhaustive patterns: type `[!]` is non-empty - --> $DIR/empty-types.rs:350:11 + --> $DIR/empty-types.rs:359:11 | LL | match *slice_never {} | ^^^^^^^^^^^^ @@ -461,31 +475,31 @@ LL + } | error: unreachable pattern - --> $DIR/empty-types.rs:359:9 + --> $DIR/empty-types.rs:368:9 | LL | _ => {} - | ^ + | ^ matches no values because `[!; 3]` is uninhabited | - = note: this pattern matches no values because `[!; 3]` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:362:9 + --> $DIR/empty-types.rs:371:9 | LL | [_, _, _] => {} - | ^^^^^^^^^ + | ^^^^^^^^^ matches no values because `[!; 3]` is uninhabited | - = note: this pattern matches no values because `[!; 3]` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:365:9 + --> $DIR/empty-types.rs:374:9 | LL | [_, ..] => {} - | ^^^^^^^ + | ^^^^^^^ matches no values because `[!; 3]` is uninhabited | - = note: this pattern matches no values because `[!; 3]` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty - --> $DIR/empty-types.rs:379:11 + --> $DIR/empty-types.rs:388:11 | LL | match array_0_never {} | ^^^^^^^^^^^^^ @@ -499,15 +513,15 @@ LL + } | error: unreachable pattern - --> $DIR/empty-types.rs:386:9 + --> $DIR/empty-types.rs:395:9 | LL | [] => {} - | -- matches all the values already + | -- matches all the relevant values LL | _ => {} - | ^ unreachable pattern + | ^ no value can reach this error[E0004]: non-exhaustive patterns: `[]` not covered - --> $DIR/empty-types.rs:388:11 + --> $DIR/empty-types.rs:397:11 | LL | match array_0_never { | ^^^^^^^^^^^^^ pattern `[]` not covered @@ -521,41 +535,41 @@ LL + [] => todo!() | error: unreachable pattern - --> $DIR/empty-types.rs:407:9 + --> $DIR/empty-types.rs:416:9 | LL | Some(_) => {} - | ^^^^^^^ + | ^^^^^^^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:412:9 + --> $DIR/empty-types.rs:421:9 | LL | Some(_a) => {} - | ^^^^^^^^ + | ^^^^^^^^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:417:9 + --> $DIR/empty-types.rs:426:9 | LL | None => {} - | ---- matches all the values already + | ---- matches all the relevant values LL | // !useful, !reachable LL | _ => {} - | ^ unreachable pattern + | ^ no value can reach this error: unreachable pattern - --> $DIR/empty-types.rs:422:9 + --> $DIR/empty-types.rs:431:9 | LL | None => {} - | ---- matches all the values already + | ---- matches all the relevant values LL | // !useful, !reachable LL | _a => {} - | ^^ unreachable pattern + | ^^ no value can reach this error[E0004]: non-exhaustive patterns: `&Some(!)` not covered - --> $DIR/empty-types.rs:442:11 + --> $DIR/empty-types.rs:451:11 | LL | match ref_opt_never { | ^^^^^^^^^^^^^ pattern `&Some(!)` not covered @@ -574,7 +588,7 @@ LL + &Some(!) | error[E0004]: non-exhaustive patterns: `Some(!)` not covered - --> $DIR/empty-types.rs:483:11 + --> $DIR/empty-types.rs:492:11 | LL | match *ref_opt_never { | ^^^^^^^^^^^^^^ pattern `Some(!)` not covered @@ -593,7 +607,7 @@ LL + Some(!) | error[E0004]: non-exhaustive patterns: `Err(!)` not covered - --> $DIR/empty-types.rs:531:11 + --> $DIR/empty-types.rs:540:11 | LL | match *ref_res_never { | ^^^^^^^^^^^^^^ pattern `Err(!)` not covered @@ -612,7 +626,7 @@ LL + Err(!) | error[E0004]: non-exhaustive patterns: `Err(!)` not covered - --> $DIR/empty-types.rs:542:11 + --> $DIR/empty-types.rs:551:11 | LL | match *ref_res_never { | ^^^^^^^^^^^^^^ pattern `Err(!)` not covered @@ -631,7 +645,7 @@ LL + Err(!) | error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty - --> $DIR/empty-types.rs:561:11 + --> $DIR/empty-types.rs:570:11 | LL | match *ref_tuple_half_never {} | ^^^^^^^^^^^^^^^^^^^^^ @@ -644,40 +658,40 @@ LL + _ => todo!(), LL + } | -error: unreachable pattern - --> $DIR/empty-types.rs:594:9 - | -LL | _ => {} - | ^ - | - = note: this pattern matches no values because `!` is uninhabited - -error: unreachable pattern - --> $DIR/empty-types.rs:597:9 - | -LL | _x => {} - | ^^ - | - = note: this pattern matches no values because `!` is uninhabited - -error: unreachable pattern - --> $DIR/empty-types.rs:600:9 - | -LL | _ if false => {} - | ^ - | - = note: this pattern matches no values because `!` is uninhabited - error: unreachable pattern --> $DIR/empty-types.rs:603:9 | -LL | _x if false => {} - | ^^ +LL | _ => {} + | ^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types + +error: unreachable pattern + --> $DIR/empty-types.rs:606:9 + | +LL | _x => {} + | ^^ matches no values because `!` is uninhabited + | + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types + +error: unreachable pattern + --> $DIR/empty-types.rs:609:9 + | +LL | _ if false => {} + | ^ matches no values because `!` is uninhabited + | + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types + +error: unreachable pattern + --> $DIR/empty-types.rs:612:9 + | +LL | _x if false => {} + | ^^ matches no values because `!` is uninhabited + | + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: `&!` not covered - --> $DIR/empty-types.rs:628:11 + --> $DIR/empty-types.rs:637:11 | LL | match ref_never { | ^^^^^^^^^ pattern `&!` not covered @@ -693,7 +707,7 @@ LL + &! | error[E0004]: non-exhaustive patterns: `Ok(!)` not covered - --> $DIR/empty-types.rs:644:11 + --> $DIR/empty-types.rs:653:11 | LL | match *ref_result_never { | ^^^^^^^^^^^^^^^^^ pattern `Ok(!)` not covered @@ -712,7 +726,7 @@ LL + Ok(!) | error[E0004]: non-exhaustive patterns: `Some(!)` not covered - --> $DIR/empty-types.rs:664:11 + --> $DIR/empty-types.rs:673:11 | LL | match *x { | ^^ pattern `Some(!)` not covered @@ -730,7 +744,7 @@ LL ~ None => {}, LL + Some(!) | -error: aborting due to 64 previous errors; 1 warning emitted +error: aborting due to 65 previous errors; 1 warning emitted Some errors have detailed explanations: E0004, E0005. For more information about an error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/empty-types.normal.stderr b/tests/ui/pattern/usefulness/empty-types.normal.stderr index c3421cd592e..8f60dad4467 100644 --- a/tests/ui/pattern/usefulness/empty-types.normal.stderr +++ b/tests/ui/pattern/usefulness/empty-types.normal.stderr @@ -2,9 +2,9 @@ error: unreachable pattern --> $DIR/empty-types.rs:49:9 | LL | _ => {} - | ^ + | ^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here --> $DIR/empty-types.rs:15:9 | @@ -15,9 +15,9 @@ error: unreachable pattern --> $DIR/empty-types.rs:52:9 | LL | _x => {} - | ^^ + | ^^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: type `&!` is non-empty --> $DIR/empty-types.rs:56:11 @@ -38,33 +38,33 @@ error: unreachable pattern --> $DIR/empty-types.rs:70:9 | LL | (_, _) => {} - | ^^^^^^ + | ^^^^^^ matches no values because `(u32, !)` is uninhabited | - = note: this pattern matches no values because `(u32, !)` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:76:9 | LL | _ => {} - | ^ + | ^ matches no values because `(!, !)` is uninhabited | - = note: this pattern matches no values because `(!, !)` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:79:9 | LL | (_, _) => {} - | ^^^^^^ + | ^^^^^^ matches no values because `(!, !)` is uninhabited | - = note: this pattern matches no values because `(!, !)` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:83:9 | LL | _ => {} - | ^ + | ^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: `Ok(_)` not covered --> $DIR/empty-types.rs:87:11 @@ -89,17 +89,17 @@ error: unreachable pattern --> $DIR/empty-types.rs:94:9 | LL | Err(_) => {} - | ^^^^^^ + | ^^^^^^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:99:9 | LL | Err(_) => {} - | ^^^^^^ + | ^^^^^^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered --> $DIR/empty-types.rs:96:11 @@ -151,81 +151,81 @@ error: unreachable pattern --> $DIR/empty-types.rs:112:9 | LL | _ => {} - | ^ + | ^ matches no values because `Result` is uninhabited | - = note: this pattern matches no values because `Result` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:115:9 | LL | Ok(_) => {} - | ^^^^^ + | ^^^^^ matches no values because `Result` is uninhabited | - = note: this pattern matches no values because `Result` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:118:9 | LL | Ok(_) => {} - | ^^^^^ + | ^^^^^ matches no values because `Result` is uninhabited | - = note: this pattern matches no values because `Result` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:119:9 | LL | _ => {} - | ^ + | ^ matches no values because `Result` is uninhabited | - = note: this pattern matches no values because `Result` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:122:9 | LL | Ok(_) => {} - | ^^^^^ + | ^^^^^ matches no values because `Result` is uninhabited | - = note: this pattern matches no values because `Result` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:123:9 | LL | Err(_) => {} - | ^^^^^^ + | ^^^^^^ matches no values because `Result` is uninhabited | - = note: this pattern matches no values because `Result` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:132:13 | LL | _ => {} - | ^ + | ^ matches no values because `Void` is uninhabited | - = note: this pattern matches no values because `Void` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:135:13 | LL | _ if false => {} - | ^ + | ^ matches no values because `Void` is uninhabited | - = note: this pattern matches no values because `Void` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:143:13 | LL | Some(_) => {} - | ^^^^^^^ + | ^^^^^^^ matches no values because `Void` is uninhabited | - = note: this pattern matches no values because `Void` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:147:13 | LL | None => {} - | ---- matches all the values already + | ---- matches all the relevant values LL | _ => {} - | ^ unreachable pattern + | ^ no value can reach this error[E0004]: non-exhaustive patterns: `Some(_)` not covered --> $DIR/empty-types.rs:156:15 @@ -250,76 +250,90 @@ error: unreachable pattern --> $DIR/empty-types.rs:199:13 | LL | _ => {} - | ^ + | ^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:204:13 | LL | _ => {} - | ^ + | ^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:209:13 | LL | _ => {} - | ^ + | ^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:214:13 | LL | _ => {} - | ^ + | ^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/empty-types.rs:220:13 | LL | _ => {} - | ^ + | ^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:279:9 + --> $DIR/empty-types.rs:281:9 | LL | _ => {} - | ^ + | ^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:282:9 + --> $DIR/empty-types.rs:284:9 | LL | (_, _) => {} - | ^^^^^^ + | ^^^^^^ matches no values because `(!, !)` is uninhabited | - = note: this pattern matches no values because `(!, !)` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:285:9 + --> $DIR/empty-types.rs:287:9 | LL | Ok(_) => {} - | ^^^^^ + | ^^^^^ matches no values because `Result` is uninhabited | - = note: this pattern matches no values because `Result` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:286:9 + --> $DIR/empty-types.rs:288:9 | LL | Err(_) => {} - | ^^^^^^ + | ^^^^^^ matches no values because `Result` is uninhabited | - = note: this pattern matches no values because `Result` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types + +error[E0005]: refutable pattern in local binding + --> $DIR/empty-types.rs:297:13 + | +LL | let Ok(_) = *ptr_result_never_err; + | ^^^^^ pattern `Err(_)` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `Result` +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let Ok(_) = *ptr_result_never_err { todo!() }; + | ++ +++++++++++ error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty - --> $DIR/empty-types.rs:307:11 + --> $DIR/empty-types.rs:316:11 | LL | match *x {} | ^^ @@ -333,7 +347,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: type `(!, !)` is non-empty - --> $DIR/empty-types.rs:309:11 + --> $DIR/empty-types.rs:318:11 | LL | match *x {} | ^^ @@ -347,7 +361,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: `Ok(_)` and `Err(_)` not covered - --> $DIR/empty-types.rs:311:11 + --> $DIR/empty-types.rs:320:11 | LL | match *x {} | ^^ patterns `Ok(_)` and `Err(_)` not covered @@ -369,7 +383,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: type `[!; 3]` is non-empty - --> $DIR/empty-types.rs:313:11 + --> $DIR/empty-types.rs:322:11 | LL | match *x {} | ^^ @@ -383,7 +397,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty - --> $DIR/empty-types.rs:318:11 + --> $DIR/empty-types.rs:327:11 | LL | match slice_never {} | ^^^^^^^^^^^ @@ -397,7 +411,7 @@ LL + } | error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered - --> $DIR/empty-types.rs:320:11 + --> $DIR/empty-types.rs:329:11 | LL | match slice_never { | ^^^^^^^^^^^ pattern `&[_, ..]` not covered @@ -411,7 +425,7 @@ LL + &[_, ..] => todo!() | error[E0004]: non-exhaustive patterns: `&[]`, `&[_]` and `&[_, _]` not covered - --> $DIR/empty-types.rs:329:11 + --> $DIR/empty-types.rs:338:11 | LL | match slice_never { | ^^^^^^^^^^^ patterns `&[]`, `&[_]` and `&[_, _]` not covered @@ -424,7 +438,7 @@ LL + &[] | &[_] | &[_, _] => todo!() | error[E0004]: non-exhaustive patterns: `&[]` and `&[_, ..]` not covered - --> $DIR/empty-types.rs:343:11 + --> $DIR/empty-types.rs:352:11 | LL | match slice_never { | ^^^^^^^^^^^ patterns `&[]` and `&[_, ..]` not covered @@ -438,7 +452,7 @@ LL + &[] | &[_, ..] => todo!() | error[E0004]: non-exhaustive patterns: type `[!]` is non-empty - --> $DIR/empty-types.rs:350:11 + --> $DIR/empty-types.rs:359:11 | LL | match *slice_never {} | ^^^^^^^^^^^^ @@ -452,31 +466,31 @@ LL + } | error: unreachable pattern - --> $DIR/empty-types.rs:359:9 + --> $DIR/empty-types.rs:368:9 | LL | _ => {} - | ^ + | ^ matches no values because `[!; 3]` is uninhabited | - = note: this pattern matches no values because `[!; 3]` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:362:9 + --> $DIR/empty-types.rs:371:9 | LL | [_, _, _] => {} - | ^^^^^^^^^ + | ^^^^^^^^^ matches no values because `[!; 3]` is uninhabited | - = note: this pattern matches no values because `[!; 3]` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:365:9 + --> $DIR/empty-types.rs:374:9 | LL | [_, ..] => {} - | ^^^^^^^ + | ^^^^^^^ matches no values because `[!; 3]` is uninhabited | - = note: this pattern matches no values because `[!; 3]` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty - --> $DIR/empty-types.rs:379:11 + --> $DIR/empty-types.rs:388:11 | LL | match array_0_never {} | ^^^^^^^^^^^^^ @@ -490,15 +504,15 @@ LL + } | error: unreachable pattern - --> $DIR/empty-types.rs:386:9 + --> $DIR/empty-types.rs:395:9 | LL | [] => {} - | -- matches all the values already + | -- matches all the relevant values LL | _ => {} - | ^ unreachable pattern + | ^ no value can reach this error[E0004]: non-exhaustive patterns: `[]` not covered - --> $DIR/empty-types.rs:388:11 + --> $DIR/empty-types.rs:397:11 | LL | match array_0_never { | ^^^^^^^^^^^^^ pattern `[]` not covered @@ -512,41 +526,41 @@ LL + [] => todo!() | error: unreachable pattern - --> $DIR/empty-types.rs:407:9 + --> $DIR/empty-types.rs:416:9 | LL | Some(_) => {} - | ^^^^^^^ + | ^^^^^^^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:412:9 + --> $DIR/empty-types.rs:421:9 | LL | Some(_a) => {} - | ^^^^^^^^ + | ^^^^^^^^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:417:9 + --> $DIR/empty-types.rs:426:9 | LL | None => {} - | ---- matches all the values already + | ---- matches all the relevant values LL | // !useful, !reachable LL | _ => {} - | ^ unreachable pattern + | ^ no value can reach this error: unreachable pattern - --> $DIR/empty-types.rs:422:9 + --> $DIR/empty-types.rs:431:9 | LL | None => {} - | ---- matches all the values already + | ---- matches all the relevant values LL | // !useful, !reachable LL | _a => {} - | ^^ unreachable pattern + | ^^ no value can reach this error[E0004]: non-exhaustive patterns: `&Some(_)` not covered - --> $DIR/empty-types.rs:442:11 + --> $DIR/empty-types.rs:451:11 | LL | match ref_opt_never { | ^^^^^^^^^^^^^ pattern `&Some(_)` not covered @@ -565,7 +579,7 @@ LL + &Some(_) => todo!() | error[E0004]: non-exhaustive patterns: `Some(_)` not covered - --> $DIR/empty-types.rs:483:11 + --> $DIR/empty-types.rs:492:11 | LL | match *ref_opt_never { | ^^^^^^^^^^^^^^ pattern `Some(_)` not covered @@ -584,7 +598,7 @@ LL + Some(_) => todo!() | error[E0004]: non-exhaustive patterns: `Err(_)` not covered - --> $DIR/empty-types.rs:531:11 + --> $DIR/empty-types.rs:540:11 | LL | match *ref_res_never { | ^^^^^^^^^^^^^^ pattern `Err(_)` not covered @@ -603,7 +617,7 @@ LL + Err(_) => todo!() | error[E0004]: non-exhaustive patterns: `Err(_)` not covered - --> $DIR/empty-types.rs:542:11 + --> $DIR/empty-types.rs:551:11 | LL | match *ref_res_never { | ^^^^^^^^^^^^^^ pattern `Err(_)` not covered @@ -622,7 +636,7 @@ LL + Err(_) => todo!() | error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty - --> $DIR/empty-types.rs:561:11 + --> $DIR/empty-types.rs:570:11 | LL | match *ref_tuple_half_never {} | ^^^^^^^^^^^^^^^^^^^^^ @@ -635,40 +649,40 @@ LL + _ => todo!(), LL + } | -error: unreachable pattern - --> $DIR/empty-types.rs:594:9 - | -LL | _ => {} - | ^ - | - = note: this pattern matches no values because `!` is uninhabited - -error: unreachable pattern - --> $DIR/empty-types.rs:597:9 - | -LL | _x => {} - | ^^ - | - = note: this pattern matches no values because `!` is uninhabited - -error: unreachable pattern - --> $DIR/empty-types.rs:600:9 - | -LL | _ if false => {} - | ^ - | - = note: this pattern matches no values because `!` is uninhabited - error: unreachable pattern --> $DIR/empty-types.rs:603:9 | -LL | _x if false => {} - | ^^ +LL | _ => {} + | ^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types + +error: unreachable pattern + --> $DIR/empty-types.rs:606:9 + | +LL | _x => {} + | ^^ matches no values because `!` is uninhabited + | + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types + +error: unreachable pattern + --> $DIR/empty-types.rs:609:9 + | +LL | _ if false => {} + | ^ matches no values because `!` is uninhabited + | + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types + +error: unreachable pattern + --> $DIR/empty-types.rs:612:9 + | +LL | _x if false => {} + | ^^ matches no values because `!` is uninhabited + | + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: `&_` not covered - --> $DIR/empty-types.rs:628:11 + --> $DIR/empty-types.rs:637:11 | LL | match ref_never { | ^^^^^^^^^ pattern `&_` not covered @@ -684,7 +698,7 @@ LL + &_ => todo!() | error[E0004]: non-exhaustive patterns: `Ok(_)` not covered - --> $DIR/empty-types.rs:644:11 + --> $DIR/empty-types.rs:653:11 | LL | match *ref_result_never { | ^^^^^^^^^^^^^^^^^ pattern `Ok(_)` not covered @@ -703,7 +717,7 @@ LL + Ok(_) => todo!() | error[E0004]: non-exhaustive patterns: `Some(_)` not covered - --> $DIR/empty-types.rs:664:11 + --> $DIR/empty-types.rs:673:11 | LL | match *x { | ^^ pattern `Some(_)` not covered @@ -721,7 +735,7 @@ LL ~ None => {}, LL + Some(_) => todo!() | -error: aborting due to 64 previous errors +error: aborting due to 65 previous errors Some errors have detailed explanations: E0004, E0005. For more information about an error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/empty-types.rs b/tests/ui/pattern/usefulness/empty-types.rs index 639c48cea12..d561a0e9c12 100644 --- a/tests/ui/pattern/usefulness/empty-types.rs +++ b/tests/ui/pattern/usefulness/empty-types.rs @@ -17,7 +17,7 @@ #[derive(Copy, Clone)] enum Void {} -/// A bunch of never situations that can't be normally constructed. +/// A bunch of never situations that can't be normally constructed so we take them as argument. #[derive(Copy, Clone)] struct NeverBundle { never: !, @@ -272,6 +272,8 @@ fn nested_validity_tracking(bundle: NeverBundle) { let ref_never: &! = &never; let tuple_never: (!, !) = bundle.tuple_never; let result_never: Result = bundle.result_never; + let result_never_err: Result = Ok(0); + let ptr_result_never_err: *const Result = &result_never_err as *const _; let union_never = Uninit::::new(); // These should be considered known_valid and warn unreachable. @@ -287,6 +289,13 @@ fn nested_validity_tracking(bundle: NeverBundle) { } // These should be considered !known_valid and not warn unreachable. + unsafe { + match *ptr_result_never_err { + Ok(_) => {} + Err(_) => {} + } + let Ok(_) = *ptr_result_never_err; //[normal,never_pats]~ ERROR refutable pattern + } match ref_never { &_ => {} } diff --git a/tests/ui/pattern/usefulness/explain-unreachable-pats.rs b/tests/ui/pattern/usefulness/explain-unreachable-pats.rs index 44d194055d9..1cfa5212414 100644 --- a/tests/ui/pattern/usefulness/explain-unreachable-pats.rs +++ b/tests/ui/pattern/usefulness/explain-unreachable-pats.rs @@ -6,10 +6,10 @@ fn main() { match (0u8,) { (1 | 2,) => {} - //~^ NOTE matches all the values already + //~^ NOTE matches all the relevant values (2,) => {} //~^ ERROR unreachable pattern - //~| NOTE unreachable pattern + //~| NOTE no value can reach this _ => {} } @@ -20,18 +20,38 @@ fn main() { //~^ NOTE matches some of the same values (1 | 2,) => {} //~^ ERROR unreachable pattern - //~| NOTE unreachable pattern - //~| NOTE these patterns collectively make the last one unreachable + //~| NOTE no value can reach this + //~| NOTE multiple earlier patterns match some of the same values //~| NOTE collectively making this unreachable _ => {} } + match 0u8 { + 1 => {} + //~^ NOTE matches some of the same values + 2 => {} + //~^ NOTE matches some of the same values + 3 => {} + //~^ NOTE matches some of the same values + 4 => {} + //~^ NOTE matches some of the same values + 5 => {} + 6 => {} + 1 ..= 6 => {} + //~^ ERROR unreachable pattern + //~| NOTE no value can reach this + //~| NOTE multiple earlier patterns match some of the same values + //~| NOTE ...and 2 other patterns + _ => {} + } + let res: Result<(),!> = Ok(()); match res { Ok(_) => {} Err(_) => {} //~^ ERROR unreachable pattern - //~| NOTE this pattern matches no values because `!` is uninhabited + //~| NOTE matches no values because `!` is uninhabited + //~| NOTE to learn more about uninhabited types, see } #[derive(Copy, Clone)] @@ -44,22 +64,24 @@ fn main() { match (&res1, res2) { (Err(_), Err(_)) => {} //~^ ERROR unreachable pattern - //~| NOTE this pattern matches no values because `Void2` is uninhabited + //~| NOTE matches no values because `Void2` is uninhabited + //~| NOTE to learn more about uninhabited types, see _ => {} } match (res1, &res2) { (Err(_), Err(_)) => {} //~^ ERROR unreachable pattern - //~| NOTE this pattern matches no values because `Void1` is uninhabited + //~| NOTE matches no values because `Void1` is uninhabited + //~| NOTE to learn more about uninhabited types, see _ => {} } if let (0 - //~^ NOTE matches all the values already + //~^ NOTE matches all the relevant values | 0, _) = (0, 0) {} //~^ ERROR unreachable pattern - //~| NOTE unreachable pattern + //~| NOTE no value can reach this match (true, true) { (_, true) if false => {} // Guarded patterns don't cover others @@ -69,20 +91,20 @@ fn main() { //~^ NOTE matches some of the same values (_, true) => {} //~^ ERROR unreachable pattern - //~| NOTE unreachable pattern - //~| NOTE these patterns collectively make the last one unreachable + //~| NOTE no value can reach this + //~| NOTE multiple earlier patterns match some of the same values //~| NOTE collectively making this unreachable } match (true, true) { (true, _) => {} - //~^ NOTE matches all the values already + //~^ NOTE matches all the relevant values (false, _) => {} #[allow(unreachable_patterns)] (_, true) => {} // Doesn't cover below because it's already unreachable. (true, true) => {} //~^ ERROR unreachable pattern - //~| NOTE unreachable pattern + //~| NOTE no value can reach this } // Despite skipping some irrelevant cases, we still report a set of rows that covers the @@ -90,11 +112,11 @@ fn main() { match (true, true, 0) { (true, _, _) => {} (_, true, 0..10) => {} - //~^ NOTE matches all the values already + //~^ NOTE matches all the relevant values (_, true, 10..) => {} (_, true, 3) => {} //~^ ERROR unreachable pattern - //~| NOTE unreachable pattern + //~| NOTE no value can reach this _ => {} } } diff --git a/tests/ui/pattern/usefulness/explain-unreachable-pats.stderr b/tests/ui/pattern/usefulness/explain-unreachable-pats.stderr index 105d4f73f66..7023c2775e9 100644 --- a/tests/ui/pattern/usefulness/explain-unreachable-pats.stderr +++ b/tests/ui/pattern/usefulness/explain-unreachable-pats.stderr @@ -2,10 +2,10 @@ error: unreachable pattern --> $DIR/explain-unreachable-pats.rs:10:9 | LL | (1 | 2,) => {} - | -------- matches all the values already + | -------- matches all the relevant values LL | LL | (2,) => {} - | ^^^^ unreachable pattern + | ^^^^ no value can reach this | note: the lint level is defined here --> $DIR/explain-unreachable-pats.rs:2:9 @@ -17,9 +17,9 @@ error: unreachable pattern --> $DIR/explain-unreachable-pats.rs:21:9 | LL | (1 | 2,) => {} - | ^^^^^^^^ unreachable pattern + | ^^^^^^^^ no value can reach this | -note: these patterns collectively make the last one unreachable +note: multiple earlier patterns match some of the same values --> $DIR/explain-unreachable-pats.rs:21:9 | LL | (1,) => {} @@ -32,46 +32,70 @@ LL | (1 | 2,) => {} | ^^^^^^^^ collectively making this unreachable error: unreachable pattern - --> $DIR/explain-unreachable-pats.rs:32:9 + --> $DIR/explain-unreachable-pats.rs:40:9 | -LL | Err(_) => {} - | ^^^^^^ +LL | 1 ..= 6 => {} + | ^^^^^^^ no value can reach this | - = note: this pattern matches no values because `!` is uninhabited - -error: unreachable pattern - --> $DIR/explain-unreachable-pats.rs:45:9 +note: multiple earlier patterns match some of the same values + --> $DIR/explain-unreachable-pats.rs:40:9 | -LL | (Err(_), Err(_)) => {} - | ^^^^^^^^^^^^^^^^ - | - = note: this pattern matches no values because `Void2` is uninhabited +LL | 1 => {} + | - matches some of the same values +LL | +LL | 2 => {} + | - matches some of the same values +LL | +LL | 3 => {} + | - matches some of the same values +LL | +LL | 4 => {} + | - matches some of the same values +... +LL | 1 ..= 6 => {} + | ^^^^^^^ ...and 2 other patterns collectively make this unreachable error: unreachable pattern --> $DIR/explain-unreachable-pats.rs:51:9 | -LL | (Err(_), Err(_)) => {} - | ^^^^^^^^^^^^^^^^ +LL | Err(_) => {} + | ^^^^^^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `Void1` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/explain-unreachable-pats.rs:60:11 + --> $DIR/explain-unreachable-pats.rs:65:9 + | +LL | (Err(_), Err(_)) => {} + | ^^^^^^^^^^^^^^^^ matches no values because `Void2` is uninhabited + | + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types + +error: unreachable pattern + --> $DIR/explain-unreachable-pats.rs:72:9 + | +LL | (Err(_), Err(_)) => {} + | ^^^^^^^^^^^^^^^^ matches no values because `Void1` is uninhabited + | + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types + +error: unreachable pattern + --> $DIR/explain-unreachable-pats.rs:82:11 | LL | if let (0 - | - matches all the values already + | - matches all the relevant values LL | LL | | 0, _) = (0, 0) {} - | ^ unreachable pattern + | ^ no value can reach this error: unreachable pattern - --> $DIR/explain-unreachable-pats.rs:70:9 + --> $DIR/explain-unreachable-pats.rs:92:9 | LL | (_, true) => {} - | ^^^^^^^^^ unreachable pattern + | ^^^^^^^^^ no value can reach this | -note: these patterns collectively make the last one unreachable - --> $DIR/explain-unreachable-pats.rs:70:9 +note: multiple earlier patterns match some of the same values + --> $DIR/explain-unreachable-pats.rs:92:9 | LL | (true, _) => {} | --------- matches some of the same values @@ -83,22 +107,22 @@ LL | (_, true) => {} | ^^^^^^^^^ collectively making this unreachable error: unreachable pattern - --> $DIR/explain-unreachable-pats.rs:83:9 + --> $DIR/explain-unreachable-pats.rs:105:9 | LL | (true, _) => {} - | --------- matches all the values already + | --------- matches all the relevant values ... LL | (true, true) => {} - | ^^^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^^^ no value can reach this error: unreachable pattern - --> $DIR/explain-unreachable-pats.rs:95:9 + --> $DIR/explain-unreachable-pats.rs:117:9 | LL | (_, true, 0..10) => {} - | ---------------- matches all the values already + | ---------------- matches all the relevant values ... LL | (_, true, 3) => {} - | ^^^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^^^ no value can reach this -error: aborting due to 9 previous errors +error: aborting due to 10 previous errors diff --git a/tests/ui/pattern/usefulness/floats.stderr b/tests/ui/pattern/usefulness/floats.stderr index d0a8841d6a8..61aaa2c7626 100644 --- a/tests/ui/pattern/usefulness/floats.stderr +++ b/tests/ui/pattern/usefulness/floats.stderr @@ -15,9 +15,9 @@ error: unreachable pattern --> $DIR/floats.rs:18:9 | LL | 0.01f16..=6.5f16 => {} - | ---------------- matches all the values already + | ---------------- matches all the relevant values LL | 0.01f16 => {} - | ^^^^^^^ unreachable pattern + | ^^^^^^^ no value can reach this | note: the lint level is defined here --> $DIR/floats.rs:1:9 @@ -29,117 +29,117 @@ error: unreachable pattern --> $DIR/floats.rs:19:9 | LL | 0.01f16..=6.5f16 => {} - | ---------------- matches all the values already + | ---------------- matches all the relevant values LL | 0.01f16 => {} LL | 0.02f16 => {} - | ^^^^^^^ unreachable pattern + | ^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/floats.rs:20:9 | LL | 0.01f16..=6.5f16 => {} - | ---------------- matches all the values already + | ---------------- matches all the relevant values ... LL | 6.5f16 => {} - | ^^^^^^ unreachable pattern + | ^^^^^^ no value can reach this error: unreachable pattern --> $DIR/floats.rs:31:9 | LL | 0.01f32..=6.5f32 => {} - | ---------------- matches all the values already + | ---------------- matches all the relevant values LL | 0.01f32 => {} - | ^^^^^^^ unreachable pattern + | ^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/floats.rs:32:9 | LL | 0.01f32..=6.5f32 => {} - | ---------------- matches all the values already + | ---------------- matches all the relevant values LL | 0.01f32 => {} LL | 0.02f32 => {} - | ^^^^^^^ unreachable pattern + | ^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/floats.rs:33:9 | LL | 0.01f32..=6.5f32 => {} - | ---------------- matches all the values already + | ---------------- matches all the relevant values ... LL | 6.5f32 => {} - | ^^^^^^ unreachable pattern + | ^^^^^^ no value can reach this error: unreachable pattern --> $DIR/floats.rs:45:9 | LL | 0.01f64..=6.5f64 => {} - | ---------------- matches all the values already + | ---------------- matches all the relevant values LL | 0.005f64 => {} LL | 0.01f64 => {} - | ^^^^^^^ unreachable pattern + | ^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/floats.rs:46:9 | LL | 0.01f64..=6.5f64 => {} - | ---------------- matches all the values already + | ---------------- matches all the relevant values ... LL | 0.02f64 => {} - | ^^^^^^^ unreachable pattern + | ^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/floats.rs:47:9 | LL | 0.01f64..=6.5f64 => {} - | ---------------- matches all the values already + | ---------------- matches all the relevant values ... LL | 6.5f64 => {} - | ^^^^^^ unreachable pattern + | ^^^^^^ no value can reach this error: unreachable pattern --> $DIR/floats.rs:49:9 | LL | 0.01f64..=6.5f64 => {} - | ---------------- matches all the values already + | ---------------- matches all the relevant values ... LL | 1.0f64..=4.0f64 => {} - | ^^^^^^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/floats.rs:62:9 | LL | 0.01f128..=6.5f128 => {} - | ------------------ matches all the values already + | ------------------ matches all the relevant values LL | 0.005f128 => {} LL | 0.01f128 => {} - | ^^^^^^^^ unreachable pattern + | ^^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/floats.rs:63:9 | LL | 0.01f128..=6.5f128 => {} - | ------------------ matches all the values already + | ------------------ matches all the relevant values ... LL | 0.02f128 => {} - | ^^^^^^^^ unreachable pattern + | ^^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/floats.rs:64:9 | LL | 0.01f128..=6.5f128 => {} - | ------------------ matches all the values already + | ------------------ matches all the relevant values ... LL | 6.5f128 => {} - | ^^^^^^^ unreachable pattern + | ^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/floats.rs:66:9 | LL | 0.01f128..=6.5f128 => {} - | ------------------ matches all the values already + | ------------------ matches all the relevant values ... LL | 1.0f128..=4.0f128 => {} - | ^^^^^^^^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^^^^^^^^ no value can reach this error: aborting due to 15 previous errors diff --git a/tests/ui/pattern/usefulness/impl-trait.stderr b/tests/ui/pattern/usefulness/impl-trait.stderr index 92932e48538..34b157f0fc4 100644 --- a/tests/ui/pattern/usefulness/impl-trait.stderr +++ b/tests/ui/pattern/usefulness/impl-trait.stderr @@ -2,9 +2,9 @@ error: unreachable pattern --> $DIR/impl-trait.rs:16:13 | LL | _ => {} - | ^ + | ^ matches no values because `Void` is uninhabited | - = note: this pattern matches no values because `Void` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here --> $DIR/impl-trait.rs:4:9 | @@ -15,49 +15,49 @@ error: unreachable pattern --> $DIR/impl-trait.rs:30:13 | LL | _ => {} - | ^ + | ^ matches no values because `Void` is uninhabited | - = note: this pattern matches no values because `Void` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/impl-trait.rs:44:13 | LL | Some(_) => {} - | ^^^^^^^ + | ^^^^^^^ matches no values because `Void` is uninhabited | - = note: this pattern matches no values because `Void` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/impl-trait.rs:48:13 | LL | None => {} - | ---- matches all the values already + | ---- matches all the relevant values LL | _ => {} - | ^ unreachable pattern + | ^ no value can reach this error: unreachable pattern --> $DIR/impl-trait.rs:58:13 | LL | Some(_) => {} - | ^^^^^^^ + | ^^^^^^^ matches no values because `Void` is uninhabited | - = note: this pattern matches no values because `Void` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/impl-trait.rs:62:13 | LL | None => {} - | ---- matches all the values already + | ---- matches all the relevant values LL | _ => {} - | ^ unreachable pattern + | ^ no value can reach this error: unreachable pattern --> $DIR/impl-trait.rs:75:9 | LL | _ => {} - | ^ + | ^ matches no values because `Void` is uninhabited | - = note: this pattern matches no values because `Void` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/impl-trait.rs:85:9 @@ -65,23 +65,23 @@ error: unreachable pattern LL | _ => {} | - matches any value LL | Some((a, b)) => {} - | ^^^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/impl-trait.rs:93:13 | LL | _ => {} - | ^ + | ^ matches no values because `Void` is uninhabited | - = note: this pattern matches no values because `Void` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/impl-trait.rs:104:9 | LL | Some((a, b)) => {} - | ------------ matches all the values already + | ------------ matches all the relevant values LL | Some((mut x, mut y)) => { - | ^^^^^^^^^^^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^^^^^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/impl-trait.rs:123:13 @@ -89,23 +89,23 @@ error: unreachable pattern LL | _ => {} | - matches any value LL | Rec { n: 0, w: Some(Rec { n: 0, w: _ }) } => {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/impl-trait.rs:137:13 | LL | _ => {} - | ^ + | ^ matches no values because `SecretelyVoid` is uninhabited | - = note: this pattern matches no values because `SecretelyVoid` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/impl-trait.rs:150:13 | LL | _ => {} - | ^ + | ^ matches no values because `SecretelyDoubleVoid` is uninhabited | - = note: this pattern matches no values because `SecretelyDoubleVoid` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: type `impl Copy` is non-empty --> $DIR/impl-trait.rs:22:11 diff --git a/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr b/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr index 5d86007a853..0d495bcbec1 100644 --- a/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr +++ b/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr @@ -2,9 +2,9 @@ error: unreachable pattern --> $DIR/reachability.rs:18:17 | LL | m!(0u8, 42, 42); - | -- ^^ unreachable pattern + | -- ^^ no value can reach this | | - | matches all the values already + | matches all the relevant values | note: the lint level is defined here --> $DIR/reachability.rs:3:9 @@ -16,129 +16,129 @@ error: unreachable pattern --> $DIR/reachability.rs:22:22 | LL | m!(0u8, 20..=30, 20); - | ------- ^^ unreachable pattern + | ------- ^^ no value can reach this | | - | matches all the values already + | matches all the relevant values error: unreachable pattern --> $DIR/reachability.rs:23:22 | LL | m!(0u8, 20..=30, 21); - | ------- ^^ unreachable pattern + | ------- ^^ no value can reach this | | - | matches all the values already + | matches all the relevant values error: unreachable pattern --> $DIR/reachability.rs:24:22 | LL | m!(0u8, 20..=30, 25); - | ------- ^^ unreachable pattern + | ------- ^^ no value can reach this | | - | matches all the values already + | matches all the relevant values error: unreachable pattern --> $DIR/reachability.rs:25:22 | LL | m!(0u8, 20..=30, 29); - | ------- ^^ unreachable pattern + | ------- ^^ no value can reach this | | - | matches all the values already + | matches all the relevant values error: unreachable pattern --> $DIR/reachability.rs:26:22 | LL | m!(0u8, 20..=30, 30); - | ------- ^^ unreachable pattern + | ------- ^^ no value can reach this | | - | matches all the values already + | matches all the relevant values error: unreachable pattern --> $DIR/reachability.rs:29:21 | LL | m!(0u8, 20..30, 20); - | ------ ^^ unreachable pattern + | ------ ^^ no value can reach this | | - | matches all the values already + | matches all the relevant values error: unreachable pattern --> $DIR/reachability.rs:30:21 | LL | m!(0u8, 20..30, 21); - | ------ ^^ unreachable pattern + | ------ ^^ no value can reach this | | - | matches all the values already + | matches all the relevant values error: unreachable pattern --> $DIR/reachability.rs:31:21 | LL | m!(0u8, 20..30, 25); - | ------ ^^ unreachable pattern + | ------ ^^ no value can reach this | | - | matches all the values already + | matches all the relevant values error: unreachable pattern --> $DIR/reachability.rs:32:21 | LL | m!(0u8, 20..30, 29); - | ------ ^^ unreachable pattern + | ------ ^^ no value can reach this | | - | matches all the values already + | matches all the relevant values error: unreachable pattern --> $DIR/reachability.rs:36:22 | LL | m!(0u8, 20..=30, 20..=30); - | ------- ^^^^^^^ unreachable pattern + | ------- ^^^^^^^ no value can reach this | | - | matches all the values already + | matches all the relevant values error: unreachable pattern --> $DIR/reachability.rs:37:22 | LL | m!(0u8, 20.. 30, 20.. 30); - | ------- ^^^^^^^ unreachable pattern + | ------- ^^^^^^^ no value can reach this | | - | matches all the values already + | matches all the relevant values error: unreachable pattern --> $DIR/reachability.rs:38:22 | LL | m!(0u8, 20..=30, 20.. 30); - | ------- ^^^^^^^ unreachable pattern + | ------- ^^^^^^^ no value can reach this | | - | matches all the values already + | matches all the relevant values error: unreachable pattern --> $DIR/reachability.rs:40:22 | LL | m!(0u8, 20..=30, 21..=30); - | ------- ^^^^^^^ unreachable pattern + | ------- ^^^^^^^ no value can reach this | | - | matches all the values already + | matches all the relevant values error: unreachable pattern --> $DIR/reachability.rs:41:22 | LL | m!(0u8, 20..=30, 20..=29); - | ------- ^^^^^^^ unreachable pattern + | ------- ^^^^^^^ no value can reach this | | - | matches all the values already + | matches all the relevant values error: unreachable pattern --> $DIR/reachability.rs:43:24 | LL | m!('a', 'A'..='z', 'a'..='z'); - | --------- ^^^^^^^^^ unreachable pattern + | --------- ^^^^^^^^^ no value can reach this | | - | matches all the values already + | matches all the relevant values error: unreachable pattern --> $DIR/reachability.rs:50:9 | LL | 5..=8 => {}, - | ^^^^^ unreachable pattern + | ^^^^^ no value can reach this | -note: these patterns collectively make the last one unreachable +note: multiple earlier patterns match some of the same values --> $DIR/reachability.rs:50:9 | LL | 5 => {}, @@ -156,9 +156,9 @@ error: unreachable pattern --> $DIR/reachability.rs:56:9 | LL | 5..15 => {}, - | ^^^^^ unreachable pattern + | ^^^^^ no value can reach this | -note: these patterns collectively make the last one unreachable +note: multiple earlier patterns match some of the same values --> $DIR/reachability.rs:56:9 | LL | 0..10 => {}, @@ -172,9 +172,9 @@ error: unreachable pattern --> $DIR/reachability.rs:63:9 | LL | 5..25 => {}, - | ^^^^^ unreachable pattern + | ^^^^^ no value can reach this | -note: these patterns collectively make the last one unreachable +note: multiple earlier patterns match some of the same values --> $DIR/reachability.rs:63:9 | LL | 0..10 => {}, @@ -190,9 +190,9 @@ error: unreachable pattern --> $DIR/reachability.rs:71:9 | LL | 5..25 => {}, - | ^^^^^ unreachable pattern + | ^^^^^ no value can reach this | -note: these patterns collectively make the last one unreachable +note: multiple earlier patterns match some of the same values --> $DIR/reachability.rs:71:9 | LL | 0..10 => {}, @@ -210,9 +210,9 @@ error: unreachable pattern --> $DIR/reachability.rs:77:9 | LL | 5..15 => {}, - | ^^^^^ unreachable pattern + | ^^^^^ no value can reach this | -note: these patterns collectively make the last one unreachable +note: multiple earlier patterns match some of the same values --> $DIR/reachability.rs:77:9 | LL | 0..10 => {}, @@ -228,15 +228,15 @@ error: unreachable pattern LL | _ => {}, | - matches any value LL | '\u{D7FF}'..='\u{E000}' => {}, - | ^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^^^^^^^^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/reachability.rs:89:9 | LL | '\u{D7FF}'..='\u{E000}' => {}, - | ^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^^^^^^^^^^^^^^ no value can reach this | -note: these patterns collectively make the last one unreachable +note: multiple earlier patterns match some of the same values --> $DIR/reachability.rs:89:9 | LL | '\u{0}'..='\u{D7FF}' => {}, @@ -250,18 +250,18 @@ error: unreachable pattern --> $DIR/reachability.rs:105:9 | LL | &42 => {} - | --- matches all the values already + | --- matches all the relevant values LL | &FOO => {} - | ^^^^ unreachable pattern + | ^^^^ no value can reach this error: unreachable pattern --> $DIR/reachability.rs:106:9 | LL | &42 => {} - | --- matches all the values already + | --- matches all the relevant values LL | &FOO => {} LL | BAR => {} - | ^^^ unreachable pattern + | ^^^ no value can reach this error: aborting due to 25 previous errors diff --git a/tests/ui/pattern/usefulness/issue-12116.stderr b/tests/ui/pattern/usefulness/issue-12116.stderr index b2c2be97563..5929b81f6c2 100644 --- a/tests/ui/pattern/usefulness/issue-12116.stderr +++ b/tests/ui/pattern/usefulness/issue-12116.stderr @@ -2,9 +2,9 @@ error: unreachable pattern --> $DIR/issue-12116.rs:15:9 | LL | &IntList::Cons(val, box ref next_list) => tail(next_list), - | -------------------------------------- matches all the values already + | -------------------------------------- matches all the relevant values LL | &IntList::Cons(val, box IntList::Nil) => IntList::Cons(val, Box::new(IntList::Nil)), - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no value can reach this | note: the lint level is defined here --> $DIR/issue-12116.rs:4:9 diff --git a/tests/ui/pattern/usefulness/issue-12369.stderr b/tests/ui/pattern/usefulness/issue-12369.stderr index 7754cbc2484..fb6f89379f8 100644 --- a/tests/ui/pattern/usefulness/issue-12369.stderr +++ b/tests/ui/pattern/usefulness/issue-12369.stderr @@ -2,9 +2,9 @@ error: unreachable pattern --> $DIR/issue-12369.rs:9:9 | LL | &[10,a, ref rest @ ..] => 10 - | ^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^^^^^^^^^^^^^ no value can reach this | -note: these patterns collectively make the last one unreachable +note: multiple earlier patterns match some of the same values --> $DIR/issue-12369.rs:9:9 | LL | &[a,b,c] => 3, diff --git a/tests/ui/pattern/usefulness/issue-13727.stderr b/tests/ui/pattern/usefulness/issue-13727.stderr index ca8533b33a4..fdba8c87015 100644 --- a/tests/ui/pattern/usefulness/issue-13727.stderr +++ b/tests/ui/pattern/usefulness/issue-13727.stderr @@ -2,9 +2,9 @@ error: unreachable pattern --> $DIR/issue-13727.rs:7:5 | LL | 256 => print!("0b1110\n"), - | --- matches all the values already + | --- matches all the relevant values LL | 512 => print!("0b1111\n"), - | ^^^ unreachable pattern + | ^^^ no value can reach this | note: the lint level is defined here --> $DIR/issue-13727.rs:2:9 diff --git a/tests/ui/pattern/usefulness/issue-30240-b.stderr b/tests/ui/pattern/usefulness/issue-30240-b.stderr index 749515fc94b..4805083c129 100644 --- a/tests/ui/pattern/usefulness/issue-30240-b.stderr +++ b/tests/ui/pattern/usefulness/issue-30240-b.stderr @@ -2,9 +2,9 @@ error: unreachable pattern --> $DIR/issue-30240-b.rs:12:9 | LL | "hello" => {} - | ------- matches all the values already + | ------- matches all the relevant values LL | "hello" => {} - | ^^^^^^^ unreachable pattern + | ^^^^^^^ no value can reach this | note: the lint level is defined here --> $DIR/issue-30240-b.rs:1:9 diff --git a/tests/ui/pattern/usefulness/issue-31221.stderr b/tests/ui/pattern/usefulness/issue-31221.stderr index 596f4d8096d..e198a9397ee 100644 --- a/tests/ui/pattern/usefulness/issue-31221.stderr +++ b/tests/ui/pattern/usefulness/issue-31221.stderr @@ -4,7 +4,7 @@ error: unreachable pattern LL | Var3 => (), | ---- matches any value LL | Var2 => (), - | ^^^^ unreachable pattern + | ^^^^ no value can reach this | note: the lint level is defined here --> $DIR/issue-31221.rs:4:9 @@ -18,15 +18,15 @@ error: unreachable pattern LL | &Var3 => (), | ----- matches any value LL | &Var2 => (), - | ^^^^^ unreachable pattern + | ^^^^^ no value can reach this error: unreachable pattern --> $DIR/issue-31221.rs:31:9 | LL | anything => () - | ^^^^^^^^ unreachable pattern + | ^^^^^^^^ no value can reach this | -note: these patterns collectively make the last one unreachable +note: multiple earlier patterns match some of the same values --> $DIR/issue-31221.rs:31:9 | LL | (Var1, b) => (), diff --git a/tests/ui/pattern/usefulness/issue-57472.stderr b/tests/ui/pattern/usefulness/issue-57472.stderr index 68b5b7cb791..5a35dbd7f93 100644 --- a/tests/ui/pattern/usefulness/issue-57472.stderr +++ b/tests/ui/pattern/usefulness/issue-57472.stderr @@ -2,9 +2,9 @@ error: unreachable pattern --> $DIR/issue-57472.rs:15:13 | LL | Punned { foo: [_], .. } => println!("foo"), - | ----------------------- matches all the values already + | ----------------------- matches all the relevant values LL | Punned { bar: [_], .. } => println!("bar"), - | ^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^^^^^^^^^^^^^^ no value can reach this | note: the lint level is defined here --> $DIR/issue-57472.rs:2:9 @@ -16,9 +16,9 @@ error: unreachable pattern --> $DIR/issue-57472.rs:32:17 | LL | Punned { foo: [_] } => println!("foo"), - | ------------------- matches all the values already + | ------------------- matches all the relevant values LL | Punned { bar: [_] } => println!("bar"), - | ^^^^^^^^^^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^^^^^^^^^^ no value can reach this error: aborting due to 2 previous errors diff --git a/tests/ui/pattern/usefulness/match-arm-statics.stderr b/tests/ui/pattern/usefulness/match-arm-statics.stderr index b6f2b47047d..d5b8a4e6d79 100644 --- a/tests/ui/pattern/usefulness/match-arm-statics.stderr +++ b/tests/ui/pattern/usefulness/match-arm-statics.stderr @@ -2,10 +2,10 @@ error: unreachable pattern --> $DIR/match-arm-statics.rs:25:9 | LL | TRUE_TRUE => (), - | --------- matches all the values already + | --------- matches all the relevant values ... LL | (true, true) => () - | ^^^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^^^ no value can reach this | note: the lint level is defined here --> $DIR/match-arm-statics.rs:2:9 @@ -17,18 +17,18 @@ error: unreachable pattern --> $DIR/match-arm-statics.rs:40:9 | LL | Some(Some(EAST)) => (), - | ---------------- matches all the values already + | ---------------- matches all the relevant values ... LL | Some(Some(East)) => (), - | ^^^^^^^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/match-arm-statics.rs:60:9 | LL | Foo { bar: Some(EAST), baz: NewBool(false) } => () - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no value can reach this | -note: these patterns collectively make the last one unreachable +note: multiple earlier patterns match some of the same values --> $DIR/match-arm-statics.rs:60:9 | LL | Foo { bar: _, baz: NEW_FALSE } => (), diff --git a/tests/ui/pattern/usefulness/match-byte-array-patterns.stderr b/tests/ui/pattern/usefulness/match-byte-array-patterns.stderr index 39675e2bdd4..79a0fb9a8dd 100644 --- a/tests/ui/pattern/usefulness/match-byte-array-patterns.stderr +++ b/tests/ui/pattern/usefulness/match-byte-array-patterns.stderr @@ -2,9 +2,9 @@ error: unreachable pattern --> $DIR/match-byte-array-patterns.rs:8:9 | LL | b"AAAA" => {}, - | ------- matches all the values already + | ------- matches all the relevant values LL | &[0x41, 0x41, 0x41, 0x41] => {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^^^^^^^^^^^^^^^^ no value can reach this | note: the lint level is defined here --> $DIR/match-byte-array-patterns.rs:1:9 @@ -16,57 +16,57 @@ error: unreachable pattern --> $DIR/match-byte-array-patterns.rs:14:9 | LL | &[0x41, 0x41, 0x41, 0x41] => {} - | ------------------------- matches all the values already + | ------------------------- matches all the relevant values LL | b"AAAA" => {}, - | ^^^^^^^ unreachable pattern + | ^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/match-byte-array-patterns.rs:20:9 | LL | &[_, 0x41, 0x41, 0x41] => {}, - | ---------------------- matches all the values already + | ---------------------- matches all the relevant values LL | b"AAAA" => {}, - | ^^^^^^^ unreachable pattern + | ^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/match-byte-array-patterns.rs:26:9 | LL | &[0x41, .., 0x41] => {} - | ----------------- matches all the values already + | ----------------- matches all the relevant values LL | b"AAAA" => {}, - | ^^^^^^^ unreachable pattern + | ^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/match-byte-array-patterns.rs:34:9 | LL | b"AAAA" => {}, - | ------- matches all the values already + | ------- matches all the relevant values LL | &[0x41, 0x41, 0x41, 0x41] => {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^^^^^^^^^^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/match-byte-array-patterns.rs:40:9 | LL | &[0x41, 0x41, 0x41, 0x41] => {} - | ------------------------- matches all the values already + | ------------------------- matches all the relevant values LL | b"AAAA" => {}, - | ^^^^^^^ unreachable pattern + | ^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/match-byte-array-patterns.rs:46:9 | LL | &[_, 0x41, 0x41, 0x41] => {}, - | ---------------------- matches all the values already + | ---------------------- matches all the relevant values LL | b"AAAA" => {}, - | ^^^^^^^ unreachable pattern + | ^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/match-byte-array-patterns.rs:52:9 | LL | &[0x41, .., 0x41] => {} - | ----------------- matches all the values already + | ----------------- matches all the relevant values LL | b"AAAA" => {}, - | ^^^^^^^ unreachable pattern + | ^^^^^^^ no value can reach this error: aborting due to 8 previous errors diff --git a/tests/ui/pattern/usefulness/match-ref-ice.stderr b/tests/ui/pattern/usefulness/match-ref-ice.stderr index 9c5af47cc1e..c5f8a95b16b 100644 --- a/tests/ui/pattern/usefulness/match-ref-ice.stderr +++ b/tests/ui/pattern/usefulness/match-ref-ice.stderr @@ -2,9 +2,9 @@ error: unreachable pattern --> $DIR/match-ref-ice.rs:13:9 | LL | [1, ref _madoka, 3] => (), - | ------------------- matches all the values already + | ------------------- matches all the relevant values LL | [1, 2, 3] => (), - | ^^^^^^^^^ unreachable pattern + | ^^^^^^^^^ no value can reach this | note: the lint level is defined here --> $DIR/match-ref-ice.rs:1:9 diff --git a/tests/ui/pattern/usefulness/match-vec-fixed.stderr b/tests/ui/pattern/usefulness/match-vec-fixed.stderr index 04507a22856..b0b8cdf887a 100644 --- a/tests/ui/pattern/usefulness/match-vec-fixed.stderr +++ b/tests/ui/pattern/usefulness/match-vec-fixed.stderr @@ -2,9 +2,9 @@ error: unreachable pattern --> $DIR/match-vec-fixed.rs:7:9 | LL | [_, _, _] => {} - | --------- matches all the values already + | --------- matches all the relevant values LL | [_, _, _] => {} - | ^^^^^^^^^ unreachable pattern + | ^^^^^^^^^ no value can reach this | note: the lint level is defined here --> $DIR/match-vec-fixed.rs:1:9 @@ -16,9 +16,9 @@ error: unreachable pattern --> $DIR/match-vec-fixed.rs:11:9 | LL | [_, 1, _] => {} - | --------- matches all the values already + | --------- matches all the relevant values LL | [_, 1, _] => {} - | ^^^^^^^^^ unreachable pattern + | ^^^^^^^^^ no value can reach this error: aborting due to 2 previous errors diff --git a/tests/ui/pattern/usefulness/match-vec-unreachable.stderr b/tests/ui/pattern/usefulness/match-vec-unreachable.stderr index 865f5b319a7..6ed8f0019fe 100644 --- a/tests/ui/pattern/usefulness/match-vec-unreachable.stderr +++ b/tests/ui/pattern/usefulness/match-vec-unreachable.stderr @@ -2,9 +2,9 @@ error: unreachable pattern --> $DIR/match-vec-unreachable.rs:8:9 | LL | [a, (2, 3), _] => (), - | -------------- matches all the values already + | -------------- matches all the relevant values LL | [(1, 2), (2, 3), b] => (), - | ^^^^^^^^^^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^^^^^^^^^^ no value can reach this | note: the lint level is defined here --> $DIR/match-vec-unreachable.rs:1:9 @@ -16,17 +16,17 @@ error: unreachable pattern --> $DIR/match-vec-unreachable.rs:18:9 | LL | [ref a, _, _, ..] => { println!("{}", a); } - | ----------------- matches all the values already + | ----------------- matches all the relevant values LL | [_, _, _, _, _] => { } - | ^^^^^^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/match-vec-unreachable.rs:26:9 | LL | ['a', 'b', 'c', ref _tail @ ..] => {} - | ------------------------------- matches all the values already + | ------------------------------- matches all the relevant values LL | ['a', 'b', 'c'] => {} - | ^^^^^^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^^^^^^ no value can reach this error: aborting due to 3 previous errors diff --git a/tests/ui/pattern/usefulness/slice-pattern-const-2.stderr b/tests/ui/pattern/usefulness/slice-pattern-const-2.stderr index 12db48590a4..a6031eaa730 100644 --- a/tests/ui/pattern/usefulness/slice-pattern-const-2.stderr +++ b/tests/ui/pattern/usefulness/slice-pattern-const-2.stderr @@ -2,10 +2,10 @@ error: unreachable pattern --> $DIR/slice-pattern-const-2.rs:9:9 | LL | MAGIC_TEST => (), - | ---------- matches all the values already + | ---------- matches all the relevant values LL | [0x00, 0x00, 0x00, 0x00] => (), LL | [4, 5, 6, 7] => (), - | ^^^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^^^ no value can reach this | note: the lint level is defined here --> $DIR/slice-pattern-const-2.rs:1:9 @@ -17,25 +17,25 @@ error: unreachable pattern --> $DIR/slice-pattern-const-2.rs:15:9 | LL | MAGIC_TEST => (), - | ---------- matches all the values already + | ---------- matches all the relevant values LL | [4, 5, 6, 7] => (), - | ^^^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/slice-pattern-const-2.rs:21:9 | LL | [4, 5, 6, 7] => (), - | ------------ matches all the values already + | ------------ matches all the relevant values LL | MAGIC_TEST => (), - | ^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/slice-pattern-const-2.rs:28:9 | LL | [4] => (), - | --- matches all the values already + | --- matches all the relevant values LL | FOO => (), - | ^^^ unreachable pattern + | ^^^ no value can reach this error: aborting due to 4 previous errors diff --git a/tests/ui/pattern/usefulness/slice-pattern-const-3.stderr b/tests/ui/pattern/usefulness/slice-pattern-const-3.stderr index 5a66799d9c9..bbec9f23602 100644 --- a/tests/ui/pattern/usefulness/slice-pattern-const-3.stderr +++ b/tests/ui/pattern/usefulness/slice-pattern-const-3.stderr @@ -2,10 +2,10 @@ error: unreachable pattern --> $DIR/slice-pattern-const-3.rs:9:9 | LL | MAGIC_TEST => (), - | ---------- matches all the values already + | ---------- matches all the relevant values LL | ["0x00", "0x00", "0x00", "0x00"] => (), LL | ["4", "5", "6", "7"] => (), - | ^^^^^^^^^^^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^^^^^^^^^^^ no value can reach this | note: the lint level is defined here --> $DIR/slice-pattern-const-3.rs:1:9 @@ -17,25 +17,25 @@ error: unreachable pattern --> $DIR/slice-pattern-const-3.rs:15:9 | LL | MAGIC_TEST => (), - | ---------- matches all the values already + | ---------- matches all the relevant values LL | ["4", "5", "6", "7"] => (), - | ^^^^^^^^^^^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^^^^^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/slice-pattern-const-3.rs:21:9 | LL | ["4", "5", "6", "7"] => (), - | -------------------- matches all the values already + | -------------------- matches all the relevant values LL | MAGIC_TEST => (), - | ^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/slice-pattern-const-3.rs:28:9 | LL | ["boo"] => (), - | ------- matches all the values already + | ------- matches all the relevant values LL | FOO => (), - | ^^^ unreachable pattern + | ^^^ no value can reach this error: aborting due to 4 previous errors diff --git a/tests/ui/pattern/usefulness/slice-pattern-const.stderr b/tests/ui/pattern/usefulness/slice-pattern-const.stderr index 87a85acc4c5..09bbee73577 100644 --- a/tests/ui/pattern/usefulness/slice-pattern-const.stderr +++ b/tests/ui/pattern/usefulness/slice-pattern-const.stderr @@ -2,10 +2,10 @@ error: unreachable pattern --> $DIR/slice-pattern-const.rs:9:9 | LL | MAGIC_TEST => (), - | ---------- matches all the values already + | ---------- matches all the relevant values LL | [0x00, 0x00, 0x00, 0x00] => (), LL | [84, 69, 83, 84] => (), - | ^^^^^^^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^^^^^^^ no value can reach this | note: the lint level is defined here --> $DIR/slice-pattern-const.rs:1:9 @@ -17,67 +17,67 @@ error: unreachable pattern --> $DIR/slice-pattern-const.rs:15:9 | LL | MAGIC_TEST => (), - | ---------- matches all the values already + | ---------- matches all the relevant values LL | [84, 69, 83, 84] => (), - | ^^^^^^^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/slice-pattern-const.rs:21:9 | LL | [84, 69, 83, 84] => (), - | ---------------- matches all the values already + | ---------------- matches all the relevant values LL | MAGIC_TEST => (), - | ^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/slice-pattern-const.rs:28:9 | LL | [4] => (), - | --- matches all the values already + | --- matches all the relevant values LL | FOO => (), - | ^^^ unreachable pattern + | ^^^ no value can reach this error: unreachable pattern --> $DIR/slice-pattern-const.rs:35:9 | LL | [4] => (), - | --- matches all the values already + | --- matches all the relevant values LL | BAR => (), - | ^^^ unreachable pattern + | ^^^ no value can reach this error: unreachable pattern --> $DIR/slice-pattern-const.rs:43:9 | LL | [] => (), - | -- matches all the values already + | -- matches all the relevant values LL | BOO => (), - | ^^^ unreachable pattern + | ^^^ no value can reach this error: unreachable pattern --> $DIR/slice-pattern-const.rs:44:9 | LL | [] => (), - | -- matches all the values already + | -- matches all the relevant values LL | BOO => (), LL | b"" => (), - | ^^^ unreachable pattern + | ^^^ no value can reach this error: unreachable pattern --> $DIR/slice-pattern-const.rs:45:9 | LL | [] => (), - | -- matches all the values already + | -- matches all the relevant values ... LL | _ => (), - | ^ unreachable pattern + | ^ no value can reach this error: unreachable pattern --> $DIR/slice-pattern-const.rs:51:9 | LL | CONST1 => {} - | ------ matches all the values already + | ------ matches all the relevant values LL | [true] => {} - | ^^^^^^ unreachable pattern + | ^^^^^^ no value can reach this error: aborting due to 9 previous errors diff --git a/tests/ui/pattern/usefulness/slice-patterns-reachability.stderr b/tests/ui/pattern/usefulness/slice-patterns-reachability.stderr index 40fbb00de1f..d45779f09a5 100644 --- a/tests/ui/pattern/usefulness/slice-patterns-reachability.stderr +++ b/tests/ui/pattern/usefulness/slice-patterns-reachability.stderr @@ -2,9 +2,9 @@ error: unreachable pattern --> $DIR/slice-patterns-reachability.rs:8:9 | LL | [true, ..] => {} - | ---------- matches all the values already + | ---------- matches all the relevant values LL | [true, ..] => {} - | ^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^ no value can reach this | note: the lint level is defined here --> $DIR/slice-patterns-reachability.rs:1:9 @@ -16,44 +16,44 @@ error: unreachable pattern --> $DIR/slice-patterns-reachability.rs:9:9 | LL | [true, ..] => {} - | ---------- matches all the values already + | ---------- matches all the relevant values LL | [true, ..] => {} LL | [true] => {} - | ^^^^^^ unreachable pattern + | ^^^^^^ no value can reach this error: unreachable pattern --> $DIR/slice-patterns-reachability.rs:14:9 | LL | [.., true] => {} - | ---------- matches all the values already + | ---------- matches all the relevant values LL | [.., true] => {} - | ^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/slice-patterns-reachability.rs:15:9 | LL | [.., true] => {} - | ---------- matches all the values already + | ---------- matches all the relevant values LL | [.., true] => {} LL | [true] => {} - | ^^^^^^ unreachable pattern + | ^^^^^^ no value can reach this error: unreachable pattern --> $DIR/slice-patterns-reachability.rs:20:9 | LL | [false, .., true] => {} - | ----------------- matches all the values already + | ----------------- matches all the relevant values LL | [false, .., true] => {} - | ^^^^^^^^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/slice-patterns-reachability.rs:21:9 | LL | [false, .., true] => {} - | ----------------- matches all the values already + | ----------------- matches all the relevant values LL | [false, .., true] => {} LL | [false, true] => {} - | ^^^^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^^^^ no value can reach this error: aborting due to 6 previous errors diff --git a/tests/ui/pattern/usefulness/struct-pattern-match-useless.stderr b/tests/ui/pattern/usefulness/struct-pattern-match-useless.stderr index cc29c42e4d6..502fa2deda9 100644 --- a/tests/ui/pattern/usefulness/struct-pattern-match-useless.stderr +++ b/tests/ui/pattern/usefulness/struct-pattern-match-useless.stderr @@ -4,7 +4,7 @@ error: unreachable pattern LL | Foo { x: _x, y: _y } => (), | -------------------- matches any value LL | Foo { .. } => () - | ^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^ no value can reach this | note: the lint level is defined here --> $DIR/struct-pattern-match-useless.rs:1:9 diff --git a/tests/ui/pattern/usefulness/top-level-alternation.stderr b/tests/ui/pattern/usefulness/top-level-alternation.stderr index ad846f23155..7fc03143bc3 100644 --- a/tests/ui/pattern/usefulness/top-level-alternation.stderr +++ b/tests/ui/pattern/usefulness/top-level-alternation.stderr @@ -2,9 +2,9 @@ error: unreachable pattern --> $DIR/top-level-alternation.rs:4:23 | LL | while let 0..=2 | 1 = 0 {} - | ----- ^ unreachable pattern + | ----- ^ no value can reach this | | - | matches all the values already + | matches all the relevant values | note: the lint level is defined here --> $DIR/top-level-alternation.rs:1:9 @@ -16,66 +16,66 @@ error: unreachable pattern --> $DIR/top-level-alternation.rs:5:20 | LL | if let 0..=2 | 1 = 0 {} - | ----- ^ unreachable pattern + | ----- ^ no value can reach this | | - | matches all the values already + | matches all the relevant values error: unreachable pattern --> $DIR/top-level-alternation.rs:9:15 | LL | 0 - | - matches all the values already + | - matches all the relevant values LL | | 0 => {} - | ^ unreachable pattern + | ^ no value can reach this error: unreachable pattern --> $DIR/top-level-alternation.rs:14:15 | LL | Some(0) - | ------- matches all the values already + | ------- matches all the relevant values LL | | Some(0) => {} - | ^^^^^^^ unreachable pattern + | ^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/top-level-alternation.rs:19:9 | LL | (0, _) | (_, 0) => {} - | --------------- matches all the values already + | --------------- matches all the relevant values LL | (0, 0) => {} - | ^^^^^^ unreachable pattern + | ^^^^^^ no value can reach this error: unreachable pattern --> $DIR/top-level-alternation.rs:39:9 | LL | None | Some(_) => {} - | -------------- matches all the values already + | -------------- matches all the relevant values LL | _ => {} - | ^ unreachable pattern + | ^ no value can reach this error: unreachable pattern --> $DIR/top-level-alternation.rs:43:9 | LL | None | Some(_) => {} - | -------------- matches all the values already + | -------------- matches all the relevant values LL | Some(_) => {} - | ^^^^^^^ unreachable pattern + | ^^^^^^^ no value can reach this error: unreachable pattern --> $DIR/top-level-alternation.rs:44:9 | LL | None | Some(_) => {} - | -------------- matches all the values already + | -------------- matches all the relevant values LL | Some(_) => {} LL | None => {} - | ^^^^ unreachable pattern + | ^^^^ no value can reach this error: unreachable pattern --> $DIR/top-level-alternation.rs:49:9 | LL | None | Some(_) => {} - | ^^^^^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^^^^^ no value can reach this | -note: these patterns collectively make the last one unreachable +note: multiple earlier patterns match some of the same values --> $DIR/top-level-alternation.rs:49:9 | LL | Some(_) => {} @@ -89,17 +89,17 @@ error: unreachable pattern --> $DIR/top-level-alternation.rs:53:9 | LL | 1 | 2 => {}, - | ----- matches all the values already + | ----- matches all the relevant values LL | 1..=2 => {}, - | ^^^^^ unreachable pattern + | ^^^^^ no value can reach this error: unreachable pattern --> $DIR/top-level-alternation.rs:56:14 | LL | let (0 | 0) = 0 else { return }; - | - ^ unreachable pattern + | - ^ no value can reach this | | - | matches all the values already + | matches all the relevant values error: aborting due to 11 previous errors diff --git a/tests/ui/privacy/private-in-public-warn.stderr b/tests/ui/privacy/private-in-public-warn.stderr index 3f7b8c281e7..3743879ffa6 100644 --- a/tests/ui/privacy/private-in-public-warn.stderr +++ b/tests/ui/privacy/private-in-public-warn.stderr @@ -100,7 +100,7 @@ error: type `types::Priv` is more private than the item `types::ef1` --> $DIR/private-in-public-warn.rs:28:9 | LL | pub fn ef1(arg: Priv); - | ^^^^^^^^^^^^^^^^^^^^^ function `types::ef1` is reachable at visibility `pub(crate)` + | ^^^^^^^^^^^^^^^^^^^^^^ function `types::ef1` is reachable at visibility `pub(crate)` | note: but type `types::Priv` is only usable at visibility `pub(self)` --> $DIR/private-in-public-warn.rs:9:5 @@ -112,7 +112,7 @@ error: type `types::Priv` is more private than the item `types::ef2` --> $DIR/private-in-public-warn.rs:29:9 | LL | pub fn ef2() -> Priv; - | ^^^^^^^^^^^^^^^^^^^^ function `types::ef2` is reachable at visibility `pub(crate)` + | ^^^^^^^^^^^^^^^^^^^^^ function `types::ef2` is reachable at visibility `pub(crate)` | note: but type `types::Priv` is only usable at visibility `pub(self)` --> $DIR/private-in-public-warn.rs:9:5 diff --git a/tests/ui/raw-ref-op/feature-raw-ref-op.rs b/tests/ui/raw-ref-op/feature-raw-ref-op.rs deleted file mode 100644 index 0a44b1cde40..00000000000 --- a/tests/ui/raw-ref-op/feature-raw-ref-op.rs +++ /dev/null @@ -1,21 +0,0 @@ -// gate-test-raw_ref_op - -macro_rules! is_expr { - ($e:expr) => {} -} - -is_expr!(&raw const a); //~ ERROR raw address of syntax is experimental -is_expr!(&raw mut a); //~ ERROR raw address of syntax is experimental - -#[cfg(FALSE)] -fn cfgd_out() { - let mut a = 0; - &raw const a; //~ ERROR raw address of syntax is experimental - &raw mut a; //~ ERROR raw address of syntax is experimental -} - -fn main() { - let mut y = 123; - let x = &raw const y; //~ ERROR raw address of syntax is experimental - let x = &raw mut y; //~ ERROR raw address of syntax is experimental -} diff --git a/tests/ui/raw-ref-op/feature-raw-ref-op.stderr b/tests/ui/raw-ref-op/feature-raw-ref-op.stderr deleted file mode 100644 index 4ffd0c90e48..00000000000 --- a/tests/ui/raw-ref-op/feature-raw-ref-op.stderr +++ /dev/null @@ -1,63 +0,0 @@ -error[E0658]: raw address of syntax is experimental - --> $DIR/feature-raw-ref-op.rs:13:5 - | -LL | &raw const a; - | ^^^^^^^^^^ - | - = note: see issue #64490 for more information - = help: add `#![feature(raw_ref_op)]` 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]: raw address of syntax is experimental - --> $DIR/feature-raw-ref-op.rs:14:5 - | -LL | &raw mut a; - | ^^^^^^^^ - | - = note: see issue #64490 for more information - = help: add `#![feature(raw_ref_op)]` 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]: raw address of syntax is experimental - --> $DIR/feature-raw-ref-op.rs:19:13 - | -LL | let x = &raw const y; - | ^^^^^^^^^^ - | - = note: see issue #64490 for more information - = help: add `#![feature(raw_ref_op)]` 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]: raw address of syntax is experimental - --> $DIR/feature-raw-ref-op.rs:20:13 - | -LL | let x = &raw mut y; - | ^^^^^^^^ - | - = note: see issue #64490 for more information - = help: add `#![feature(raw_ref_op)]` 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]: raw address of syntax is experimental - --> $DIR/feature-raw-ref-op.rs:7:10 - | -LL | is_expr!(&raw const a); - | ^^^^^^^^^^ - | - = note: see issue #64490 for more information - = help: add `#![feature(raw_ref_op)]` 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]: raw address of syntax is experimental - --> $DIR/feature-raw-ref-op.rs:8:10 - | -LL | is_expr!(&raw mut a); - | ^^^^^^^^ - | - = note: see issue #64490 for more information - = help: add `#![feature(raw_ref_op)]` 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 6 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/raw-ref-op/raw-ref-op.rs b/tests/ui/raw-ref-op/raw-ref-op.rs index 70b7a5a4806..0989a6005dc 100644 --- a/tests/ui/raw-ref-op/raw-ref-op.rs +++ b/tests/ui/raw-ref-op/raw-ref-op.rs @@ -1,7 +1,5 @@ //@ run-pass -#![feature(raw_ref_op)] - fn main() { let mut x = 123; let c_p = &raw const x; diff --git a/tests/ui/raw-ref-op/raw-ref-temp-deref.rs b/tests/ui/raw-ref-op/raw-ref-temp-deref.rs index 5270bdb7a2b..a0078bbc1cd 100644 --- a/tests/ui/raw-ref-op/raw-ref-temp-deref.rs +++ b/tests/ui/raw-ref-op/raw-ref-temp-deref.rs @@ -1,7 +1,7 @@ //@ check-pass // Check that taking the address of a place that contains a dereference is // allowed. -#![feature(raw_ref_op, type_ascription)] +#![feature(type_ascription)] const PAIR_REF: &(i32, i64) = &(1, 2); diff --git a/tests/ui/raw-ref-op/raw-ref-temp.rs b/tests/ui/raw-ref-op/raw-ref-temp.rs index 10e47cb34c5..70f67602af2 100644 --- a/tests/ui/raw-ref-op/raw-ref-temp.rs +++ b/tests/ui/raw-ref-op/raw-ref-temp.rs @@ -1,5 +1,5 @@ // Ensure that we don't allow taking the address of temporary values -#![feature(raw_ref_op, type_ascription)] +#![feature(type_ascription)] const FOUR: u64 = 4; diff --git a/tests/ui/raw-ref-op/unusual_locations.rs b/tests/ui/raw-ref-op/unusual_locations.rs index badf529cb45..eb40fa8a7ee 100644 --- a/tests/ui/raw-ref-op/unusual_locations.rs +++ b/tests/ui/raw-ref-op/unusual_locations.rs @@ -1,7 +1,5 @@ //@ check-pass -#![feature(raw_ref_op)] - const USES_PTR: () = { let u = (); &raw const u; }; static ALSO_USES_PTR: () = { let u = (); &raw const u; }; diff --git a/tests/ui/reachable/unreachable-arm.stderr b/tests/ui/reachable/unreachable-arm.stderr index 79627404030..50c29b30c69 100644 --- a/tests/ui/reachable/unreachable-arm.stderr +++ b/tests/ui/reachable/unreachable-arm.stderr @@ -2,9 +2,9 @@ error: unreachable pattern --> $DIR/unreachable-arm.rs:11:9 | LL | Foo::B(_) | Foo::A(box _, 1) => { } - | ---------------------------- matches all the values already + | ---------------------------- matches all the relevant values LL | Foo::A(_, 1) => { } - | ^^^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^^^ no value can reach this | note: the lint level is defined here --> $DIR/unreachable-arm.rs:4:9 diff --git a/tests/ui/reachable/unreachable-loop-patterns.stderr b/tests/ui/reachable/unreachable-loop-patterns.stderr index 9b7c2ba4acd..03959ac1606 100644 --- a/tests/ui/reachable/unreachable-loop-patterns.stderr +++ b/tests/ui/reachable/unreachable-loop-patterns.stderr @@ -2,9 +2,9 @@ error: unreachable pattern --> $DIR/unreachable-loop-patterns.rs:16:9 | LL | for _ in unimplemented!() as Void {} - | ^ + | ^ matches no values because `Void` is uninhabited | - = note: this pattern matches no values because `Void` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here --> $DIR/unreachable-loop-patterns.rs:3:9 | diff --git a/tests/ui/reachable/unreachable-try-pattern.stderr b/tests/ui/reachable/unreachable-try-pattern.stderr index bc1a6fffda6..b082bc11603 100644 --- a/tests/ui/reachable/unreachable-try-pattern.stderr +++ b/tests/ui/reachable/unreachable-try-pattern.stderr @@ -17,9 +17,9 @@ warning: unreachable pattern --> $DIR/unreachable-try-pattern.rs:19:24 | LL | let y = (match x { Ok(n) => Ok(n as u32), Err(e) => Err(e) })?; - | ^^^^^ + | ^^^^^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here --> $DIR/unreachable-try-pattern.rs:4:9 | @@ -30,9 +30,9 @@ warning: unreachable pattern --> $DIR/unreachable-try-pattern.rs:30:40 | LL | let y = (match x { Ok(n) => Ok(n), Err(e) => Err(e) })?; - | ^^^^^^ + | ^^^^^^ matches no values because `Void` is uninhabited | - = note: this pattern matches no values because `Void` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types warning: 3 warnings emitted diff --git a/tests/ui/regions/explicit-static-bound-on-trait.rs b/tests/ui/regions/explicit-static-bound-on-trait.rs new file mode 100644 index 00000000000..835da34d1bb --- /dev/null +++ b/tests/ui/regions/explicit-static-bound-on-trait.rs @@ -0,0 +1,13 @@ +struct Hello<'a> { + value: Box, + //~^ ERROR lifetime bound not satisfied +} + +impl<'a> Hello<'a> { + fn new(value: T) -> Self { + Self { value: Box::new(value) } + //~^ ERROR the parameter type `T` may not live long enough + } +} + +fn main() {} diff --git a/tests/ui/regions/explicit-static-bound-on-trait.stderr b/tests/ui/regions/explicit-static-bound-on-trait.stderr new file mode 100644 index 00000000000..30d39c6e86e --- /dev/null +++ b/tests/ui/regions/explicit-static-bound-on-trait.stderr @@ -0,0 +1,32 @@ +error[E0478]: lifetime bound not satisfied + --> $DIR/explicit-static-bound-on-trait.rs:2:12 + | +LL | value: Box, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: lifetime parameter instantiated with the lifetime `'a` as defined here + --> $DIR/explicit-static-bound-on-trait.rs:1:14 + | +LL | struct Hello<'a> { + | ^^ +note: but lifetime parameter must outlive the static lifetime + --> $SRC_DIR/core/src/any.rs:LL:COL + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/explicit-static-bound-on-trait.rs:8:23 + | +LL | Self { value: Box::new(value) } + | ^^^^^^^^^^^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound + | +LL | fn new(value: T) -> Self { + | +++++++++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0310, E0478. +For more information about an error, try `rustc --explain E0310`. diff --git a/tests/ui/repr/conflicting-repr-hints.stderr b/tests/ui/repr/conflicting-repr-hints.stderr index 4dcd8f4fc28..fbfa69e7fb1 100644 --- a/tests/ui/repr/conflicting-repr-hints.stderr +++ b/tests/ui/repr/conflicting-repr-hints.stderr @@ -81,3 +81,25 @@ error: aborting due to 12 previous errors Some errors have detailed explanations: E0566, E0587, E0634. For more information about an error, try `rustc --explain E0566`. +Future incompatibility report: Future breakage diagnostic: +error[E0566]: conflicting representation hints + --> $DIR/conflicting-repr-hints.rs:13:8 + | +LL | #[repr(C, u64)] + | ^ ^^^ + | + = 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 #68585 + = note: `#[deny(conflicting_repr_hints)]` on by default + +Future breakage diagnostic: +error[E0566]: conflicting representation hints + --> $DIR/conflicting-repr-hints.rs:19:8 + | +LL | #[repr(u32, u64)] + | ^^^ ^^^ + | + = 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 #68585 + = note: `#[deny(conflicting_repr_hints)]` on by default + diff --git a/tests/ui/repr/repr-transparent-non-exhaustive-transparent-in-prose.rs b/tests/ui/repr/repr-transparent-non-exhaustive-transparent-in-prose.rs new file mode 100644 index 00000000000..6ab34719f06 --- /dev/null +++ b/tests/ui/repr/repr-transparent-non-exhaustive-transparent-in-prose.rs @@ -0,0 +1,25 @@ +//@ check-pass + +#![feature(sync_unsafe_cell)] +#![allow(unused)] +#![deny(repr_transparent_external_private_fields)] + +// https://github.com/rust-lang/rust/issues/129470 + +struct ZST; + +#[repr(transparent)] +struct TransparentWithManuallyDropZST { + value: i32, + md: std::mem::ManuallyDrop, + mu: std::mem::MaybeUninit, + p: std::pin::Pin, + pd: std::marker::PhantomData, + pp: std::marker::PhantomPinned, + c: std::cell::Cell, + uc: std::cell::UnsafeCell, + suc: std::cell::SyncUnsafeCell, + zst: ZST, +} + +fn main() {} diff --git a/tests/ui/resolve/local-shadows-inner-generic.rs b/tests/ui/resolve/local-shadows-inner-generic.rs new file mode 100644 index 00000000000..d9145b9fe2c --- /dev/null +++ b/tests/ui/resolve/local-shadows-inner-generic.rs @@ -0,0 +1,8 @@ +//@ check-pass + +#![allow(non_camel_case_types)] + +pub fn main() { + let a = 1; + struct Foo { field: a, }; +} diff --git a/tests/ui/return/return-from-residual-sugg-issue-125997.fixed b/tests/ui/return/return-from-residual-sugg-issue-125997.fixed index b2eca69aeb9..43a9907a9b4 100644 --- a/tests/ui/return/return-from-residual-sugg-issue-125997.fixed +++ b/tests/ui/return/return-from-residual-sugg-issue-125997.fixed @@ -9,7 +9,6 @@ use std::io::prelude::*; fn test1() -> Result<(), Box> { let mut _file = File::create("foo.txt")?; //~^ ERROR the `?` operator can only be used in a function - Ok(()) } @@ -17,7 +16,6 @@ fn test2() -> Result<(), Box> { let mut _file = File::create("foo.txt")?; //~^ ERROR the `?` operator can only be used in a function println!(); - Ok(()) } @@ -27,16 +25,31 @@ macro_rules! mac { let mut _file = File::create("foo.txt")?; //~^ ERROR the `?` operator can only be used in a function println!(); - - Ok(()) -} + Ok(()) + } }; } +struct A; + +impl A { + fn test4(&self) -> Result<(), Box> { + let mut _file = File::create("foo.txt")?; + //~^ ERROR the `?` operator can only be used in a method + Ok(()) + } + + fn test5(&self) -> Result<(), Box> { + let mut _file = File::create("foo.txt")?; + //~^ ERROR the `?` operator can only be used in a method + println!(); + Ok(()) + } +} + fn main() -> Result<(), Box> { let mut _file = File::create("foo.txt")?; //~^ ERROR the `?` operator can only be used in a function mac!(); - Ok(()) } diff --git a/tests/ui/return/return-from-residual-sugg-issue-125997.rs b/tests/ui/return/return-from-residual-sugg-issue-125997.rs index dd8550a388b..30ca27eae45 100644 --- a/tests/ui/return/return-from-residual-sugg-issue-125997.rs +++ b/tests/ui/return/return-from-residual-sugg-issue-125997.rs @@ -27,6 +27,21 @@ macro_rules! mac { }; } +struct A; + +impl A { + fn test4(&self) { + let mut _file = File::create("foo.txt")?; + //~^ ERROR the `?` operator can only be used in a method + } + + fn test5(&self) { + let mut _file = File::create("foo.txt")?; + //~^ ERROR the `?` operator can only be used in a method + println!(); + } +} + fn main() { let mut _file = File::create("foo.txt")?; //~^ ERROR the `?` operator can only be used in a function diff --git a/tests/ui/return/return-from-residual-sugg-issue-125997.stderr b/tests/ui/return/return-from-residual-sugg-issue-125997.stderr index ef938f0213d..e22f33fd242 100644 --- a/tests/ui/return/return-from-residual-sugg-issue-125997.stderr +++ b/tests/ui/return/return-from-residual-sugg-issue-125997.stderr @@ -12,9 +12,7 @@ help: consider adding return type LL ~ fn test1() -> Result<(), Box> { LL | let mut _file = File::create("foo.txt")?; LL | -LL + LL + Ok(()) -LL + } | error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) @@ -32,13 +30,48 @@ LL ~ fn test2() -> Result<(), Box> { LL | let mut _file = File::create("foo.txt")?; LL | LL | println!(); -LL + LL + Ok(()) -LL + } + | + +error[E0277]: the `?` operator can only be used in a method that returns `Result` or `Option` (or another type that implements `FromResidual`) + --> $DIR/return-from-residual-sugg-issue-125997.rs:34:48 + | +LL | fn test4(&self) { + | --------------- this function should return `Result` or `Option` to accept `?` +LL | let mut _file = File::create("foo.txt")?; + | ^ cannot use the `?` operator in a method that returns `()` + | + = help: the trait `FromResidual>` is not implemented for `()` +help: consider adding return type + | +LL ~ fn test4(&self) -> Result<(), Box> { +LL | let mut _file = File::create("foo.txt")?; +LL | +LL ~ Ok(()) +LL ~ } + | + +error[E0277]: the `?` operator can only be used in a method that returns `Result` or `Option` (or another type that implements `FromResidual`) + --> $DIR/return-from-residual-sugg-issue-125997.rs:39:48 + | +LL | fn test5(&self) { + | --------------- this function should return `Result` or `Option` to accept `?` +LL | let mut _file = File::create("foo.txt")?; + | ^ cannot use the `?` operator in a method that returns `()` + | + = help: the trait `FromResidual>` is not implemented for `()` +help: consider adding return type + | +LL ~ fn test5(&self) -> Result<(), Box> { +LL | let mut _file = File::create("foo.txt")?; +LL | +LL | println!(); +LL ~ Ok(()) +LL ~ } | error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) - --> $DIR/return-from-residual-sugg-issue-125997.rs:31:44 + --> $DIR/return-from-residual-sugg-issue-125997.rs:46:44 | LL | fn main() { | --------- this function should return `Result` or `Option` to accept `?` @@ -52,9 +85,7 @@ LL ~ fn main() -> Result<(), Box> { LL | let mut _file = File::create("foo.txt")?; LL | LL | mac!(); -LL + LL + Ok(()) -LL + } | error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) @@ -76,11 +107,10 @@ LL ~ fn test3() -> Result<(), Box> { LL | let mut _file = File::create("foo.txt")?; LL | LL | println!(); -LL ~ -LL + Ok(()) -LL + } +LL ~ Ok(()) +LL ~ } | -error: aborting due to 4 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.stderr index 79b640d9f41..6b3f303eeab 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.stderr +++ b/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.stderr @@ -2,9 +2,9 @@ error: unreachable pattern --> $DIR/unreachable.rs:14:9 | LL | Err(!), - | ^^^^^^ + | ^^^^^^ matches no values because `Void` is uninhabited | - = note: this pattern matches no values because `Void` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here --> $DIR/unreachable.rs:4:9 | @@ -15,41 +15,41 @@ error: unreachable pattern --> $DIR/unreachable.rs:17:19 | LL | let (Ok(_x) | Err(!)) = res_void; - | ^^^^^^ + | ^^^^^^ matches no values because `Void` is uninhabited | - = note: this pattern matches no values because `Void` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/unreachable.rs:19:12 | LL | if let Err(!) = res_void {} - | ^^^^^^ + | ^^^^^^ matches no values because `Void` is uninhabited | - = note: this pattern matches no values because `Void` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/unreachable.rs:21:24 | LL | if let (Ok(true) | Err(!)) = res_void {} - | ^^^^^^ + | ^^^^^^ matches no values because `Void` is uninhabited | - = note: this pattern matches no values because `Void` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/unreachable.rs:23:23 | LL | for (Ok(mut _x) | Err(!)) in [res_void] {} - | ^^^^^^ + | ^^^^^^ matches no values because `Void` is uninhabited | - = note: this pattern matches no values because `Void` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/unreachable.rs:27:18 | LL | fn foo((Ok(_x) | Err(!)): Result) {} - | ^^^^^^ + | ^^^^^^ matches no values because `Void` is uninhabited | - = note: this pattern matches no values because `Void` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: aborting due to 6 previous errors diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr index d5f58e436c5..dfd7f9d6300 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr @@ -2,9 +2,9 @@ error: unreachable pattern --> $DIR/enum_same_crate_empty_match.rs:28:9 | LL | _ => {} - | ^ + | ^ matches no values because `EmptyNonExhaustiveEnum` is uninhabited | - = note: this pattern matches no values because `EmptyNonExhaustiveEnum` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here --> $DIR/enum_same_crate_empty_match.rs:1:9 | diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr index 4ec4ec9705a..956725fc10e 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr @@ -2,9 +2,9 @@ error: unreachable pattern --> $DIR/issue-65157-repeated-match-arm.rs:15:9 | LL | PartiallyInhabitedVariants::Struct { .. } => {}, - | ----------------------------------------- matches all the values already + | ----------------------------------------- matches all the relevant values LL | PartiallyInhabitedVariants::Struct { .. } => {}, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no value can reach this | note: the lint level is defined here --> $DIR/issue-65157-repeated-match-arm.rs:2:9 diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr index c399bb9083f..7e7dc802e7f 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr @@ -2,9 +2,9 @@ error: unreachable pattern --> $DIR/patterns_same_crate.rs:51:9 | LL | Some(_x) => (), - | ^^^^^^^^ + | ^^^^^^^^ matches no values because `UninhabitedEnum` is uninhabited | - = note: this pattern matches no values because `UninhabitedEnum` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here --> $DIR/patterns_same_crate.rs:1:9 | @@ -15,33 +15,33 @@ error: unreachable pattern --> $DIR/patterns_same_crate.rs:56:9 | LL | Some(_x) => (), - | ^^^^^^^^ + | ^^^^^^^^ matches no values because `UninhabitedVariants` is uninhabited | - = note: this pattern matches no values because `UninhabitedVariants` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/patterns_same_crate.rs:60:15 | LL | while let PartiallyInhabitedVariants::Struct { x } = partially_inhabited_variant() { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ matches no values because `!` is uninhabited | - = note: this pattern matches no values because `!` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/patterns_same_crate.rs:64:15 | LL | while let Some(_x) = uninhabited_struct() { - | ^^^^^^^^ + | ^^^^^^^^ matches no values because `UninhabitedStruct` is uninhabited | - = note: this pattern matches no values because `UninhabitedStruct` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/patterns_same_crate.rs:67:15 | LL | while let Some(_x) = uninhabited_tuple_struct() { - | ^^^^^^^^ + | ^^^^^^^^ matches no values because `UninhabitedTupleStruct` is uninhabited | - = note: this pattern matches no values because `UninhabitedTupleStruct` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: aborting due to 5 previous errors diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/warns.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/warns.stderr index 8d0874fa900..693a06a2297 100644 --- a/tests/ui/rfcs/rfc-2294-if-let-guard/warns.stderr +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/warns.stderr @@ -16,9 +16,9 @@ error: unreachable pattern --> $DIR/warns.rs:15:25 | LL | x if let None | None = x => {} - | ---- ^^^^ unreachable pattern + | ---- ^^^^ no value can reach this | | - | matches all the values already + | matches all the relevant values | note: the lint level is defined here --> $DIR/warns.rs:12:8 diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-cfg.stderr b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-cfg.stderr index 16e1af46059..9b92166bcb7 100644 --- a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-cfg.stderr +++ b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-cfg.stderr @@ -16,6 +16,12 @@ error: unused variable: `a` LL | #[cfg(something)] a: i32, | ^ help: if this is intentional, prefix it with an underscore: `_a` +error: unused variable: `a` + --> $DIR/param-attrs-cfg.rs:107:27 + | +LL | #[cfg(something)] a: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_a` + error: unused variable: `b` --> $DIR/param-attrs-cfg.rs:30:23 | @@ -100,12 +106,6 @@ error: unused variable: `c` LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, | ^ help: if this is intentional, prefix it with an underscore: `_c` -error: unused variable: `a` - --> $DIR/param-attrs-cfg.rs:107:27 - | -LL | #[cfg(something)] a: i32, - | ^ help: if this is intentional, prefix it with an underscore: `_a` - error: unused variable: `b` --> $DIR/param-attrs-cfg.rs:113:27 | diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/multiple-declarations.stderr b/tests/ui/rfcs/rfc-2627-raw-dylib/multiple-declarations.stderr index 7866af59444..b766b5c8dd8 100644 --- a/tests/ui/rfcs/rfc-2627-raw-dylib/multiple-declarations.stderr +++ b/tests/ui/rfcs/rfc-2627-raw-dylib/multiple-declarations.stderr @@ -2,7 +2,7 @@ error: multiple declarations of external function `f` from library `foo.dll` hav --> $DIR/multiple-declarations.rs:13:9 | LL | fn f(x: i32); - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/unsupported-abi.stderr b/tests/ui/rfcs/rfc-2627-raw-dylib/unsupported-abi.stderr index d7c7344b596..ef022404e7f 100644 --- a/tests/ui/rfcs/rfc-2627-raw-dylib/unsupported-abi.stderr +++ b/tests/ui/rfcs/rfc-2627-raw-dylib/unsupported-abi.stderr @@ -2,7 +2,7 @@ error: ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture --> $DIR/unsupported-abi.rs:6:5 | LL | fn f(x: i32); - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail.rs index 637a24f53bc..6c320c0462e 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail.rs @@ -1,4 +1,4 @@ -//@ check-pass +//~ ERROR the trait bound //@ compile-flags: -Znext-solver #![allow(incomplete_features)] @@ -17,6 +17,6 @@ impl Foo for S { } impl const Bar for S {} -//FIXME ~^ ERROR the trait bound +// FIXME(effects) bad span fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail.stderr new file mode 100644 index 00000000000..9a907bbee0a --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail.stderr @@ -0,0 +1,11 @@ +error[E0277]: the trait bound `Maybe: TyCompat<<(Foo::{synthetic#0},) as std::marker::effects::Intersection>::Output>` is not satisfied + | +note: required by a bound in `Bar::{synthetic#0}` + --> $DIR/super-traits-fail.rs:11:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ required by this bound in `Bar::{synthetic#0}` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rust-2024/unsafe-attributes/in_2024_compatibility.rs b/tests/ui/rust-2024/unsafe-attributes/in_2024_compatibility.rs index c6f9115cde7..f3b8645abaf 100644 --- a/tests/ui/rust-2024/unsafe-attributes/in_2024_compatibility.rs +++ b/tests/ui/rust-2024/unsafe-attributes/in_2024_compatibility.rs @@ -1,5 +1,4 @@ #![deny(rust_2024_compatibility)] -#![feature(unsafe_attributes)] #[no_mangle] //~^ ERROR: unsafe attribute used without unsafe diff --git a/tests/ui/rust-2024/unsafe-attributes/in_2024_compatibility.stderr b/tests/ui/rust-2024/unsafe-attributes/in_2024_compatibility.stderr index f0689d9883c..4629a154ac3 100644 --- a/tests/ui/rust-2024/unsafe-attributes/in_2024_compatibility.stderr +++ b/tests/ui/rust-2024/unsafe-attributes/in_2024_compatibility.stderr @@ -1,5 +1,5 @@ error: unsafe attribute used without unsafe - --> $DIR/in_2024_compatibility.rs:4:3 + --> $DIR/in_2024_compatibility.rs:3:3 | LL | #[no_mangle] | ^^^^^^^^^ usage of unsafe attribute diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attribute-marked.rs b/tests/ui/rust-2024/unsafe-attributes/unsafe-attribute-marked.rs index 279ced2525a..7c919fed976 100644 --- a/tests/ui/rust-2024/unsafe-attributes/unsafe-attribute-marked.rs +++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attribute-marked.rs @@ -4,7 +4,6 @@ //@[edition2024] compile-flags: -Zunstable-options //@ check-pass -#![feature(unsafe_attributes)] #[unsafe(no_mangle)] extern "C" fn foo() {} diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.fixed b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.fixed index 6ebdff0334c..586881d1807 100644 --- a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.fixed +++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.fixed @@ -1,5 +1,4 @@ //@ run-rustfix -#![feature(unsafe_attributes)] #![deny(unsafe_attr_outside_unsafe)] macro_rules! tt { diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.rs b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.rs index c78ff45ea4c..03e122c7d57 100644 --- a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.rs +++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.rs @@ -1,5 +1,4 @@ //@ run-rustfix -#![feature(unsafe_attributes)] #![deny(unsafe_attr_outside_unsafe)] macro_rules! tt { diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.stderr b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.stderr index c95984f58ec..64debc58905 100644 --- a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.stderr +++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.stderr @@ -1,5 +1,5 @@ error: unsafe attribute used without unsafe - --> $DIR/unsafe-attributes-fix.rs:44:6 + --> $DIR/unsafe-attributes-fix.rs:43:6 | LL | tt!([no_mangle]); | ^^^^^^^^^ usage of unsafe attribute @@ -7,7 +7,7 @@ LL | tt!([no_mangle]); = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! = note: for more information, see issue #123757 note: the lint level is defined here - --> $DIR/unsafe-attributes-fix.rs:3:9 + --> $DIR/unsafe-attributes-fix.rs:2:9 | LL | #![deny(unsafe_attr_outside_unsafe)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | tt!([unsafe(no_mangle)]); | +++++++ + error: unsafe attribute used without unsafe - --> $DIR/unsafe-attributes-fix.rs:14:11 + --> $DIR/unsafe-attributes-fix.rs:13:11 | LL | #[$e] | ^^ usage of unsafe attribute @@ -34,7 +34,7 @@ LL | #[unsafe($e)] | +++++++ + error: unsafe attribute used without unsafe - --> $DIR/unsafe-attributes-fix.rs:48:7 + --> $DIR/unsafe-attributes-fix.rs:47:7 | LL | meta!(no_mangle); | ^^^^^^^^^ usage of unsafe attribute @@ -47,7 +47,7 @@ LL | meta!(unsafe(no_mangle)); | +++++++ + error: unsafe attribute used without unsafe - --> $DIR/unsafe-attributes-fix.rs:51:8 + --> $DIR/unsafe-attributes-fix.rs:50:8 | LL | meta2!(export_name = "baw"); | ^^^^^^^^^^^ usage of unsafe attribute @@ -60,7 +60,7 @@ LL | meta2!(unsafe(export_name = "baw")); | +++++++ + error: unsafe attribute used without unsafe - --> $DIR/unsafe-attributes-fix.rs:23:11 + --> $DIR/unsafe-attributes-fix.rs:22:11 | LL | #[$e = $l] | ^^ usage of unsafe attribute @@ -77,7 +77,7 @@ LL | #[unsafe($e = $l)] | +++++++ + error: unsafe attribute used without unsafe - --> $DIR/unsafe-attributes-fix.rs:56:3 + --> $DIR/unsafe-attributes-fix.rs:55:3 | LL | #[no_mangle] | ^^^^^^^^^ usage of unsafe attribute diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.edition2024.stderr b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.edition2024.stderr index 35475d66716..fb697e14ef1 100644 --- a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.edition2024.stderr +++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.edition2024.stderr @@ -1,5 +1,5 @@ error: unsafe attribute used without unsafe - --> $DIR/unsafe-attributes.rs:9:3 + --> $DIR/unsafe-attributes.rs:8:3 | LL | #[no_mangle] | ^^^^^^^^^ usage of unsafe attribute diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.rs b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.rs index 3a6af9dfb2b..f6f2994bb6d 100644 --- a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.rs +++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.rs @@ -4,7 +4,6 @@ //@[edition2024] edition:2024 //@[edition2024] compile-flags: -Zunstable-options -#![feature(unsafe_attributes)] #[no_mangle] //[edition2024]~ ERROR: unsafe attribute used without unsafe extern "C" fn foo() {} diff --git a/tests/ui/rust-2024/unsafe-before_exec.e2024.stderr b/tests/ui/rust-2024/unsafe-before_exec.e2024.stderr new file mode 100644 index 00000000000..2798ccdefd0 --- /dev/null +++ b/tests/ui/rust-2024/unsafe-before_exec.e2024.stderr @@ -0,0 +1,11 @@ +error[E0133]: call to unsafe function `before_exec` is unsafe and requires unsafe block + --> $DIR/unsafe-before_exec.rs:14:5 + | +LL | cmd.before_exec(|| Ok(())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/rust-2024/unsafe-before_exec.rs b/tests/ui/rust-2024/unsafe-before_exec.rs new file mode 100644 index 00000000000..540394da80e --- /dev/null +++ b/tests/ui/rust-2024/unsafe-before_exec.rs @@ -0,0 +1,17 @@ +//@ revisions: e2021 e2024 +//@ only-unix +//@[e2021] edition: 2021 +//@[e2021] check-pass +//@[e2024] edition: 2024 +//@[e2024] compile-flags: -Zunstable-options + +use std::process::Command; +use std::os::unix::process::CommandExt; + +#[allow(deprecated)] +fn main() { + let mut cmd = Command::new("sleep"); + cmd.before_exec(|| Ok(())); + //[e2024]~^ ERROR call to unsafe function `before_exec` is unsafe + drop(cmd); // we don't actually run the command. +} diff --git a/tests/ui/rust-2024/unsafe-env-suggestion.stderr b/tests/ui/rust-2024/unsafe-env-suggestion.stderr index 3aa10a3bed6..1506741f6bc 100644 --- a/tests/ui/rust-2024/unsafe-env-suggestion.stderr +++ b/tests/ui/rust-2024/unsafe-env-suggestion.stderr @@ -11,7 +11,7 @@ note: the lint level is defined here | LL | #![deny(deprecated_safe_2024)] | ^^^^^^^^^^^^^^^^^^^^ -help: you can wrap the call in an `unsafe` block if you can guarantee the code is only ever called from single-threaded code +help: you can wrap the call in an `unsafe` block if you can guarantee that the environment access only happens in single-threaded code | LL + // TODO: Audit that the environment access only happens in single-threaded code. LL ~ unsafe { env::set_var("FOO", "BAR") }; @@ -25,7 +25,7 @@ LL | env::remove_var("FOO"); | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! = note: for more information, see issue #27970 -help: you can wrap the call in an `unsafe` block if you can guarantee the code is only ever called from single-threaded code +help: you can wrap the call in an `unsafe` block if you can guarantee that the environment access only happens in single-threaded code | LL + // TODO: Audit that the environment access only happens in single-threaded code. LL ~ unsafe { env::remove_var("FOO") }; diff --git a/tests/ui/sanitizer/cfi/transparent-has-regions.rs b/tests/ui/sanitizer/cfi/transparent-has-regions.rs new file mode 100644 index 00000000000..b70e1ea1791 --- /dev/null +++ b/tests/ui/sanitizer/cfi/transparent-has-regions.rs @@ -0,0 +1,18 @@ +//@ needs-sanitizer-cfi +//@ compile-flags: -Ccodegen-units=1 -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi +//@ no-prefer-dynamic +//@ only-x86_64-unknown-linux-gnu +//@ build-pass + +pub trait Trait {} + +impl Trait for i32 {} + +#[repr(transparent)] +struct BoxedTrait(Box); + +fn hello(x: BoxedTrait) {} + +fn main() { + hello(BoxedTrait(Box::new(1))); +} diff --git a/tests/ui/sanitizer/thread.rs b/tests/ui/sanitizer/thread.rs index 9d9ad6ee518..566774d6b1d 100644 --- a/tests/ui/sanitizer/thread.rs +++ b/tests/ui/sanitizer/thread.rs @@ -20,7 +20,6 @@ //@ error-pattern: Location is heap block of size 4 //@ error-pattern: allocated by main thread -#![feature(raw_ref_op)] #![feature(rustc_private)] extern crate libc; diff --git a/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr index e04ec8bb3bc..216b7053488 100644 --- a/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr +++ b/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -7,10 +7,10 @@ LL | async fn f(self: Pin<&Self>) -> impl Clone { self } | | opaque type defined here | hidden type `Pin<&Foo>` captures the anonymous lifetime defined here | -help: to declare that `impl Clone` captures `'_`, you can add an explicit `'_` lifetime bound +help: add a `use<...>` bound to explicitly capture `'_` | -LL | async fn f(self: Pin<&Self>) -> impl Clone + '_ { self } - | ++++ +LL | async fn f(self: Pin<&Self>) -> impl Clone + use<'_> { self } + | +++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr index a2964881d58..7a2ce110a38 100644 --- a/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr +++ b/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr @@ -7,10 +7,10 @@ LL | fn f(self: Pin<&Self>) -> impl Clone { self } | | opaque type defined here | hidden type `Pin<&Foo>` captures the anonymous lifetime defined here | -help: to declare that `impl Clone` captures `'_`, you can add an explicit `'_` lifetime bound +help: add a `use<...>` bound to explicitly capture `'_` | -LL | fn f(self: Pin<&Self>) -> impl Clone + '_ { self } - | ++++ +LL | fn f(self: Pin<&Self>) -> impl Clone + use<'_> { self } + | +++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/simd/shuffle.rs b/tests/ui/simd/shuffle.rs index 09926d95557..dc0d688284e 100644 --- a/tests/ui/simd/shuffle.rs +++ b/tests/ui/simd/shuffle.rs @@ -6,15 +6,20 @@ #![allow(incomplete_features)] #![feature(adt_const_params)] +use std::marker::ConstParamTy; + extern "rust-intrinsic" { fn simd_shuffle(a: T, b: T, i: I) -> U; } -#[derive(Copy, Clone)] +#[derive(Copy, Clone, ConstParamTy, PartialEq, Eq)] #[repr(simd)] struct Simd([T; N]); -pub unsafe fn __shuffle_vector16(x: T, y: T) -> U { +unsafe fn __shuffle_vector16(x: T, y: T) -> U { + simd_shuffle(x, y, IDX) +} +unsafe fn __shuffle_vector16_v2, T, U>(x: T, y: T) -> U { simd_shuffle(x, y, IDX) } @@ -30,6 +35,17 @@ fn main() { let y: Simd = simd_shuffle(a, b, I2); assert_eq!(y.0, [1, 5]); } + // Test that we can also use a SIMD vector instead of a normal array for the shuffle. + const I1_SIMD: Simd = Simd([0, 2, 4, 6]); + const I2_SIMD: Simd = Simd([1, 5]); + unsafe { + let x: Simd = simd_shuffle(a, b, I1_SIMD); + assert_eq!(x.0, [0, 2, 4, 6]); + + let y: Simd = simd_shuffle(a, b, I2_SIMD); + assert_eq!(y.0, [1, 5]); + } + // Test that an indirection (via an unnamed constant) // through a const generic parameter also works. // See https://github.com/rust-lang/rust/issues/113500 for details. @@ -42,4 +58,11 @@ fn main() { Simd, >(a, b); } + unsafe { + __shuffle_vector16_v2::< + { Simd([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]) }, + Simd, + Simd, + >(a, b); + } } diff --git a/tests/ui/sized/unsized-binding.stderr b/tests/ui/sized/unsized-binding.stderr index 7c3276032c2..8de236cd0b6 100644 --- a/tests/ui/sized/unsized-binding.stderr +++ b/tests/ui/sized/unsized-binding.stderr @@ -7,6 +7,11 @@ LL | let x = *""; = help: the trait `Sized` is not implemented for `str` = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - let x = *""; +LL + let x = ""; + | error: aborting due to 1 previous error diff --git a/tests/ui/sized/unsized-str-in-return-expr-arg-and-local.rs b/tests/ui/sized/unsized-str-in-return-expr-arg-and-local.rs new file mode 100644 index 00000000000..35abbb80d99 --- /dev/null +++ b/tests/ui/sized/unsized-str-in-return-expr-arg-and-local.rs @@ -0,0 +1,30 @@ +fn foo() -> impl Sized { +//~^ ERROR the size for values of type `str` cannot be known at compilation time +//~| HELP the trait `Sized` is not implemented for `str` + *"" //~ HELP consider not dereferencing the expression +} +fn bar(_: impl Sized) {} +struct S; + +impl S { + fn baz(&self, _: impl Sized) {} +} + +fn main() { + let _ = foo(); + let x = *""; + //~^ ERROR the size for values of type `str` cannot be known at compilation time + //~| HELP consider not dereferencing the expression + //~| HELP the trait `Sized` is not implemented for `str` + //~| HELP unsized locals are gated as an unstable feature + bar(x); + S.baz(x); + bar(*""); + //~^ ERROR the size for values of type `str` cannot be known at compilation time + //~| HELP consider not dereferencing the expression + //~| HELP the trait `Sized` is not implemented for `str` + S.baz(*""); + //~^ ERROR the size for values of type `str` cannot be known at compilation time + //~| HELP consider not dereferencing the expression + //~| HELP the trait `Sized` is not implemented for `str` +} diff --git a/tests/ui/sized/unsized-str-in-return-expr-arg-and-local.stderr b/tests/ui/sized/unsized-str-in-return-expr-arg-and-local.stderr new file mode 100644 index 00000000000..9b7258aff12 --- /dev/null +++ b/tests/ui/sized/unsized-str-in-return-expr-arg-and-local.stderr @@ -0,0 +1,74 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/unsized-str-in-return-expr-arg-and-local.rs:1:13 + | +LL | fn foo() -> impl Sized { + | ^^^^^^^^^^ doesn't have a size known at compile-time +... +LL | *"" + | --- return type was inferred to be `str` here + | + = help: the trait `Sized` is not implemented for `str` +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - *"" +LL + "" + | + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/unsized-str-in-return-expr-arg-and-local.rs:15:9 + | +LL | let x = *""; + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - let x = *""; +LL + let x = ""; + | + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/unsized-str-in-return-expr-arg-and-local.rs:22:9 + | +LL | bar(*""); + | --- ^^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `str` +note: required by a bound in `bar` + --> $DIR/unsized-str-in-return-expr-arg-and-local.rs:6:16 + | +LL | fn bar(_: impl Sized) {} + | ^^^^^ required by this bound in `bar` +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - bar(*""); +LL + bar(""); + | + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/unsized-str-in-return-expr-arg-and-local.rs:26:11 + | +LL | S.baz(*""); + | --- ^^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `str` +note: required by a bound in `S::baz` + --> $DIR/unsized-str-in-return-expr-arg-and-local.rs:10:27 + | +LL | fn baz(&self, _: impl Sized) {} + | ^^^^^ required by this bound in `S::baz` +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - S.baz(*""); +LL + S.baz(""); + | + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.rs b/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.rs index fb962ad24bf..858fba2132a 100644 --- a/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.rs +++ b/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.rs @@ -14,5 +14,6 @@ struct Wrapper::Type> {} impl Wrapper {} //~^ ERROR the constant `C` is not of type `::Type` +//~| ERROR: mismatched types fn main() {} diff --git a/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.stderr b/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.stderr index 7094ee8c67c..71d4277275f 100644 --- a/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.stderr +++ b/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.stderr @@ -20,5 +20,17 @@ note: required by a const generic parameter in `Wrapper` LL | struct Wrapper::Type> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this const generic parameter in `Wrapper` -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/default-proj-ty-as-type-of-const-issue-125757.rs:15:30 + | +LL | impl Wrapper {} + | ^ expected associated type, found `usize` + | + = note: expected associated type `::Type` + found type `usize` + = help: consider constraining the associated type `::Type` to `usize` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs index a0ee7714417..f89a463bc58 100644 --- a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs +++ b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs @@ -6,6 +6,7 @@ struct S; impl Copy for S {} +//~^ ERROR: mismatched types impl Copy for S {} //~^ ERROR: conflicting implementations of trait `Copy` for type `S<_>` diff --git a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr index 2953bc95917..1dac58e1f69 100644 --- a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr +++ b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr @@ -1,11 +1,19 @@ error[E0119]: conflicting implementations of trait `Copy` for type `S<_>` - --> $DIR/bad-const-wf-doesnt-specialize.rs:9:1 + --> $DIR/bad-const-wf-doesnt-specialize.rs:10:1 | LL | impl Copy for S {} | -------------------------------- first implementation here +LL | LL | impl Copy for S {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `S<_>` -error: aborting due to 1 previous error +error[E0308]: mismatched types + --> $DIR/bad-const-wf-doesnt-specialize.rs:8:31 + | +LL | impl Copy for S {} + | ^ expected `usize`, found `i32` -For more information about this error, try `rustc --explain E0119`. +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0119, E0308. +For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/static/raw-ref-extern-static.rs b/tests/ui/static/raw-ref-extern-static.rs index 95a53a8640d..81bc5990efe 100644 --- a/tests/ui/static/raw-ref-extern-static.rs +++ b/tests/ui/static/raw-ref-extern-static.rs @@ -1,5 +1,4 @@ //@ check-pass -#![feature(raw_ref_op)] use std::ptr; // see https://github.com/rust-lang/rust/issues/125833 diff --git a/tests/ui/static/raw-ref-static-mut.rs b/tests/ui/static/raw-ref-static-mut.rs index 6855cc7b050..d4159fc65ca 100644 --- a/tests/ui/static/raw-ref-static-mut.rs +++ b/tests/ui/static/raw-ref-static-mut.rs @@ -1,5 +1,4 @@ //@ check-pass -#![feature(raw_ref_op)] use std::ptr; // see https://github.com/rust-lang/rust/issues/125833 diff --git a/tests/ui/suggestions/issue-84973-blacklist.stderr b/tests/ui/suggestions/issue-84973-blacklist.stderr index 4fd063e4692..c1ef1cd428e 100644 --- a/tests/ui/suggestions/issue-84973-blacklist.stderr +++ b/tests/ui/suggestions/issue-84973-blacklist.stderr @@ -66,6 +66,11 @@ note: required by a bound in `f_sized` | LL | fn f_sized(t: T) {} | ^^^^^ required by this bound in `f_sized` +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - f_sized(*ref_cl); +LL + f_sized(ref_cl); + | error[E0277]: `Rc<{integer}>` cannot be sent between threads safely --> $DIR/issue-84973-blacklist.rs:27:12 diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index 64af17c830e..88a18e9d06d 100644 --- a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -20,10 +20,10 @@ LL | | *dest = g.get(); LL | | } | |_____^ | -help: to declare that `impl FnOnce()` captures `'_`, you can add an explicit `'_` lifetime bound +help: add a `use<...>` bound to explicitly capture `'_` | -LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() + '_ - | ++++ +LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() + use<'_, G, T> + | +++++++++++++++ error[E0311]: the parameter type `G` may not live long enough --> $DIR/missing-lifetimes-in-signature.rs:30:5 diff --git a/tests/ui/target-feature/gate.rs b/tests/ui/target-feature/gate.rs index 94d79d56c59..5c4fb847932 100644 --- a/tests/ui/target-feature/gate.rs +++ b/tests/ui/target-feature/gate.rs @@ -17,6 +17,7 @@ // gate-test-ermsb_target_feature // gate-test-bpf_target_feature // gate-test-aarch64_ver_target_feature +// gate-test-aarch64_unstable_target_feature // gate-test-csky_target_feature // gate-test-loongarch_target_feature // gate-test-lahfsahf_target_feature diff --git a/tests/ui/target-feature/gate.stderr b/tests/ui/target-feature/gate.stderr index a69020e6864..37c5ed01688 100644 --- a/tests/ui/target-feature/gate.stderr +++ b/tests/ui/target-feature/gate.stderr @@ -1,5 +1,5 @@ error[E0658]: the target feature `avx512bw` is currently unstable - --> $DIR/gate.rs:26:18 + --> $DIR/gate.rs:27:18 | LL | #[target_feature(enable = "avx512bw")] | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/target-feature/struct-target-features.rs b/tests/ui/target-feature/struct-target-features.rs new file mode 100644 index 00000000000..feb479b6dc8 --- /dev/null +++ b/tests/ui/target-feature/struct-target-features.rs @@ -0,0 +1,98 @@ +//@ only-x86_64 +#![feature(struct_target_features)] +//~^ WARNING the feature `struct_target_features` is incomplete and may not be safe to use and/or cause compiler crashes +#![feature(target_feature_11)] + +use std::arch::x86_64::*; + +#[target_feature(enable = "avx")] +//~^ ERROR attribute should be applied to a function definition or unit struct +struct Invalid(u32); + +#[target_feature(enable = "avx")] +struct Avx {} + +#[target_feature(enable = "sse")] +struct Sse(); + +#[target_feature(enable = "avx")] +fn avx() {} + +trait TFAssociatedType { + type Assoc; +} + +impl TFAssociatedType for () { + type Assoc = Avx; +} + +fn avx_self(_: <() as TFAssociatedType>::Assoc) { + avx(); +} + +fn avx_avx(_: Avx) { + avx(); +} + +extern "C" fn bad_fun(_: Avx) {} +//~^ ERROR cannot use a struct with target features in a function with non-Rust ABI + +#[inline(always)] +//~^ ERROR cannot use `#[inline(always)]` with `#[target_feature]` +fn inline_fun(_: Avx) {} +//~^ ERROR cannot use a struct with target features in a #[inline(always)] function + +trait Simd { + fn do_something(&self); +} + +impl Simd for Avx { + fn do_something(&self) { + unsafe { + println!("{:?}", _mm256_setzero_ps()); + } + } +} + +impl Simd for Sse { + fn do_something(&self) { + unsafe { + println!("{:?}", _mm_setzero_ps()); + } + } +} + +struct WithAvx { + #[allow(dead_code)] + avx: Avx, +} + +impl Simd for WithAvx { + fn do_something(&self) { + unsafe { + println!("{:?}", _mm256_setzero_ps()); + } + } +} + +#[inline(never)] +fn dosomething(simd: &S) { + simd.do_something(); +} + +fn avxfn(_: &Avx) {} + +fn main() { + Avx {}; + //~^ ERROR initializing type with `target_feature` attr is unsafe and requires unsafe function or block [E0133] + + if is_x86_feature_detected!("avx") { + let avx = unsafe { Avx {} }; + avxfn(&avx); + dosomething(&avx); + dosomething(&WithAvx { avx }); + } + if is_x86_feature_detected!("sse") { + dosomething(&unsafe { Sse {} }) + } +} diff --git a/tests/ui/target-feature/struct-target-features.stderr b/tests/ui/target-feature/struct-target-features.stderr new file mode 100644 index 00000000000..5ef863f504e --- /dev/null +++ b/tests/ui/target-feature/struct-target-features.stderr @@ -0,0 +1,47 @@ +warning: the feature `struct_target_features` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/struct-target-features.rs:2:12 + | +LL | #![feature(struct_target_features)] + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #129107 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: attribute should be applied to a function definition or unit struct + --> $DIR/struct-target-features.rs:8:1 + | +LL | #[target_feature(enable = "avx")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | struct Invalid(u32); + | -------------------- not a function definition or a unit struct + +error: cannot use a struct with target features in a function with non-Rust ABI + --> $DIR/struct-target-features.rs:37:1 + | +LL | extern "C" fn bad_fun(_: Avx) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: cannot use a struct with target features in a #[inline(always)] function + --> $DIR/struct-target-features.rs:42:1 + | +LL | fn inline_fun(_: Avx) {} + | ^^^^^^^^^^^^^^^^^^^^^ + +error: cannot use `#[inline(always)]` with `#[target_feature]` + --> $DIR/struct-target-features.rs:40:1 + | +LL | #[inline(always)] + | ^^^^^^^^^^^^^^^^^ + +error[E0133]: initializing type with `target_feature` attr is unsafe and requires unsafe function or block + --> $DIR/struct-target-features.rs:86:5 + | +LL | Avx {}; + | ^^^^^^ initializing type with `target_feature` attr + | + = note: this struct can only be constructed if the corresponding `target_feature`s are available + +error: aborting due to 5 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/threads-sendsync/child-outlives-parent.rs b/tests/ui/threads-sendsync/child-outlives-parent.rs index 213fd008cd3..e965bac5713 100644 --- a/tests/ui/threads-sendsync/child-outlives-parent.rs +++ b/tests/ui/threads-sendsync/child-outlives-parent.rs @@ -6,8 +6,8 @@ use std::thread; -fn child2(_s: String) { } +fn child2(_s: String) {} pub fn main() { - let _x = thread::spawn(move|| child2("hi".to_string())); + let _x = thread::spawn(move || child2("hi".to_string())); } diff --git a/tests/ui/threads-sendsync/clone-with-exterior.rs b/tests/ui/threads-sendsync/clone-with-exterior.rs index 67790367e27..9d5ac4b16aa 100644 --- a/tests/ui/threads-sendsync/clone-with-exterior.rs +++ b/tests/ui/threads-sendsync/clone-with-exterior.rs @@ -7,14 +7,15 @@ use std::thread; struct Pair { a: isize, - b: isize + b: isize, } pub fn main() { - let z: Box<_> = Box::new(Pair { a : 10, b : 12}); + let z: Box<_> = Box::new(Pair { a: 10, b: 12 }); - thread::spawn(move|| { + thread::spawn(move || { assert_eq!(z.a, 10); assert_eq!(z.b, 12); - }).join(); + }) + .join(); } diff --git a/tests/ui/threads-sendsync/comm.rs b/tests/ui/threads-sendsync/comm.rs index 0c37fda8a39..3eb68707e78 100644 --- a/tests/ui/threads-sendsync/comm.rs +++ b/tests/ui/threads-sendsync/comm.rs @@ -2,12 +2,12 @@ #![allow(unused_must_use)] //@ needs-threads -use std::thread; use std::sync::mpsc::{channel, Sender}; +use std::thread; pub fn main() { let (tx, rx) = channel(); - let t = thread::spawn(move || { child(&tx) }); + let t = thread::spawn(move || child(&tx)); let y = rx.recv().unwrap(); println!("received"); println!("{}", y); diff --git a/tests/ui/threads-sendsync/issue-24313.rs b/tests/ui/threads-sendsync/issue-24313.rs index 1ea862f1e7d..99c6c4a5e12 100644 --- a/tests/ui/threads-sendsync/issue-24313.rs +++ b/tests/ui/threads-sendsync/issue-24313.rs @@ -2,14 +2,15 @@ //@ needs-threads //@ ignore-sgx no processes -use std::thread; -use std::env; use std::process::Command; +use std::{env, thread}; struct Handle(i32); impl Drop for Handle { - fn drop(&mut self) { panic!(); } + fn drop(&mut self) { + panic!(); + } } thread_local!(static HANDLE: Handle = Handle(0)); @@ -19,14 +20,15 @@ fn main() { if args.len() == 1 { let out = Command::new(&args[0]).arg("test").output().unwrap(); let stderr = std::str::from_utf8(&out.stderr).unwrap(); - assert!(stderr.contains("explicit panic"), - "bad failure message:\n{}\n", stderr); + assert!(stderr.contains("explicit panic"), "bad failure message:\n{}\n", stderr); } else { // TLS dtors are not always run on process exit thread::spawn(|| { HANDLE.with(|h| { println!("{}", h.0); }); - }).join().unwrap(); + }) + .join() + .unwrap(); } } diff --git a/tests/ui/threads-sendsync/issue-29488.rs b/tests/ui/threads-sendsync/issue-29488.rs index fbbd6b02a06..5ce27faed76 100644 --- a/tests/ui/threads-sendsync/issue-29488.rs +++ b/tests/ui/threads-sendsync/issue-29488.rs @@ -19,5 +19,7 @@ fn main() { thread::spawn(|| { FOO.with(|_| {}); println!("test1"); - }).join().unwrap(); + }) + .join() + .unwrap(); } diff --git a/tests/ui/threads-sendsync/issue-4446.rs b/tests/ui/threads-sendsync/issue-4446.rs index aa2de51974b..5652ad7de55 100644 --- a/tests/ui/threads-sendsync/issue-4446.rs +++ b/tests/ui/threads-sendsync/issue-4446.rs @@ -9,7 +9,10 @@ pub fn main() { tx.send("hello, world").unwrap(); - thread::spawn(move|| { + thread::spawn(move || { println!("{}", rx.recv().unwrap()); - }).join().ok().unwrap(); + }) + .join() + .ok() + .unwrap(); } diff --git a/tests/ui/threads-sendsync/issue-4448.rs b/tests/ui/threads-sendsync/issue-4448.rs index b8324a8c43f..1adebd1e252 100644 --- a/tests/ui/threads-sendsync/issue-4448.rs +++ b/tests/ui/threads-sendsync/issue-4448.rs @@ -7,7 +7,7 @@ use std::thread; pub fn main() { let (tx, rx) = channel::<&'static str>(); - let t = thread::spawn(move|| { + let t = thread::spawn(move || { assert_eq!(rx.recv().unwrap(), "hello, world"); }); diff --git a/tests/ui/threads-sendsync/issue-8827.rs b/tests/ui/threads-sendsync/issue-8827.rs index fa07a4ebc7d..57fc87db768 100644 --- a/tests/ui/threads-sendsync/issue-8827.rs +++ b/tests/ui/threads-sendsync/issue-8827.rs @@ -1,12 +1,12 @@ //@ run-pass //@ needs-threads -use std::thread; use std::sync::mpsc::{channel, Receiver}; +use std::thread; fn periodical(n: isize) -> Receiver { let (chan, port) = channel(); - thread::spawn(move|| { + thread::spawn(move || { loop { for _ in 1..n { match chan.send(false) { @@ -16,7 +16,7 @@ fn periodical(n: isize) -> Receiver { } match chan.send(true) { Ok(()) => {} - Err(..) => break + Err(..) => break, } } }); @@ -25,7 +25,7 @@ fn periodical(n: isize) -> Receiver { fn integers() -> Receiver { let (chan, port) = channel(); - thread::spawn(move|| { + thread::spawn(move || { let mut i = 1; loop { match chan.send(i) { @@ -47,7 +47,7 @@ fn main() { (_, true, true) => println!("FizzBuzz"), (_, true, false) => println!("Fizz"), (_, false, true) => println!("Buzz"), - (i, false, false) => println!("{}", i) + (i, false, false) => println!("{}", i), } } } diff --git a/tests/ui/threads-sendsync/issue-9396.rs b/tests/ui/threads-sendsync/issue-9396.rs index 6b5907e5c1d..b532ddf104d 100644 --- a/tests/ui/threads-sendsync/issue-9396.rs +++ b/tests/ui/threads-sendsync/issue-9396.rs @@ -3,12 +3,12 @@ #![allow(deprecated)] //@ needs-threads -use std::sync::mpsc::{TryRecvError, channel}; +use std::sync::mpsc::{channel, TryRecvError}; use std::thread; pub fn main() { let (tx, rx) = channel(); - let t = thread::spawn(move||{ + let t = thread::spawn(move || { thread::sleep_ms(10); tx.send(()).unwrap(); }); @@ -16,7 +16,7 @@ pub fn main() { match rx.try_recv() { Ok(()) => break, Err(TryRecvError::Empty) => {} - Err(TryRecvError::Disconnected) => unreachable!() + Err(TryRecvError::Disconnected) => unreachable!(), } } t.join(); diff --git a/tests/ui/threads-sendsync/mpsc_stress.rs b/tests/ui/threads-sendsync/mpsc_stress.rs index f5354c60bfc..fe0b47f3a84 100644 --- a/tests/ui/threads-sendsync/mpsc_stress.rs +++ b/tests/ui/threads-sendsync/mpsc_stress.rs @@ -2,18 +2,12 @@ //@ compile-flags:--test //@ needs-threads -use std::sync::mpsc::channel; -use std::sync::mpsc::TryRecvError; -use std::sync::mpsc::RecvError; -use std::sync::mpsc::RecvTimeoutError; +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::mpsc::{channel, RecvError, RecvTimeoutError, TryRecvError}; use std::sync::Arc; -use std::sync::atomic::AtomicUsize; -use std::sync::atomic::Ordering; - use std::thread; use std::time::Duration; - /// Simple thread synchronization utility struct Barrier { // Not using mutex/condvar for precision @@ -42,7 +36,6 @@ impl Barrier { } } - fn shared_close_sender_does_not_lose_messages_iter() { let (tb, rb) = Barrier::new2(); @@ -71,7 +64,6 @@ fn shared_close_sender_does_not_lose_messages() { }); } - // https://github.com/rust-lang/rust/issues/39364 fn concurrent_recv_timeout_and_upgrade_iter() { // 1 us @@ -85,8 +77,8 @@ fn concurrent_recv_timeout_and_upgrade_iter() { match rx.recv_timeout(sleep) { Ok(_) => { break; - }, - Err(_) => {}, + } + Err(_) => {} } } }); @@ -105,7 +97,6 @@ fn concurrent_recv_timeout_and_upgrade() { }); } - fn concurrent_writes_iter() { const THREADS: usize = 4; const PER_THR: usize = 100; diff --git a/tests/ui/threads-sendsync/send-is-not-static-par-for.rs b/tests/ui/threads-sendsync/send-is-not-static-par-for.rs index b943b0c433d..dd02166c0fa 100644 --- a/tests/ui/threads-sendsync/send-is-not-static-par-for.rs +++ b/tests/ui/threads-sendsync/send-is-not-static-par-for.rs @@ -1,12 +1,13 @@ //@ run-pass #![allow(unused_imports)] -use std::thread; use std::sync::Mutex; +use std::thread; fn par_for(iter: I, f: F) - where I: Iterator, - I::Item: Send, - F: Fn(I::Item) + Sync +where + I: Iterator, + I::Item: Send, + F: Fn(I::Item) + Sync, { for item in iter { f(item) @@ -15,9 +16,7 @@ fn par_for(iter: I, f: F) fn sum(x: &[i32]) { let sum_lengths = Mutex::new(0); - par_for(x.windows(4), |x| { - *sum_lengths.lock().unwrap() += x.len() - }); + par_for(x.windows(4), |x| *sum_lengths.lock().unwrap() += x.len()); assert_eq!(*sum_lengths.lock().unwrap(), (x.len() - 3) * 4); } @@ -26,9 +25,7 @@ fn main() { let mut elements = [0; 20]; // iterators over references into this stack frame - par_for(elements.iter_mut().enumerate(), |(i, x)| { - *x = i as i32 - }); + par_for(elements.iter_mut().enumerate(), |(i, x)| *x = i as i32); sum(&elements) } diff --git a/tests/ui/threads-sendsync/send-resource.rs b/tests/ui/threads-sendsync/send-resource.rs index 3e1532b3132..c02a3717d3d 100644 --- a/tests/ui/threads-sendsync/send-resource.rs +++ b/tests/ui/threads-sendsync/send-resource.rs @@ -6,11 +6,11 @@ //@ pretty-expanded FIXME #23616 //@ needs-threads -use std::thread; use std::sync::mpsc::channel; +use std::thread; struct test { - f: isize, + f: isize, } impl Drop for test { @@ -18,15 +18,13 @@ impl Drop for test { } fn test(f: isize) -> test { - test { - f: f - } + test { f: f } } pub fn main() { let (tx, rx) = channel(); - let t = thread::spawn(move|| { + let t = thread::spawn(move || { let (tx2, rx2) = channel(); tx.send(tx2).unwrap(); diff --git a/tests/ui/threads-sendsync/send-type-inference.rs b/tests/ui/threads-sendsync/send-type-inference.rs index 287b3d567ae..7608c19b575 100644 --- a/tests/ui/threads-sendsync/send-type-inference.rs +++ b/tests/ui/threads-sendsync/send-type-inference.rs @@ -9,11 +9,11 @@ use std::sync::mpsc::{channel, Sender}; // tests that ctrl's type gets inferred properly struct Command { key: K, - val: V + val: V, } -fn cache_server(mut tx: Sender>>) { +fn cache_server(mut tx: Sender>>) { let (tx1, _rx) = channel(); tx.send(tx1); } -pub fn main() { } +pub fn main() {} diff --git a/tests/ui/threads-sendsync/send_str_hashmap.rs b/tests/ui/threads-sendsync/send_str_hashmap.rs index 9cbb0bed447..2675b162190 100644 --- a/tests/ui/threads-sendsync/send_str_hashmap.rs +++ b/tests/ui/threads-sendsync/send_str_hashmap.rs @@ -1,9 +1,7 @@ //@ run-pass -use std::collections::HashMap; use std::borrow::Cow; - -use std::borrow::Cow::Borrowed as B; -use std::borrow::Cow::Owned as O; +use std::borrow::Cow::{Borrowed as B, Owned as O}; +use std::collections::HashMap; type SendStr = Cow<'static, str>; diff --git a/tests/ui/threads-sendsync/send_str_treemap.rs b/tests/ui/threads-sendsync/send_str_treemap.rs index cc1f560f69b..3e0eace3399 100644 --- a/tests/ui/threads-sendsync/send_str_treemap.rs +++ b/tests/ui/threads-sendsync/send_str_treemap.rs @@ -1,8 +1,7 @@ //@ run-pass -use std::collections::BTreeMap; use std::borrow::Cow; - -use std::borrow::Cow::{Owned as O, Borrowed as B}; +use std::borrow::Cow::{Borrowed as B, Owned as O}; +use std::collections::BTreeMap; type SendStr = Cow<'static, str>; @@ -51,8 +50,8 @@ fn main() { assert_eq!(map.get(&O("def".to_string())), Some(&d)); assert!(map.remove(&B("foo")).is_some()); - assert_eq!(map.into_iter().map(|(k, v)| format!("{}{}", k, v)) - .collect::>() - .concat(), - "abc50bcd51cde52def53".to_string()); + assert_eq!( + map.into_iter().map(|(k, v)| format!("{}{}", k, v)).collect::>().concat(), + "abc50bcd51cde52def53".to_string() + ); } diff --git a/tests/ui/threads-sendsync/sendable-class.rs b/tests/ui/threads-sendsync/sendable-class.rs index 3ee1b60a04a..8e5e76d826a 100644 --- a/tests/ui/threads-sendsync/sendable-class.rs +++ b/tests/ui/threads-sendsync/sendable-class.rs @@ -11,15 +11,12 @@ use std::sync::mpsc::channel; struct foo { - i: isize, - j: char, + i: isize, + j: char, } -fn foo(i:isize, j: char) -> foo { - foo { - i: i, - j: j - } +fn foo(i: isize, j: char) -> foo { + foo { i: i, j: j } } pub fn main() { diff --git a/tests/ui/threads-sendsync/sendfn-is-a-block.rs b/tests/ui/threads-sendsync/sendfn-is-a-block.rs index f01b440424a..9afa1c47b65 100644 --- a/tests/ui/threads-sendsync/sendfn-is-a-block.rs +++ b/tests/ui/threads-sendsync/sendfn-is-a-block.rs @@ -1,7 +1,9 @@ //@ run-pass - -fn test(f: F) -> usize where F: FnOnce(usize) -> usize { +fn test(f: F) -> usize +where + F: FnOnce(usize) -> usize, +{ return f(22); } diff --git a/tests/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs b/tests/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs index 63cf3ff4049..79a71e968f9 100644 --- a/tests/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs +++ b/tests/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs @@ -3,19 +3,24 @@ use std::thread; -pub fn main() { test05(); } +pub fn main() { + test05(); +} -fn test05_start(f: F) { +fn test05_start(f: F) { f(22); } fn test05() { let three: Box<_> = Box::new(3); - let fn_to_send = move|n:isize| { + let fn_to_send = move |n: isize| { println!("{}", *three + n); // will copy x into the closure assert_eq!(*three, 3); }; - thread::spawn(move|| { + thread::spawn(move || { test05_start(fn_to_send); - }).join().ok().unwrap(); + }) + .join() + .ok() + .unwrap(); } diff --git a/tests/ui/threads-sendsync/spawn-fn.rs b/tests/ui/threads-sendsync/spawn-fn.rs index e4d83b53f3c..558c2d515aa 100644 --- a/tests/ui/threads-sendsync/spawn-fn.rs +++ b/tests/ui/threads-sendsync/spawn-fn.rs @@ -10,9 +10,9 @@ fn x(s: String, n: isize) { } pub fn main() { - let t1 = thread::spawn(|| x("hello from first spawned fn".to_string(), 65) ); - let t2 = thread::spawn(|| x("hello from second spawned fn".to_string(), 66) ); - let t3 = thread::spawn(|| x("hello from third spawned fn".to_string(), 67) ); + let t1 = thread::spawn(|| x("hello from first spawned fn".to_string(), 65)); + let t2 = thread::spawn(|| x("hello from second spawned fn".to_string(), 66)); + let t3 = thread::spawn(|| x("hello from third spawned fn".to_string(), 67)); let mut i = 30; while i > 0 { i = i - 1; diff --git a/tests/ui/threads-sendsync/spawn-types.rs b/tests/ui/threads-sendsync/spawn-types.rs index 2a7a9e2f497..e53385aa714 100644 --- a/tests/ui/threads-sendsync/spawn-types.rs +++ b/tests/ui/threads-sendsync/spawn-types.rs @@ -4,13 +4,13 @@ //@ needs-threads /* - Make sure we can spawn tasks that take different types of - parameters. This is based on a test case for #520 provided by Rob - Arnold. - */ + Make sure we can spawn tasks that take different types of + parameters. This is based on a test case for #520 provided by Rob + Arnold. +*/ -use std::thread; use std::sync::mpsc::{channel, Sender}; +use std::thread; type ctx = Sender; @@ -20,6 +20,6 @@ fn iotask(_tx: &ctx, ip: String) { pub fn main() { let (tx, _rx) = channel::(); - let t = thread::spawn(move|| iotask(&tx, "localhost".to_string()) ); + let t = thread::spawn(move || iotask(&tx, "localhost".to_string())); t.join().ok().unwrap(); } diff --git a/tests/ui/threads-sendsync/spawn.rs b/tests/ui/threads-sendsync/spawn.rs index c7b344b9f75..c9f7c40ddb8 100644 --- a/tests/ui/threads-sendsync/spawn.rs +++ b/tests/ui/threads-sendsync/spawn.rs @@ -4,7 +4,10 @@ use std::thread; pub fn main() { - thread::spawn(move|| child(10)).join().ok().unwrap(); + thread::spawn(move || child(10)).join().ok().unwrap(); } -fn child(i: isize) { println!("{}", i); assert_eq!(i, 10); } +fn child(i: isize) { + println!("{}", i); + assert_eq!(i, 10); +} diff --git a/tests/ui/threads-sendsync/spawn2.rs b/tests/ui/threads-sendsync/spawn2.rs index 8278fec1885..02dff2a3483 100644 --- a/tests/ui/threads-sendsync/spawn2.rs +++ b/tests/ui/threads-sendsync/spawn2.rs @@ -4,7 +4,7 @@ use std::thread; pub fn main() { - let t = thread::spawn(move|| child((10, 20, 30, 40, 50, 60, 70, 80, 90)) ); + let t = thread::spawn(move || child((10, 20, 30, 40, 50, 60, 70, 80, 90))); t.join().ok().unwrap(); // forget Err value, since it doesn't implement Debug } diff --git a/tests/ui/threads-sendsync/sync-send-in-std.rs b/tests/ui/threads-sendsync/sync-send-in-std.rs index 3a97cbb0c68..ddf026236a8 100644 --- a/tests/ui/threads-sendsync/sync-send-in-std.rs +++ b/tests/ui/threads-sendsync/sync-send-in-std.rs @@ -6,8 +6,16 @@ use std::net::ToSocketAddrs; -fn is_sync(_: T) where T: Sync {} -fn is_send(_: T) where T: Send {} +fn is_sync(_: T) +where + T: Sync, +{ +} +fn is_send(_: T) +where + T: Send, +{ +} macro_rules! all_sync_send { ($ctor:expr, $($iter:ident),+) => ({ diff --git a/tests/ui/threads-sendsync/sync-send-iterators-in-libcollections.rs b/tests/ui/threads-sendsync/sync-send-iterators-in-libcollections.rs index 3b8fdb60acf..51d5e294b38 100644 --- a/tests/ui/threads-sendsync/sync-send-iterators-in-libcollections.rs +++ b/tests/ui/threads-sendsync/sync-send-iterators-in-libcollections.rs @@ -3,18 +3,20 @@ #![allow(warnings)] #![feature(drain, collections_bound, btree_range)] -use std::collections::BinaryHeap; -use std::collections::{BTreeMap, BTreeSet}; -use std::collections::LinkedList; -use std::collections::VecDeque; -use std::collections::HashMap; -use std::collections::HashSet; - +use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque}; use std::mem; use std::ops::Bound::Included; -fn is_sync(_: T) where T: Sync {} -fn is_send(_: T) where T: Send {} +fn is_sync(_: T) +where + T: Sync, +{ +} +fn is_send(_: T) +where + T: Send, +{ +} macro_rules! all_sync_send { ($ctor:expr, $($iter:ident),+) => ({ diff --git a/tests/ui/threads-sendsync/sync-send-iterators-in-libcore.rs b/tests/ui/threads-sendsync/sync-send-iterators-in-libcore.rs index 4c77b5d2ad8..512c81a85fc 100644 --- a/tests/ui/threads-sendsync/sync-send-iterators-in-libcore.rs +++ b/tests/ui/threads-sendsync/sync-send-iterators-in-libcore.rs @@ -5,8 +5,16 @@ use std::iter::{empty, once, repeat}; -fn is_sync(_: T) where T: Sync {} -fn is_send(_: T) where T: Send {} +fn is_sync(_: T) +where + T: Sync, +{ +} +fn is_send(_: T) +where + T: Send, +{ +} macro_rules! all_sync_send { ($ctor:expr, $iter:ident) => ({ @@ -43,12 +51,12 @@ macro_rules! all_sync_send_mutable_ref { } macro_rules! is_sync_send { - ($ctor:expr) => ({ + ($ctor:expr) => {{ let x = $ctor; is_sync(x); let y = $ctor; is_send(y); - }) + }}; } fn main() { @@ -63,24 +71,26 @@ fn main() { let a = [1]; let b = [2]; - all_sync_send!(a.iter(), - cloned, - cycle, - chain([2].iter()), - zip([2].iter()), - map(|_| 1), - filter(|_| true), - filter_map(|_| Some(1)), - enumerate, - peekable, - skip_while(|_| true), - take_while(|_| true), - skip(1), - take(1), - scan(1, |_, _| Some(1)), - flat_map(|_| b.iter()), - fuse, - inspect(|_| ())); + all_sync_send!( + a.iter(), + cloned, + cycle, + chain([2].iter()), + zip([2].iter()), + map(|_| 1), + filter(|_| true), + filter_map(|_| Some(1)), + enumerate, + peekable, + skip_while(|_| true), + take_while(|_| true), + skip(1), + take(1), + scan(1, |_, _| Some(1)), + flat_map(|_| b.iter()), + fuse, + inspect(|_| ()) + ); is_sync_send!((1..).step_by(2)); is_sync_send!((1..2).step_by(2)); diff --git a/tests/ui/threads-sendsync/task-comm-0.rs b/tests/ui/threads-sendsync/task-comm-0.rs index 50f2b591894..c4fe36e770d 100644 --- a/tests/ui/threads-sendsync/task-comm-0.rs +++ b/tests/ui/threads-sendsync/task-comm-0.rs @@ -2,12 +2,14 @@ #![allow(unused_must_use)] //@ needs-threads -use std::thread; use std::sync::mpsc::{channel, Sender}; +use std::thread; -pub fn main() { test05(); } +pub fn main() { + test05(); +} -fn test05_start(tx : &Sender) { +fn test05_start(tx: &Sender) { tx.send(10).unwrap(); println!("sent 10"); tx.send(20).unwrap(); @@ -18,7 +20,7 @@ fn test05_start(tx : &Sender) { fn test05() { let (tx, rx) = channel(); - let t = thread::spawn(move|| { test05_start(&tx) }); + let t = thread::spawn(move || test05_start(&tx)); let mut value: isize = rx.recv().unwrap(); println!("{}", value); value = rx.recv().unwrap(); diff --git a/tests/ui/threads-sendsync/task-comm-1.rs b/tests/ui/threads-sendsync/task-comm-1.rs index 41592bd916b..75d9e887cd1 100644 --- a/tests/ui/threads-sendsync/task-comm-1.rs +++ b/tests/ui/threads-sendsync/task-comm-1.rs @@ -4,11 +4,15 @@ use std::thread; -pub fn main() { test00(); } +pub fn main() { + test00(); +} -fn start() { println!("Started / Finished task."); } +fn start() { + println!("Started / Finished task."); +} fn test00() { - thread::spawn(move|| start() ).join(); + thread::spawn(move || start()).join(); println!("Completing."); } diff --git a/tests/ui/threads-sendsync/task-comm-10.rs b/tests/ui/threads-sendsync/task-comm-10.rs index 844652c0dde..44c31aeed77 100644 --- a/tests/ui/threads-sendsync/task-comm-10.rs +++ b/tests/ui/threads-sendsync/task-comm-10.rs @@ -3,8 +3,8 @@ #![allow(unused_mut)] //@ needs-threads -use std::thread; use std::sync::mpsc::{channel, Sender}; +use std::thread; fn start(tx: &Sender>) { let (tx2, rx) = channel(); @@ -22,7 +22,7 @@ fn start(tx: &Sender>) { pub fn main() { let (tx, rx) = channel(); - let child = thread::spawn(move|| { start(&tx) }); + let child = thread::spawn(move || start(&tx)); let mut c = rx.recv().unwrap(); c.send("A".to_string()).unwrap(); diff --git a/tests/ui/threads-sendsync/task-comm-11.rs b/tests/ui/threads-sendsync/task-comm-11.rs index 199082fda96..7c349c716fa 100644 --- a/tests/ui/threads-sendsync/task-comm-11.rs +++ b/tests/ui/threads-sendsync/task-comm-11.rs @@ -13,9 +13,7 @@ fn start(tx: &Sender>) { pub fn main() { let (tx, rx) = channel(); - let child = thread::spawn(move|| { - start(&tx) - }); + let child = thread::spawn(move || start(&tx)); let _tx = rx.recv().unwrap(); child.join(); } diff --git a/tests/ui/threads-sendsync/task-comm-12.rs b/tests/ui/threads-sendsync/task-comm-12.rs index 7be7ec4c988..95c5d5c45ef 100644 --- a/tests/ui/threads-sendsync/task-comm-12.rs +++ b/tests/ui/threads-sendsync/task-comm-12.rs @@ -5,15 +5,17 @@ use std::thread; -pub fn main() { test00(); } +pub fn main() { + test00(); +} -fn start(_task_number: isize) { println!("Started / Finished task."); } +fn start(_task_number: isize) { + println!("Started / Finished task."); +} fn test00() { let i: isize = 0; - let mut result = thread::spawn(move|| { - start(i) - }); + let mut result = thread::spawn(move || start(i)); // Sleep long enough for the thread to finish. let mut i = 0_usize; diff --git a/tests/ui/threads-sendsync/task-comm-13.rs b/tests/ui/threads-sendsync/task-comm-13.rs index 414e6e0db76..88ea3cbff08 100644 --- a/tests/ui/threads-sendsync/task-comm-13.rs +++ b/tests/ui/threads-sendsync/task-comm-13.rs @@ -7,12 +7,15 @@ use std::thread; fn start(tx: &Sender, start: isize, number_of_messages: isize) { let mut i: isize = 0; - while i< number_of_messages { tx.send(start + i).unwrap(); i += 1; } + while i < number_of_messages { + tx.send(start + i).unwrap(); + i += 1; + } } pub fn main() { println!("Check that we don't deadlock."); let (tx, rx) = channel(); - let _ = thread::spawn(move|| { start(&tx, 0, 10) }).join(); + let _ = thread::spawn(move || start(&tx, 0, 10)).join(); println!("Joined task"); } diff --git a/tests/ui/threads-sendsync/task-comm-14.rs b/tests/ui/threads-sendsync/task-comm-14.rs index 54deb221294..ff4ffd2968d 100644 --- a/tests/ui/threads-sendsync/task-comm-14.rs +++ b/tests/ui/threads-sendsync/task-comm-14.rs @@ -13,7 +13,10 @@ pub fn main() { while (i > 0) { println!("{}", i); let tx = tx.clone(); - thread::spawn({let i = i; move|| { child(i, &tx) }}); + thread::spawn({ + let i = i; + move || child(i, &tx) + }); i = i - 1; } diff --git a/tests/ui/threads-sendsync/task-comm-15.rs b/tests/ui/threads-sendsync/task-comm-15.rs index f487bf3cc84..1308446893b 100644 --- a/tests/ui/threads-sendsync/task-comm-15.rs +++ b/tests/ui/threads-sendsync/task-comm-15.rs @@ -20,9 +20,7 @@ pub fn main() { // the child's point of view the receiver may die. We should // drop messages on the floor in this case, and not crash! let (tx, rx) = channel(); - let t = thread::spawn(move|| { - start(&tx, 10) - }); + let t = thread::spawn(move || start(&tx, 10)); rx.recv(); t.join(); } diff --git a/tests/ui/threads-sendsync/task-comm-16.rs b/tests/ui/threads-sendsync/task-comm-16.rs index 3b0fec11acd..e76f7bedc93 100644 --- a/tests/ui/threads-sendsync/task-comm-16.rs +++ b/tests/ui/threads-sendsync/task-comm-16.rs @@ -3,15 +3,19 @@ #![allow(unused_parens)] #![allow(non_camel_case_types)] -use std::sync::mpsc::channel; use std::cmp; +use std::sync::mpsc::channel; // Tests of ports and channels on various types fn test_rec() { - struct R {val0: isize, val1: u8, val2: char} + struct R { + val0: isize, + val1: u8, + val2: char, + } let (tx, rx) = channel(); - let r0: R = R {val0: 0, val1: 1, val2: '2'}; + let r0: R = R { val0: 0, val1: 1, val2: '2' }; tx.send(r0).unwrap(); let mut r1: R; r1 = rx.recv().unwrap(); @@ -45,34 +49,29 @@ fn test_str() { enum t { tag1, tag2(isize), - tag3(isize, u8, char) + tag3(isize, u8, char), } impl cmp::PartialEq for t { fn eq(&self, other: &t) -> bool { match *self { - t::tag1 => { - match (*other) { - t::tag1 => true, - _ => false - } - } - t::tag2(e0a) => { - match (*other) { - t::tag2(e0b) => e0a == e0b, - _ => false - } - } - t::tag3(e0a, e1a, e2a) => { - match (*other) { - t::tag3(e0b, e1b, e2b) => - e0a == e0b && e1a == e1b && e2a == e2b, - _ => false - } - } + t::tag1 => match (*other) { + t::tag1 => true, + _ => false, + }, + t::tag2(e0a) => match (*other) { + t::tag2(e0b) => e0a == e0b, + _ => false, + }, + t::tag3(e0a, e1a, e2a) => match (*other) { + t::tag3(e0b, e1b, e2b) => e0a == e0b && e1a == e1b && e2a == e2b, + _ => false, + }, } } - fn ne(&self, other: &t) -> bool { !(*self).eq(other) } + fn ne(&self, other: &t) -> bool { + !(*self).eq(other) + } } fn test_tag() { diff --git a/tests/ui/threads-sendsync/task-comm-17.rs b/tests/ui/threads-sendsync/task-comm-17.rs index 687322d4dc9..a545beee599 100644 --- a/tests/ui/threads-sendsync/task-comm-17.rs +++ b/tests/ui/threads-sendsync/task-comm-17.rs @@ -9,9 +9,8 @@ use std::thread; -fn f() { -} +fn f() {} pub fn main() { - thread::spawn(move|| f() ).join(); + thread::spawn(move || f()).join(); } diff --git a/tests/ui/threads-sendsync/task-comm-3.rs b/tests/ui/threads-sendsync/task-comm-3.rs index 26f3eaf9dc6..565d97596c7 100644 --- a/tests/ui/threads-sendsync/task-comm-3.rs +++ b/tests/ui/threads-sendsync/task-comm-3.rs @@ -2,10 +2,13 @@ #![allow(unused_must_use)] //@ needs-threads -use std::thread; use std::sync::mpsc::{channel, Sender}; +use std::thread; -pub fn main() { println!("===== WITHOUT THREADS ====="); test00(); } +pub fn main() { + println!("===== WITHOUT THREADS ====="); + test00(); +} fn test00_start(ch: &Sender, message: isize, count: isize) { println!("Starting test00_start"); @@ -34,9 +37,7 @@ fn test00() { let tx = tx.clone(); results.push(thread::spawn({ let i = i; - move|| { - test00_start(&tx, i, number_of_messages) - } + move || test00_start(&tx, i, number_of_messages) })); i = i + 1; } @@ -53,7 +54,9 @@ fn test00() { } // Join spawned threads... - for r in results { r.join(); } + for r in results { + r.join(); + } println!("Completed: Final number is: "); println!("{}", sum); diff --git a/tests/ui/threads-sendsync/task-comm-4.rs b/tests/ui/threads-sendsync/task-comm-4.rs index 1210cee5582..6223f6a1ded 100644 --- a/tests/ui/threads-sendsync/task-comm-4.rs +++ b/tests/ui/threads-sendsync/task-comm-4.rs @@ -3,7 +3,9 @@ use std::sync::mpsc::channel; -pub fn main() { test00(); } +pub fn main() { + test00(); +} fn test00() { let mut r: isize = 0; diff --git a/tests/ui/threads-sendsync/task-comm-5.rs b/tests/ui/threads-sendsync/task-comm-5.rs index e07aa18c24d..e008b28f56c 100644 --- a/tests/ui/threads-sendsync/task-comm-5.rs +++ b/tests/ui/threads-sendsync/task-comm-5.rs @@ -2,7 +2,9 @@ use std::sync::mpsc::channel; -pub fn main() { test00(); } +pub fn main() { + test00(); +} fn test00() { let _r: isize = 0; @@ -10,8 +12,14 @@ fn test00() { let (tx, rx) = channel(); let number_of_messages: isize = 1000; let mut i: isize = 0; - while i < number_of_messages { tx.send(i + 0).unwrap(); i += 1; } + while i < number_of_messages { + tx.send(i + 0).unwrap(); + i += 1; + } i = 0; - while i < number_of_messages { sum += rx.recv().unwrap(); i += 1; } + while i < number_of_messages { + sum += rx.recv().unwrap(); + i += 1; + } assert_eq!(sum, number_of_messages * (number_of_messages - 1) / 2); } diff --git a/tests/ui/threads-sendsync/task-comm-6.rs b/tests/ui/threads-sendsync/task-comm-6.rs index 6a7dea63993..60697c908af 100644 --- a/tests/ui/threads-sendsync/task-comm-6.rs +++ b/tests/ui/threads-sendsync/task-comm-6.rs @@ -4,7 +4,9 @@ use std::sync::mpsc::channel; -pub fn main() { test00(); } +pub fn main() { + test00(); +} fn test00() { let mut r: isize = 0; @@ -38,5 +40,4 @@ fn test00() { assert_eq!(sum, 1998000); // assert (sum == 4 * ((number_of_messages * // (number_of_messages - 1)) / 2)); - } diff --git a/tests/ui/threads-sendsync/task-comm-7.rs b/tests/ui/threads-sendsync/task-comm-7.rs index d9b322daa66..bb59e4b4a72 100644 --- a/tests/ui/threads-sendsync/task-comm-7.rs +++ b/tests/ui/threads-sendsync/task-comm-7.rs @@ -6,12 +6,16 @@ use std::sync::mpsc::{channel, Sender}; use std::thread; -pub fn main() { test00(); } +pub fn main() { + test00(); +} -fn test00_start(c: &Sender, start: isize, - number_of_messages: isize) { +fn test00_start(c: &Sender, start: isize, number_of_messages: isize) { let mut i: isize = 0; - while i < number_of_messages { c.send(start + i).unwrap(); i += 1; } + while i < number_of_messages { + c.send(start + i).unwrap(); + i += 1; + } } fn test00() { @@ -21,19 +25,19 @@ fn test00() { let number_of_messages: isize = 10; let tx2 = tx.clone(); - let t1 = thread::spawn(move|| { + let t1 = thread::spawn(move || { test00_start(&tx2, number_of_messages * 0, number_of_messages); }); let tx2 = tx.clone(); - let t2 = thread::spawn(move|| { + let t2 = thread::spawn(move || { test00_start(&tx2, number_of_messages * 1, number_of_messages); }); let tx2 = tx.clone(); - let t3 = thread::spawn(move|| { + let t3 = thread::spawn(move || { test00_start(&tx2, number_of_messages * 2, number_of_messages); }); let tx2 = tx.clone(); - let t4 = thread::spawn(move|| { + let t4 = thread::spawn(move || { test00_start(&tx2, number_of_messages * 3, number_of_messages); }); diff --git a/tests/ui/threads-sendsync/task-comm-9.rs b/tests/ui/threads-sendsync/task-comm-9.rs index 3e617e4a40c..2e1f3cb673a 100644 --- a/tests/ui/threads-sendsync/task-comm-9.rs +++ b/tests/ui/threads-sendsync/task-comm-9.rs @@ -2,14 +2,19 @@ #![allow(unused_must_use)] //@ needs-threads -use std::thread; use std::sync::mpsc::{channel, Sender}; +use std::thread; -pub fn main() { test00(); } +pub fn main() { + test00(); +} fn test00_start(c: &Sender, number_of_messages: isize) { let mut i: isize = 0; - while i < number_of_messages { c.send(i + 0).unwrap(); i += 1; } + while i < number_of_messages { + c.send(i + 0).unwrap(); + i += 1; + } } fn test00() { @@ -18,7 +23,7 @@ fn test00() { let (tx, rx) = channel(); let number_of_messages: isize = 10; - let result = thread::spawn(move|| { + let result = thread::spawn(move || { test00_start(&tx, number_of_messages); }); diff --git a/tests/ui/threads-sendsync/task-life-0.rs b/tests/ui/threads-sendsync/task-life-0.rs index d3eca5d371f..f08a281e76c 100644 --- a/tests/ui/threads-sendsync/task-life-0.rs +++ b/tests/ui/threads-sendsync/task-life-0.rs @@ -6,9 +6,7 @@ use std::thread; pub fn main() { - thread::spawn(move|| child("Hello".to_string()) ).join(); + thread::spawn(move || child("Hello".to_string())).join(); } -fn child(_s: String) { - -} +fn child(_s: String) {} diff --git a/tests/ui/threads-sendsync/task-spawn-move-and-copy.rs b/tests/ui/threads-sendsync/task-spawn-move-and-copy.rs index ea1c6a9b108..07d1a3d5c36 100644 --- a/tests/ui/threads-sendsync/task-spawn-move-and-copy.rs +++ b/tests/ui/threads-sendsync/task-spawn-move-and-copy.rs @@ -2,8 +2,8 @@ #![allow(unused_must_use)] //@ needs-threads -use std::thread; use std::sync::mpsc::channel; +use std::thread; pub fn main() { let (tx, rx) = channel::(); diff --git a/tests/ui/threads-sendsync/task-stderr.rs b/tests/ui/threads-sendsync/task-stderr.rs index cad10c7a792..3934084e02a 100644 --- a/tests/ui/threads-sendsync/task-stderr.rs +++ b/tests/ui/threads-sendsync/task-stderr.rs @@ -4,20 +4,21 @@ #![feature(internal_output_capture)] -use std::io; -use std::str; use std::sync::{Arc, Mutex}; -use std::thread; +use std::{io, str, thread}; fn main() { let data = Arc::new(Mutex::new(Vec::new())); - let res = thread::Builder::new().spawn({ - let data = data.clone(); - move || { - io::set_output_capture(Some(data)); - panic!("Hello, world!") - } - }).unwrap().join(); + let res = thread::Builder::new() + .spawn({ + let data = data.clone(); + move || { + io::set_output_capture(Some(data)); + panic!("Hello, world!") + } + }) + .unwrap() + .join(); assert!(res.is_err()); let output = data.lock().unwrap(); diff --git a/tests/ui/threads-sendsync/tcp-stress.rs b/tests/ui/threads-sendsync/tcp-stress.rs index 429a4657314..b2f76a55fb9 100644 --- a/tests/ui/threads-sendsync/tcp-stress.rs +++ b/tests/ui/threads-sendsync/tcp-stress.rs @@ -8,14 +8,14 @@ use std::io::prelude::*; use std::net::{TcpListener, TcpStream}; use std::process; use std::sync::mpsc::channel; -use std::time::Duration; use std::thread::{self, Builder}; +use std::time::Duration; const TARGET_CNT: usize = 200; fn main() { // This test has a chance to time out, try to not let it time out - thread::spawn(move|| -> () { + thread::spawn(move || -> () { thread::sleep(Duration::from_secs(30)); process::exit(1); }); @@ -38,12 +38,12 @@ fn main() { let mut spawned_cnt = 0; for _ in 0..TARGET_CNT { let tx = tx.clone(); - let res = Builder::new().stack_size(64 * 1024).spawn(move|| { + let res = Builder::new().stack_size(64 * 1024).spawn(move || { match TcpStream::connect(addr) { Ok(mut stream) => { let _ = stream.write(&[1]); let _ = stream.read(&mut [0]); - }, + } Err(..) => {} } tx.send(()).unwrap(); diff --git a/tests/ui/threads-sendsync/threads.rs b/tests/ui/threads-sendsync/threads.rs index f3ed7890364..ad4e4774ea0 100644 --- a/tests/ui/threads-sendsync/threads.rs +++ b/tests/ui/threads-sendsync/threads.rs @@ -7,10 +7,16 @@ use std::thread; pub fn main() { let mut i = 10; while i > 0 { - thread::spawn({let i = i; move|| child(i)}).join(); + thread::spawn({ + let i = i; + move || child(i) + }) + .join(); i = i - 1; } println!("main thread exiting"); } -fn child(x: isize) { println!("{}", x); } +fn child(x: isize) { + println!("{}", x); +} diff --git a/tests/ui/threads-sendsync/tls-dtors-are-run-in-a-static-binary.rs b/tests/ui/threads-sendsync/tls-dtors-are-run-in-a-static-binary.rs index 84176659412..983028681cd 100644 --- a/tests/ui/threads-sendsync/tls-dtors-are-run-in-a-static-binary.rs +++ b/tests/ui/threads-sendsync/tls-dtors-are-run-in-a-static-binary.rs @@ -8,7 +8,9 @@ struct Foo; impl Drop for Foo { fn drop(&mut self) { - unsafe { HIT = true; } + unsafe { + HIT = true; + } } } @@ -17,6 +19,8 @@ thread_local!(static FOO: Foo = Foo); fn main() { std::thread::spawn(|| { FOO.with(|_| {}); - }).join().unwrap(); + }) + .join() + .unwrap(); assert!(unsafe { HIT }); } diff --git a/tests/ui/threads-sendsync/tls-init-on-init.rs b/tests/ui/threads-sendsync/tls-init-on-init.rs index fd764669e7f..1cae19aae86 100644 --- a/tests/ui/threads-sendsync/tls-init-on-init.rs +++ b/tests/ui/threads-sendsync/tls-init-on-init.rs @@ -1,14 +1,14 @@ //@ run-pass #![allow(stable_features)] - //@ needs-threads - #![feature(thread_local_try_with)] -use std::thread; use std::sync::atomic::{AtomicUsize, Ordering}; +use std::thread; -struct Foo { cnt: usize } +struct Foo { + cnt: usize, +} thread_local!(static FOO: Foo = Foo::init()); @@ -40,5 +40,7 @@ impl Drop for Foo { fn main() { thread::spawn(|| { FOO.with(|_| {}); - }).join().unwrap(); + }) + .join() + .unwrap(); } diff --git a/tests/ui/threads-sendsync/tls-try-with.rs b/tests/ui/threads-sendsync/tls-try-with.rs index 72cee219a0a..04071e77daa 100644 --- a/tests/ui/threads-sendsync/tls-try-with.rs +++ b/tests/ui/threads-sendsync/tls-try-with.rs @@ -1,8 +1,6 @@ //@ run-pass #![allow(stable_features)] - //@ needs-threads - #![feature(thread_local_try_with)] use std::thread; @@ -16,15 +14,17 @@ thread_local!(static FOO: Foo = Foo {}); impl Drop for Foo { fn drop(&mut self) { assert!(FOO.try_with(|_| panic!("`try_with` closure run")).is_err()); - unsafe { DROP_RUN = true; } + unsafe { + DROP_RUN = true; + } } } fn main() { thread::spawn(|| { - assert_eq!(FOO.try_with(|_| { - 132 - }).expect("`try_with` failed"), 132); - }).join().unwrap(); + assert_eq!(FOO.try_with(|_| { 132 }).expect("`try_with` failed"), 132); + }) + .join() + .unwrap(); assert!(unsafe { DROP_RUN }); } diff --git a/tests/ui/threads-sendsync/trivial-message.rs b/tests/ui/threads-sendsync/trivial-message.rs index 81657373643..d76ba0009dc 100644 --- a/tests/ui/threads-sendsync/trivial-message.rs +++ b/tests/ui/threads-sendsync/trivial-message.rs @@ -2,9 +2,9 @@ #![allow(unused_must_use)] /* - This is about the simplest program that can successfully send a - message. - */ + This is about the simplest program that can successfully send a + message. +*/ use std::sync::mpsc::channel; diff --git a/tests/ui/threads-sendsync/unwind-resource.rs b/tests/ui/threads-sendsync/unwind-resource.rs index 3b1ab57b46e..ec27a1846fe 100644 --- a/tests/ui/threads-sendsync/unwind-resource.rs +++ b/tests/ui/threads-sendsync/unwind-resource.rs @@ -21,9 +21,7 @@ impl Drop for complainer { fn complainer(tx: Sender) -> complainer { println!("Hello!"); - complainer { - tx: tx - } + complainer { tx: tx } } fn f(tx: Sender) { @@ -33,7 +31,7 @@ fn f(tx: Sender) { pub fn main() { let (tx, rx) = channel(); - let t = thread::spawn(move|| f(tx.clone())); + let t = thread::spawn(move || f(tx.clone())); println!("hiiiiiiiii"); assert!(rx.recv().unwrap()); drop(t.join()); diff --git a/tests/ui/threads-sendsync/yield.rs b/tests/ui/threads-sendsync/yield.rs index 99d14bd92ea..c2b10b901cf 100644 --- a/tests/ui/threads-sendsync/yield.rs +++ b/tests/ui/threads-sendsync/yield.rs @@ -17,5 +17,9 @@ pub fn main() { } fn child() { - println!("4"); thread::yield_now(); println!("5"); thread::yield_now(); println!("6"); + println!("4"); + thread::yield_now(); + println!("5"); + thread::yield_now(); + println!("6"); } diff --git a/tests/ui/threads-sendsync/yield1.rs b/tests/ui/threads-sendsync/yield1.rs index c965d2fc303..441e93ecf90 100644 --- a/tests/ui/threads-sendsync/yield1.rs +++ b/tests/ui/threads-sendsync/yield1.rs @@ -13,4 +13,6 @@ pub fn main() { result.join(); } -fn child() { println!("2"); } +fn child() { + println!("2"); +} diff --git a/tests/ui/threads-sendsync/yield2.rs b/tests/ui/threads-sendsync/yield2.rs index 9502f0d33da..2c24df44af2 100644 --- a/tests/ui/threads-sendsync/yield2.rs +++ b/tests/ui/threads-sendsync/yield2.rs @@ -4,5 +4,9 @@ use std::thread; pub fn main() { let mut i: isize = 0; - while i < 100 { i = i + 1; println!("{}", i); thread::yield_now(); } + while i < 100 { + i = i + 1; + println!("{}", i); + thread::yield_now(); + } } diff --git a/tests/ui/traits/next-solver/alias-bound-unsound.rs b/tests/ui/traits/next-solver/alias-bound-unsound.rs index a5bd3e7afa8..272e5db3b7a 100644 --- a/tests/ui/traits/next-solver/alias-bound-unsound.rs +++ b/tests/ui/traits/next-solver/alias-bound-unsound.rs @@ -27,5 +27,6 @@ fn main() { //~| ERROR overflow evaluating the requirement `&<() as Foo>::Item well-formed` //~| ERROR overflow evaluating the requirement `<() as Foo>::Item == _` //~| ERROR overflow evaluating the requirement `<() as Foo>::Item == _` + //~| ERROR overflow evaluating the requirement `<() as Foo>::Item == _` println!("{x}"); } diff --git a/tests/ui/traits/next-solver/alias-bound-unsound.stderr b/tests/ui/traits/next-solver/alias-bound-unsound.stderr index a5c2f215134..e5cf5b6bc3d 100644 --- a/tests/ui/traits/next-solver/alias-bound-unsound.stderr +++ b/tests/ui/traits/next-solver/alias-bound-unsound.stderr @@ -44,6 +44,12 @@ LL | drop(<() as Foo>::copy_me(&x)); | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 6 previous errors +error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _` + --> $DIR/alias-bound-unsound.rs:24:31 + | +LL | drop(<() as Foo>::copy_me(&x)); + | ^^ + +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/object/pretty.rs b/tests/ui/traits/object/pretty.rs index 8958871ed5d..6660ff040f7 100644 --- a/tests/ui/traits/object/pretty.rs +++ b/tests/ui/traits/object/pretty.rs @@ -18,6 +18,10 @@ trait FixedHrtb: for<'a> SuperGeneric<'a, Assoc2 = &'a u8> {} trait AnyDifferentBinders: for<'a> SuperGeneric<'a, Assoc2 = &'a u8> + Super {} trait FixedDifferentBinders: for<'a> SuperGeneric<'a, Assoc2 = &'a u8> + Super {} +trait HasGat { + type Assoc where Self: Sized; +} + fn dyn_super(x: &dyn Super) { x } //~ERROR mismatched types fn dyn_any(x: &dyn Any) { x } //~ERROR mismatched types fn dyn_fixed(x: &dyn Fixed) { x } //~ERROR mismatched types @@ -34,4 +38,7 @@ fn dyn_fixed_hrtb(x: &dyn FixedHrtb) { x } //~ERROR mismatched types fn dyn_any_different_binders(x: &dyn AnyDifferentBinders) { x } //~ERROR mismatched types fn dyn_fixed_different_binders(x: &dyn FixedDifferentBinders) { x } //~ERROR mismatched types +fn dyn_has_gat(x: &dyn HasGat = ()>) { x } //~ERROR mismatched types +//~^ WARN unnecessary associated type bound + fn main() {} diff --git a/tests/ui/traits/object/pretty.stderr b/tests/ui/traits/object/pretty.stderr index bc645e5f967..6964d97c08e 100644 --- a/tests/ui/traits/object/pretty.stderr +++ b/tests/ui/traits/object/pretty.stderr @@ -1,5 +1,14 @@ +warning: unnecessary associated type bound for not object safe associated type + --> $DIR/pretty.rs:41:35 + | +LL | fn dyn_has_gat(x: &dyn HasGat = ()>) { x } + | ^^^^^^^^^^^^^^^^ help: remove this bound + | + = note: this associated type has a `where Self: Sized` bound, and while the associated type can be specified, it cannot be used because trait objects are never `Sized` + = note: `#[warn(unused_associated_type_bounds)]` on by default + error[E0308]: mismatched types - --> $DIR/pretty.rs:21:43 + --> $DIR/pretty.rs:25:43 | LL | fn dyn_super(x: &dyn Super) { x } | - ^ expected `()`, found `&dyn Super` @@ -10,7 +19,7 @@ LL | fn dyn_super(x: &dyn Super) { x } found reference `&dyn Super` error[E0308]: mismatched types - --> $DIR/pretty.rs:22:39 + --> $DIR/pretty.rs:26:39 | LL | fn dyn_any(x: &dyn Any) { x } | - ^ expected `()`, found `&dyn Any` @@ -21,7 +30,7 @@ LL | fn dyn_any(x: &dyn Any) { x } found reference `&dyn Any` error[E0308]: mismatched types - --> $DIR/pretty.rs:23:31 + --> $DIR/pretty.rs:27:31 | LL | fn dyn_fixed(x: &dyn Fixed) { x } | - ^ expected `()`, found `&dyn Fixed` @@ -32,7 +41,7 @@ LL | fn dyn_fixed(x: &dyn Fixed) { x } found reference `&dyn Fixed` error[E0308]: mismatched types - --> $DIR/pretty.rs:24:50 + --> $DIR/pretty.rs:28:50 | LL | fn dyn_fixed_multi(x: &dyn Fixed) { x } | - ^ expected `()`, found `&dyn Fixed` @@ -43,7 +52,7 @@ LL | fn dyn_fixed_multi(x: &dyn Fixed) { x } found reference `&dyn Fixed` error[E0308]: mismatched types - --> $DIR/pretty.rs:25:38 + --> $DIR/pretty.rs:29:38 | LL | fn dyn_fixed_sub(x: &dyn FixedSub) { x } | - ^ expected `()`, found `&dyn FixedSub` @@ -54,7 +63,7 @@ LL | fn dyn_fixed_sub(x: &dyn FixedSub) { x } found reference `&dyn FixedSub` error[E0308]: mismatched types - --> $DIR/pretty.rs:26:44 + --> $DIR/pretty.rs:30:44 | LL | fn dyn_fixed_static(x: &dyn FixedStatic) { x } | - ^ expected `()`, found `&dyn FixedStatic` @@ -65,7 +74,7 @@ LL | fn dyn_fixed_static(x: &dyn FixedStatic) { x } found reference `&dyn FixedStatic` error[E0308]: mismatched types - --> $DIR/pretty.rs:28:75 + --> $DIR/pretty.rs:32:75 | LL | fn dyn_super_generic(x: &dyn for<'a> SuperGeneric<'a, Assoc2 = &'a u8>) { x } | - ^ expected `()`, found `&dyn SuperGeneric<'a, Assoc2 = &u8>` @@ -76,7 +85,7 @@ LL | fn dyn_super_generic(x: &dyn for<'a> SuperGeneric<'a, Assoc2 = &'a u8>) { x found reference `&dyn for<'a> SuperGeneric<'a, Assoc2 = &'a u8>` error[E0308]: mismatched types - --> $DIR/pretty.rs:29:71 + --> $DIR/pretty.rs:33:71 | LL | fn dyn_any_generic(x: &dyn for<'a> AnyGeneric<'a, Assoc2 = &'a u8>) { x } | - ^ expected `()`, found `&dyn AnyGeneric<'a, Assoc2 = &u8>` @@ -87,7 +96,7 @@ LL | fn dyn_any_generic(x: &dyn for<'a> AnyGeneric<'a, Assoc2 = &'a u8>) { x } found reference `&dyn for<'a> AnyGeneric<'a, Assoc2 = &'a u8>` error[E0308]: mismatched types - --> $DIR/pretty.rs:30:60 + --> $DIR/pretty.rs:34:60 | LL | fn dyn_fixed_generic1(x: &dyn for<'a> FixedGeneric1<'a>) { x } | - ^ expected `()`, found `&dyn FixedGeneric1<'a>` @@ -98,7 +107,7 @@ LL | fn dyn_fixed_generic1(x: &dyn for<'a> FixedGeneric1<'a>) { x } found reference `&dyn for<'a> FixedGeneric1<'a>` error[E0308]: mismatched types - --> $DIR/pretty.rs:31:60 + --> $DIR/pretty.rs:35:60 | LL | fn dyn_fixed_generic2(x: &dyn for<'a> FixedGeneric2<'a>) { x } | - ^ expected `()`, found `&dyn FixedGeneric2<'a>` @@ -109,7 +118,7 @@ LL | fn dyn_fixed_generic2(x: &dyn for<'a> FixedGeneric2<'a>) { x } found reference `&dyn for<'a> FixedGeneric2<'a>` error[E0308]: mismatched types - --> $DIR/pretty.rs:32:79 + --> $DIR/pretty.rs:36:79 | LL | fn dyn_fixed_generic_multi(x: &dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>) { x } | - ^ expected `()`, found `&dyn FixedGeneric1<'a, Assoc2 = ...>` @@ -120,7 +129,7 @@ LL | fn dyn_fixed_generic_multi(x: &dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>) found reference `&dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>` error[E0308]: mismatched types - --> $DIR/pretty.rs:33:40 + --> $DIR/pretty.rs:37:40 | LL | fn dyn_fixed_hrtb(x: &dyn FixedHrtb) { x } | - ^ expected `()`, found `&dyn FixedHrtb` @@ -131,7 +140,7 @@ LL | fn dyn_fixed_hrtb(x: &dyn FixedHrtb) { x } found reference `&dyn FixedHrtb` error[E0308]: mismatched types - --> $DIR/pretty.rs:34:73 + --> $DIR/pretty.rs:38:73 | LL | fn dyn_any_different_binders(x: &dyn AnyDifferentBinders) { x } | - ^ expected `()`, found `&dyn AnyDifferentBinders` @@ -142,7 +151,7 @@ LL | fn dyn_any_different_binders(x: &dyn AnyDifferentBinders) { x } found reference `&dyn AnyDifferentBinders` error[E0308]: mismatched types - --> $DIR/pretty.rs:35:65 + --> $DIR/pretty.rs:39:65 | LL | fn dyn_fixed_different_binders(x: &dyn FixedDifferentBinders) { x } | - ^ expected `()`, found `&dyn FixedDifferentBinders` @@ -152,6 +161,17 @@ LL | fn dyn_fixed_different_binders(x: &dyn FixedDifferentBinders) { x } = note: expected unit type `()` found reference `&dyn FixedDifferentBinders` -error: aborting due to 14 previous errors +error[E0308]: mismatched types + --> $DIR/pretty.rs:41:56 + | +LL | fn dyn_has_gat(x: &dyn HasGat = ()>) { x } + | - ^ expected `()`, found `&dyn HasGat = ()>` + | | + | help: try adding a return type: `-> &dyn HasGat = ()>` + | + = note: expected unit type `()` + found reference `&dyn HasGat = ()>` + +error: aborting due to 15 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/transmutability/abstraction/abstracted_assume.rs b/tests/ui/transmutability/abstraction/abstracted_assume.rs index 897e1b4b50a..7fd91e31a04 100644 --- a/tests/ui/transmutability/abstraction/abstracted_assume.rs +++ b/tests/ui/transmutability/abstraction/abstracted_assume.rs @@ -8,7 +8,7 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable< Src, @@ -16,7 +16,7 @@ mod assert { const ASSUME: std::mem::Assume, >() where - Dst: BikeshedIntrinsicFrom< + Dst: TransmuteFrom< Src, ASSUME, >, diff --git a/tests/ui/transmutability/abstraction/const_generic_fn.rs b/tests/ui/transmutability/abstraction/const_generic_fn.rs index 0a5f0de0214..1ea978ce1ba 100644 --- a/tests/ui/transmutability/abstraction/const_generic_fn.rs +++ b/tests/ui/transmutability/abstraction/const_generic_fn.rs @@ -6,12 +6,12 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn array_like() where - T: BikeshedIntrinsicFrom<[E; N], { Assume::SAFETY }>, - [E; N]: BikeshedIntrinsicFrom + T: TransmuteFrom<[E; N], { Assume::SAFETY }>, + [E; N]: TransmuteFrom {} } diff --git a/tests/ui/transmutability/alignment/align-fail.rs b/tests/ui/transmutability/alignment/align-fail.rs index d88f1285c11..4c1a69b0128 100644 --- a/tests/ui/transmutability/alignment/align-fail.rs +++ b/tests/ui/transmutability/alignment/align-fail.rs @@ -2,11 +2,11 @@ #![feature(transmutability)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable() where - Dst: BikeshedIntrinsicFrom() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() where - Dst: BikeshedIntrinsicFrom() where - Dst: BikeshedIntrinsicFrom, + Dst: TransmuteFrom, { } } diff --git a/tests/ui/transmutability/arrays/huge-len.stderr b/tests/ui/transmutability/arrays/huge-len.stderr index 3fc652f47c1..1fa16c649d4 100644 --- a/tests/ui/transmutability/arrays/huge-len.stderr +++ b/tests/ui/transmutability/arrays/huge-len.stderr @@ -2,7 +2,7 @@ error[E0277]: `()` cannot be safely transmuted into `ExplicitlyPadded` --> $DIR/huge-len.rs:21:41 | LL | assert::is_maybe_transmutable::<(), ExplicitlyPadded>(); - | ^^^^^^^^^^^^^^^^ analyzing the transmutability of `ExplicitlyPadded` is not yet supported + | ^^^^^^^^^^^^^^^^ values of the type `ExplicitlyPadded` are too big for the current architecture | note: required by a bound in `is_maybe_transmutable` --> $DIR/huge-len.rs:8:14 @@ -10,14 +10,14 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` +LL | Dst: TransmuteFrom, + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` error[E0277]: `ExplicitlyPadded` cannot be safely transmuted into `()` --> $DIR/huge-len.rs:24:55 | LL | assert::is_maybe_transmutable::(); - | ^^ analyzing the transmutability of `ExplicitlyPadded` is not yet supported + | ^^ values of the type `ExplicitlyPadded` are too big for the current architecture | note: required by a bound in `is_maybe_transmutable` --> $DIR/huge-len.rs:8:14 @@ -25,8 +25,8 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` +LL | Dst: TransmuteFrom, + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` error: aborting due to 2 previous errors diff --git a/tests/ui/transmutability/arrays/issue-103783-array-length.rs b/tests/ui/transmutability/arrays/issue-103783-array-length.rs index 7fcbcc01075..3537a39259c 100644 --- a/tests/ui/transmutability/arrays/issue-103783-array-length.rs +++ b/tests/ui/transmutability/arrays/issue-103783-array-length.rs @@ -3,11 +3,11 @@ #![allow(dead_code)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable() where - Dst: BikeshedIntrinsicFrom< + Dst: TransmuteFrom< Src, { Assume { alignment: true, lifetimes: true, safety: true, validity: true } }, >, diff --git a/tests/ui/transmutability/arrays/should_have_correct_length.rs b/tests/ui/transmutability/arrays/should_have_correct_length.rs index 747897d49d7..00c0c1122ef 100644 --- a/tests/ui/transmutability/arrays/should_have_correct_length.rs +++ b/tests/ui/transmutability/arrays/should_have_correct_length.rs @@ -6,11 +6,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable() where - Dst: BikeshedIntrinsicFrom + Dst: TransmuteFrom {} } diff --git a/tests/ui/transmutability/arrays/should_inherit_alignment.rs b/tests/ui/transmutability/arrays/should_inherit_alignment.rs index d95c51e3361..70d2f07c449 100644 --- a/tests/ui/transmutability/arrays/should_inherit_alignment.rs +++ b/tests/ui/transmutability/arrays/should_inherit_alignment.rs @@ -6,11 +6,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable() where - Dst: BikeshedIntrinsicFrom() where - Dst: BikeshedIntrinsicFrom() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() where - Dst: BikeshedIntrinsicFrom() where - Dst: BikeshedIntrinsicFrom() where - Dst: BikeshedIntrinsicFrom() where - Dst: BikeshedIntrinsicFrom() where - Dst: BikeshedIntrinsicFrom() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() where - Dst: BikeshedIntrinsicFrom() where - Dst: BikeshedIntrinsicFrom() where - Dst: BikeshedIntrinsicFrom() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() where - Dst: BikeshedIntrinsicFrom() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() where - (): std::mem::BikeshedIntrinsicFrom + (): std::mem::TransmuteFrom {} enum Uninhabited {} diff --git a/tests/ui/transmutability/issue-101739-1.rs b/tests/ui/transmutability/issue-101739-1.rs index 20bd7917e53..fcc1db073ee 100644 --- a/tests/ui/transmutability/issue-101739-1.rs +++ b/tests/ui/transmutability/issue-101739-1.rs @@ -1,12 +1,13 @@ #![feature(transmutability)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable() where - Dst: BikeshedIntrinsicFrom, //~ ERROR cannot find type `Dst` in this scope - //~^ the constant `ASSUME_ALIGNMENT` is not of type `Assume` + Dst: TransmuteFrom, //~ ERROR cannot find type `Dst` in this scope + //~| the constant `ASSUME_ALIGNMENT` is not of type `Assume` + //~| ERROR: mismatched types { } } diff --git a/tests/ui/transmutability/issue-101739-1.stderr b/tests/ui/transmutability/issue-101739-1.stderr index ba18a980f4d..3687631dc51 100644 --- a/tests/ui/transmutability/issue-101739-1.stderr +++ b/tests/ui/transmutability/issue-101739-1.stderr @@ -1,18 +1,25 @@ error[E0412]: cannot find type `Dst` in this scope --> $DIR/issue-101739-1.rs:8:9 | -LL | Dst: BikeshedIntrinsicFrom, +LL | Dst: TransmuteFrom, | ^^^ not found in this scope error: the constant `ASSUME_ALIGNMENT` is not of type `Assume` --> $DIR/issue-101739-1.rs:8:14 | -LL | Dst: BikeshedIntrinsicFrom, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Assume`, found `bool` +LL | Dst: TransmuteFrom, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Assume`, found `bool` | -note: required by a const generic parameter in `BikeshedIntrinsicFrom` +note: required by a const generic parameter in `TransmuteFrom` --> $SRC_DIR/core/src/mem/transmutability.rs:LL:COL -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/issue-101739-1.rs:8:33 + | +LL | Dst: TransmuteFrom, + | ^^^^^^^^^^^^^^^^ expected `Assume`, found `bool` -For more information about this error, try `rustc --explain E0412`. +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0308, E0412. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/transmutability/issue-101739-2.rs b/tests/ui/transmutability/issue-101739-2.rs index 8b36bf3dcb1..02aa4669e05 100644 --- a/tests/ui/transmutability/issue-101739-2.rs +++ b/tests/ui/transmutability/issue-101739-2.rs @@ -3,7 +3,7 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable< Src, @@ -14,19 +14,23 @@ mod assert { const ASSUME_VISIBILITY: bool, >() where - Dst: BikeshedIntrinsicFrom< //~ ERROR trait takes at most 2 generic arguments but 5 generic arguments were supplied - Src, - ASSUME_ALIGNMENT, - ASSUME_LIFETIMES, - ASSUME_VALIDITY, - ASSUME_VISIBILITY, - >, - {} + Dst: TransmuteFrom< + //~^ ERROR trait takes at most 2 generic arguments but 5 generic arguments were supplied + Src, + ASSUME_ALIGNMENT, //~ ERROR: mismatched types + ASSUME_LIFETIMES, + ASSUME_VALIDITY, + ASSUME_VISIBILITY, + >, + { + } } fn via_const() { - #[repr(C)] struct Src; - #[repr(C)] struct Dst; + #[repr(C)] + struct Src; + #[repr(C)] + struct Dst; const FALSE: bool = false; diff --git a/tests/ui/transmutability/issue-101739-2.stderr b/tests/ui/transmutability/issue-101739-2.stderr index 6b0a36a414b..526fcabe14e 100644 --- a/tests/ui/transmutability/issue-101739-2.stderr +++ b/tests/ui/transmutability/issue-101739-2.stderr @@ -1,16 +1,23 @@ error[E0107]: trait takes at most 2 generic arguments but 5 generic arguments were supplied --> $DIR/issue-101739-2.rs:17:14 | -LL | Dst: BikeshedIntrinsicFrom< - | ^^^^^^^^^^^^^^^^^^^^^ expected at most 2 generic arguments -LL | Src, -LL | ASSUME_ALIGNMENT, - | _____________________________- -LL | | ASSUME_LIFETIMES, -LL | | ASSUME_VALIDITY, -LL | | ASSUME_VISIBILITY, - | |_____________________________- help: remove the unnecessary generic arguments +LL | Dst: TransmuteFrom< + | ^^^^^^^^^^^^^ expected at most 2 generic arguments +... +LL | ASSUME_ALIGNMENT, + | _________________________________- +LL | | ASSUME_LIFETIMES, +LL | | ASSUME_VALIDITY, +LL | | ASSUME_VISIBILITY, + | |_________________________________- help: remove the unnecessary generic arguments -error: aborting due to 1 previous error +error[E0308]: mismatched types + --> $DIR/issue-101739-2.rs:20:17 + | +LL | ASSUME_ALIGNMENT, + | ^^^^^^^^^^^^^^^^ expected `Assume`, found `bool` -For more information about this error, try `rustc --explain E0107`. +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0107, E0308. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/transmutability/issue-110467.rs b/tests/ui/transmutability/issue-110467.rs index 1f9e521c24b..4acea5f766d 100644 --- a/tests/ui/transmutability/issue-110467.rs +++ b/tests/ui/transmutability/issue-110467.rs @@ -1,11 +1,11 @@ //@ check-pass #![crate_type = "lib"] #![feature(transmutability)] -use std::mem::BikeshedIntrinsicFrom; +use std::mem::TransmuteFrom; pub fn is_maybe_transmutable() where - Dst: BikeshedIntrinsicFrom, + Dst: TransmuteFrom, { } diff --git a/tests/ui/transmutability/issue-110892.rs b/tests/ui/transmutability/issue-110892.rs index 9713684c959..ad1b9e7af10 100644 --- a/tests/ui/transmutability/issue-110892.rs +++ b/tests/ui/transmutability/issue-110892.rs @@ -3,7 +3,7 @@ #![allow(incomplete_features)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable< Src, @@ -14,7 +14,7 @@ mod assert { const ASSUME_VALIDITY: bool, >() where - Dst: BikeshedIntrinsicFrom< + Dst: TransmuteFrom< Src, { from_options(ASSUME_ALIGNMENT, ASSUME_LIFETIMES, ASSUME_SAFETY, ASSUME_VALIDITY) } >, diff --git a/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.rs b/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.rs index 30c381745d0..07133aa5614 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.rs +++ b/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.rs @@ -2,7 +2,7 @@ #![crate_type = "lib"] -use std::mem::BikeshedIntrinsicFrom; +use std::mem::TransmuteFrom; //~^ ERROR use of unstable library feature 'transmutability' [E0658] use std::mem::Assume; diff --git a/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.stderr b/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.stderr index 9f221907172..a2096cd53e5 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.stderr +++ b/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.stderr @@ -1,8 +1,8 @@ error[E0658]: use of unstable library feature 'transmutability' --> $DIR/feature-missing.rs:5:5 | -LL | use std::mem::BikeshedIntrinsicFrom; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | use std::mem::TransmuteFrom; + | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #99571 for more information = help: add `#![feature(transmutability)]` to the crate attributes to enable diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.rs b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.rs index bcfbc1430a8..b8828c59d35 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.rs +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.rs @@ -5,11 +5,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable() where - Dst: BikeshedIntrinsicFrom + Dst: TransmuteFrom {} } diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst_field.rs b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst_field.rs new file mode 100644 index 00000000000..2285d2f532e --- /dev/null +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst_field.rs @@ -0,0 +1,26 @@ +// An unknown destination type should be gracefully handled. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(incomplete_features)] + +mod assert { + use std::mem::TransmuteFrom; + + pub fn is_transmutable() + where + Dst: TransmuteFrom + {} +} + +fn should_gracefully_handle_unknown_dst_field() { + #[repr(C)] struct Src; + #[repr(C)] struct Dst(Missing); //~ cannot find type + assert::is_transmutable::(); //~ ERROR cannot be safely transmuted +} + +fn should_gracefully_handle_unknown_dst_ref_field() { + #[repr(C)] struct Src(&'static Src); + #[repr(C)] struct Dst(&'static Missing); //~ cannot find type + assert::is_transmutable::(); //~ ERROR cannot be safely transmuted +} diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst_field.stderr b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst_field.stderr new file mode 100644 index 00000000000..564aee687a5 --- /dev/null +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst_field.stderr @@ -0,0 +1,46 @@ +error[E0412]: cannot find type `Missing` in this scope + --> $DIR/unknown_dst_field.rs:18:27 + | +LL | #[repr(C)] struct Dst(Missing); + | ^^^^^^^ not found in this scope + +error[E0412]: cannot find type `Missing` in this scope + --> $DIR/unknown_dst_field.rs:24:36 + | +LL | #[repr(C)] struct Dst(&'static Missing); + | ^^^^^^^ not found in this scope + +error[E0277]: `should_gracefully_handle_unknown_dst_field::Src` cannot be safely transmuted into `should_gracefully_handle_unknown_dst_field::Dst` + --> $DIR/unknown_dst_field.rs:19:36 + | +LL | assert::is_transmutable::(); + | ^^^ `should_gracefully_handle_unknown_dst_field::Dst` has an unknown layout + | +note: required by a bound in `is_transmutable` + --> $DIR/unknown_dst_field.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this function +LL | where +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `should_gracefully_handle_unknown_dst_ref_field::Src` cannot be safely transmuted into `should_gracefully_handle_unknown_dst_ref_field::Dst` + --> $DIR/unknown_dst_field.rs:25:36 + | +LL | assert::is_transmutable::(); + | ^^^ `should_gracefully_handle_unknown_dst_ref_field::Dst` has an unknown layout + | +note: required by a bound in `is_transmutable` + --> $DIR/unknown_dst_field.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this function +LL | where +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0412. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.rs b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.rs index bd7c3fc7fb5..10ba7a61b87 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.rs +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.rs @@ -5,11 +5,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable() where - Dst: BikeshedIntrinsicFrom + Dst: TransmuteFrom {} } diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.rs b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.rs index 58c16d773e1..598e04971e2 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.rs +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.rs @@ -5,16 +5,22 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable() where - Dst: BikeshedIntrinsicFrom + Dst: TransmuteFrom {} } -fn should_gracefully_handle_unknown_dst_field() { - #[repr(C)] struct Src; - #[repr(C)] struct Dst(Missing); //~ cannot find type +fn should_gracefully_handle_unknown_src_field() { + #[repr(C)] struct Src(Missing); //~ cannot find type + #[repr(C)] struct Dst(); + assert::is_transmutable::(); //~ ERROR cannot be safely transmuted +} + +fn should_gracefully_handle_unknown_src_ref_field() { + #[repr(C)] struct Src(&'static Missing); //~ cannot find type + #[repr(C)] struct Dst(&'static Dst); assert::is_transmutable::(); //~ ERROR cannot be safely transmuted } diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.stderr b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.stderr index cabc7bcfef7..1156391c301 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.stderr +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.stderr @@ -1,14 +1,20 @@ error[E0412]: cannot find type `Missing` in this scope - --> $DIR/unknown_src_field.rs:18:27 + --> $DIR/unknown_src_field.rs:17:27 | -LL | #[repr(C)] struct Dst(Missing); +LL | #[repr(C)] struct Src(Missing); | ^^^^^^^ not found in this scope -error[E0277]: `Src` cannot be safely transmuted into `Dst` +error[E0412]: cannot find type `Missing` in this scope + --> $DIR/unknown_src_field.rs:23:36 + | +LL | #[repr(C)] struct Src(&'static Missing); + | ^^^^^^^ not found in this scope + +error[E0277]: `should_gracefully_handle_unknown_src_field::Src` cannot be safely transmuted into `should_gracefully_handle_unknown_src_field::Dst` --> $DIR/unknown_src_field.rs:19:36 | LL | assert::is_transmutable::(); - | ^^^ analyzing the transmutability of `Dst` is not yet supported + | ^^^ `should_gracefully_handle_unknown_src_field::Src` has an unknown layout | note: required by a bound in `is_transmutable` --> $DIR/unknown_src_field.rs:12:14 @@ -16,10 +22,25 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` -error: aborting due to 2 previous errors +error[E0277]: `should_gracefully_handle_unknown_src_ref_field::Src` cannot be safely transmuted into `should_gracefully_handle_unknown_src_ref_field::Dst` + --> $DIR/unknown_src_field.rs:25:36 + | +LL | assert::is_transmutable::(); + | ^^^ `should_gracefully_handle_unknown_src_ref_field::Src` has an unknown layout + | +note: required by a bound in `is_transmutable` + --> $DIR/unknown_src_field.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this function +LL | where +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error: aborting due to 4 previous errors Some errors have detailed explanations: E0277, E0412. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.rs b/tests/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.rs index 608366fa089..df925975bad 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.rs +++ b/tests/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.rs @@ -8,7 +8,7 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable< Src, @@ -19,7 +19,7 @@ mod assert { const ASSUME_VALIDITY: bool, >() where - Dst: BikeshedIntrinsicFrom< + Dst: TransmuteFrom< Src, { from_options(ASSUME_ALIGNMENT, ASSUME_LIFETIMES, ASSUME_SAFETY, ASSUME_VALIDITY) } >, diff --git a/tests/ui/transmutability/maybeuninit.rs b/tests/ui/transmutability/maybeuninit.rs index 77c3381c774..7b60785b7e0 100644 --- a/tests/ui/transmutability/maybeuninit.rs +++ b/tests/ui/transmutability/maybeuninit.rs @@ -5,11 +5,11 @@ use std::mem::MaybeUninit; mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable() where - Dst: BikeshedIntrinsicFrom + Dst: TransmuteFrom {} } diff --git a/tests/ui/transmutability/maybeuninit.stderr b/tests/ui/transmutability/maybeuninit.stderr index be7dcaf35ea..897c2df10a8 100644 --- a/tests/ui/transmutability/maybeuninit.stderr +++ b/tests/ui/transmutability/maybeuninit.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` error: aborting due to 1 previous error diff --git a/tests/ui/transmutability/primitives/bool-mut.rs b/tests/ui/transmutability/primitives/bool-mut.rs index 09b6d582d87..0a7dad37aaf 100644 --- a/tests/ui/transmutability/primitives/bool-mut.rs +++ b/tests/ui/transmutability/primitives/bool-mut.rs @@ -2,11 +2,11 @@ #![feature(transmutability)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable() where - Dst: BikeshedIntrinsicFrom + Dst: TransmuteFrom {} } diff --git a/tests/ui/transmutability/primitives/bool-mut.stderr b/tests/ui/transmutability/primitives/bool-mut.stderr index a6cf146659e..fcf60bc979c 100644 --- a/tests/ui/transmutability/primitives/bool-mut.stderr +++ b/tests/ui/transmutability/primitives/bool-mut.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error: aborting due to 1 previous error diff --git a/tests/ui/transmutability/primitives/bool.current.stderr b/tests/ui/transmutability/primitives/bool.current.stderr index da6a4a44e95..2945cdaad40 100644 --- a/tests/ui/transmutability/primitives/bool.current.stderr +++ b/tests/ui/transmutability/primitives/bool.current.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error: aborting due to 1 previous error diff --git a/tests/ui/transmutability/primitives/bool.next.stderr b/tests/ui/transmutability/primitives/bool.next.stderr index da6a4a44e95..2945cdaad40 100644 --- a/tests/ui/transmutability/primitives/bool.next.stderr +++ b/tests/ui/transmutability/primitives/bool.next.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error: aborting due to 1 previous error diff --git a/tests/ui/transmutability/primitives/bool.rs b/tests/ui/transmutability/primitives/bool.rs index 19236a1ae2e..6fac8ba1ad1 100644 --- a/tests/ui/transmutability/primitives/bool.rs +++ b/tests/ui/transmutability/primitives/bool.rs @@ -4,16 +4,16 @@ #![feature(transmutability)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable() where - Dst: BikeshedIntrinsicFrom + Dst: TransmuteFrom {} pub fn is_maybe_transmutable() where - Dst: BikeshedIntrinsicFrom + Dst: TransmuteFrom {} } diff --git a/tests/ui/transmutability/primitives/numbers.current.stderr b/tests/ui/transmutability/primitives/numbers.current.stderr index 0a9b9d182f8..efb2ce8c772 100644 --- a/tests/ui/transmutability/primitives/numbers.current.stderr +++ b/tests/ui/transmutability/primitives/numbers.current.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u16` --> $DIR/numbers.rs:65:40 @@ -25,8 +25,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `i32` --> $DIR/numbers.rs:66:40 @@ -40,8 +40,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `f32` --> $DIR/numbers.rs:67:40 @@ -55,8 +55,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u32` --> $DIR/numbers.rs:68:40 @@ -70,8 +70,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:69:40 @@ -85,8 +85,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:70:40 @@ -100,8 +100,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:71:40 @@ -115,8 +115,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:72:39 @@ -130,8 +130,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:73:39 @@ -145,8 +145,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i16` --> $DIR/numbers.rs:75:40 @@ -160,8 +160,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u16` --> $DIR/numbers.rs:76:40 @@ -175,8 +175,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i32` --> $DIR/numbers.rs:77:40 @@ -190,8 +190,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `f32` --> $DIR/numbers.rs:78:40 @@ -205,8 +205,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u32` --> $DIR/numbers.rs:79:40 @@ -220,8 +220,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:80:40 @@ -235,8 +235,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:81:40 @@ -250,8 +250,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:82:40 @@ -265,8 +265,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:83:39 @@ -280,8 +280,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:84:39 @@ -295,8 +295,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `i32` --> $DIR/numbers.rs:86:40 @@ -310,8 +310,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `f32` --> $DIR/numbers.rs:87:40 @@ -325,8 +325,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `u32` --> $DIR/numbers.rs:88:40 @@ -340,8 +340,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:89:40 @@ -355,8 +355,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:90:40 @@ -370,8 +370,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:91:40 @@ -385,8 +385,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:92:39 @@ -400,8 +400,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:93:39 @@ -415,8 +415,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `i32` --> $DIR/numbers.rs:95:40 @@ -430,8 +430,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `f32` --> $DIR/numbers.rs:96:40 @@ -445,8 +445,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `u32` --> $DIR/numbers.rs:97:40 @@ -460,8 +460,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:98:40 @@ -475,8 +475,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:99:40 @@ -490,8 +490,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:100:40 @@ -505,8 +505,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:101:39 @@ -520,8 +520,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:102:39 @@ -535,8 +535,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:104:40 @@ -550,8 +550,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:105:40 @@ -565,8 +565,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:106:40 @@ -580,8 +580,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:107:39 @@ -595,8 +595,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:108:39 @@ -610,8 +610,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:110:40 @@ -625,8 +625,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:111:40 @@ -640,8 +640,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:112:40 @@ -655,8 +655,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:113:39 @@ -670,8 +670,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:114:39 @@ -685,8 +685,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:116:40 @@ -700,8 +700,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:117:40 @@ -715,8 +715,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:118:40 @@ -730,8 +730,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:119:39 @@ -745,8 +745,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:120:39 @@ -760,8 +760,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u64` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:122:39 @@ -775,8 +775,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u64` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:123:39 @@ -790,8 +790,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i64` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:125:39 @@ -805,8 +805,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i64` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:126:39 @@ -820,8 +820,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f64` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:128:39 @@ -835,8 +835,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f64` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:129:39 @@ -850,8 +850,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error: aborting due to 57 previous errors diff --git a/tests/ui/transmutability/primitives/numbers.next.stderr b/tests/ui/transmutability/primitives/numbers.next.stderr index 0a9b9d182f8..efb2ce8c772 100644 --- a/tests/ui/transmutability/primitives/numbers.next.stderr +++ b/tests/ui/transmutability/primitives/numbers.next.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u16` --> $DIR/numbers.rs:65:40 @@ -25,8 +25,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `i32` --> $DIR/numbers.rs:66:40 @@ -40,8 +40,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `f32` --> $DIR/numbers.rs:67:40 @@ -55,8 +55,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u32` --> $DIR/numbers.rs:68:40 @@ -70,8 +70,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:69:40 @@ -85,8 +85,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:70:40 @@ -100,8 +100,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:71:40 @@ -115,8 +115,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:72:39 @@ -130,8 +130,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:73:39 @@ -145,8 +145,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i16` --> $DIR/numbers.rs:75:40 @@ -160,8 +160,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u16` --> $DIR/numbers.rs:76:40 @@ -175,8 +175,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i32` --> $DIR/numbers.rs:77:40 @@ -190,8 +190,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `f32` --> $DIR/numbers.rs:78:40 @@ -205,8 +205,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u32` --> $DIR/numbers.rs:79:40 @@ -220,8 +220,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:80:40 @@ -235,8 +235,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:81:40 @@ -250,8 +250,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:82:40 @@ -265,8 +265,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:83:39 @@ -280,8 +280,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:84:39 @@ -295,8 +295,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `i32` --> $DIR/numbers.rs:86:40 @@ -310,8 +310,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `f32` --> $DIR/numbers.rs:87:40 @@ -325,8 +325,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `u32` --> $DIR/numbers.rs:88:40 @@ -340,8 +340,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:89:40 @@ -355,8 +355,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:90:40 @@ -370,8 +370,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:91:40 @@ -385,8 +385,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:92:39 @@ -400,8 +400,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:93:39 @@ -415,8 +415,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `i32` --> $DIR/numbers.rs:95:40 @@ -430,8 +430,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `f32` --> $DIR/numbers.rs:96:40 @@ -445,8 +445,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `u32` --> $DIR/numbers.rs:97:40 @@ -460,8 +460,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:98:40 @@ -475,8 +475,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:99:40 @@ -490,8 +490,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:100:40 @@ -505,8 +505,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:101:39 @@ -520,8 +520,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:102:39 @@ -535,8 +535,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:104:40 @@ -550,8 +550,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:105:40 @@ -565,8 +565,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:106:40 @@ -580,8 +580,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:107:39 @@ -595,8 +595,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:108:39 @@ -610,8 +610,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:110:40 @@ -625,8 +625,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:111:40 @@ -640,8 +640,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:112:40 @@ -655,8 +655,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:113:39 @@ -670,8 +670,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:114:39 @@ -685,8 +685,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:116:40 @@ -700,8 +700,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:117:40 @@ -715,8 +715,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:118:40 @@ -730,8 +730,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:119:39 @@ -745,8 +745,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:120:39 @@ -760,8 +760,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u64` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:122:39 @@ -775,8 +775,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u64` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:123:39 @@ -790,8 +790,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i64` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:125:39 @@ -805,8 +805,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i64` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:126:39 @@ -820,8 +820,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f64` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:128:39 @@ -835,8 +835,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f64` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:129:39 @@ -850,8 +850,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error: aborting due to 57 previous errors diff --git a/tests/ui/transmutability/primitives/numbers.rs b/tests/ui/transmutability/primitives/numbers.rs index 401502474cf..b5c21c992b6 100644 --- a/tests/ui/transmutability/primitives/numbers.rs +++ b/tests/ui/transmutability/primitives/numbers.rs @@ -7,11 +7,11 @@ #![allow(dead_code)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable() where - Dst: BikeshedIntrinsicFrom + Dst: TransmuteFrom {} } diff --git a/tests/ui/transmutability/primitives/unit.current.stderr b/tests/ui/transmutability/primitives/unit.current.stderr index 52b708d680e..4bfb229832b 100644 --- a/tests/ui/transmutability/primitives/unit.current.stderr +++ b/tests/ui/transmutability/primitives/unit.current.stderr @@ -10,7 +10,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() where - Dst: BikeshedIntrinsicFrom(src: Src) -> Dst +where + Dst: TransmuteFrom, +{ + core::intrinsics::transmute_unchecked(src) +} + +mod bare { + use super::*; + + fn extend_bare<'a>(src: &'a u8) -> &'static u8 { + unsafe { transmute(src) } + } +} + +mod nested { + use super::*; + + fn extend_nested<'a>(src: &'a &'a u8) -> &'a &'static u8 { + unsafe { transmute(src) } + } +} + +mod tuple { + use super::*; + + fn extend_unit<'a>(src: (&'a u8,)) -> (&'static u8,) { + unsafe { transmute(src) } + } + + fn extend_pair<'a>(src: (&'a u8, u8)) -> (&'static u8, u8) { + unsafe { transmute(src) } + } +} + +mod r#struct { + use super::*; + + struct Struct<'a>(&'a u8); + + fn extend_struct<'a>(src: Struct<'a>) -> Struct<'static> { + unsafe { transmute(src) } + } +} + +mod r#enum { + use super::*; + + enum Single<'a> { + A(&'a u8), + } + + fn extend_single<'a>(src: Single<'a>) -> Single<'static> { + unsafe { transmute(src) } + } + + enum Multi<'a> { + A(&'a u8), + B, + C, + } + + fn extend_multi<'a>(src: Multi<'a>) -> Multi<'static> { + unsafe { transmute(src) } + } +} + +mod hrtb { + use super::*; + + fn call_extend_hrtb<'a>(src: &'a u8) -> &'static u8 { + unsafe { extend_hrtb(src) } + } + + unsafe fn extend_hrtb<'a>(src: &'a u8) -> &'static u8 + where + for<'b> &'b u8: TransmuteFrom<&'a u8, { Assume::LIFETIMES }>, + { + core::intrinsics::transmute_unchecked(src) + } +} + +fn main() {} diff --git a/tests/ui/transmutability/references/accept_unexercised_lifetime_extension.rs b/tests/ui/transmutability/references/accept_unexercised_lifetime_extension.rs new file mode 100644 index 00000000000..5734575e90b --- /dev/null +++ b/tests/ui/transmutability/references/accept_unexercised_lifetime_extension.rs @@ -0,0 +1,68 @@ +//@ check-pass + +//! Accept lifetime extensions of un-exercised lifetimes. + +#![feature(transmutability, core_intrinsics)] + +use std::mem::{Assume, TransmuteFrom}; + +unsafe fn transmute(src: Src) -> Dst +where + Dst: TransmuteFrom, +{ + core::intrinsics::transmute_unchecked(src) +} + +enum Void {} + +mod phantom { + use super::*; + use std::marker::PhantomData; + + fn extend_bare<'a>(src: PhantomData<&'a u8>) -> PhantomData<&'static u8> { + unsafe { transmute(src) } + } +} + + +mod tuple { + use super::*; + + fn extend_pair<'a>(src: (&'a u8, Void)) -> (&'static u8, Void) { + unsafe { transmute(src) } + } +} + +mod r#struct { + use super::*; + + struct Struct<'a>(&'a u8, Void); + + fn extend_struct<'a>(src: Struct<'a>) -> Struct<'static> { + unsafe { transmute(src) } + } +} + +mod r#enum { + use super::*; + + enum Single<'a> { + A(&'a u8, Void), + } + + fn extend_single<'a>(src: Single<'a>) -> Single<'static> { + unsafe { transmute(src) } + } + + enum Multi<'a> { + A(&'a u8, Void), + B, + C, + } + + fn extend_multi<'a>(src: Multi<'a>) -> Multi<'static> { + unsafe { transmute(src) } + } +} + +fn main() {} diff --git a/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible-mut.rs b/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible-mut.rs index ba2db755e3b..92068ee0d4f 100644 --- a/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible-mut.rs +++ b/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible-mut.rs @@ -2,11 +2,11 @@ #![feature(transmutability)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable() where - Dst: BikeshedIntrinsicFrom() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() where - Dst: BikeshedIntrinsicFrom() where - Dst: BikeshedIntrinsicFrom() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() where - Dst: BikeshedIntrinsicFrom() where - Dst: BikeshedIntrinsicFrom< + Dst: TransmuteFrom< Src, { Assume { diff --git a/tests/ui/transmutability/references/reject_extension.stderr b/tests/ui/transmutability/references/reject_extension.stderr index 88dd0313e3c..182106acf12 100644 --- a/tests/ui/transmutability/references/reject_extension.stderr +++ b/tests/ui/transmutability/references/reject_extension.stderr @@ -10,7 +10,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom< +LL | Dst: TransmuteFrom< | ______________^ LL | | Src, LL | | { diff --git a/tests/ui/transmutability/references/reject_lifetime_extension.rs b/tests/ui/transmutability/references/reject_lifetime_extension.rs new file mode 100644 index 00000000000..ff9290c34af --- /dev/null +++ b/tests/ui/transmutability/references/reject_lifetime_extension.rs @@ -0,0 +1,91 @@ +//@ check-fail + +//! Reject lifetime extensions. + +#![feature(transmutability, core_intrinsics)] + +use std::mem::{Assume, TransmuteFrom}; + +unsafe fn transmute(src: Src) -> Dst +where + Dst: TransmuteFrom, +{ + core::intrinsics::transmute_unchecked(src) +} + +mod bare { + use super::*; + + fn extend_bare<'a>(src: &'a u8) -> &'static u8 { + unsafe { transmute(src) } //~ ERROR lifetime may not live long enough + } +} + +mod nested { + use super::*; + + fn extend_nested<'a>(src: &'a &'a u8) -> &'a &'static u8 { + unsafe { transmute(src) } //~ ERROR lifetime may not live long enough + } +} + +mod tuple { + use super::*; + + fn extend_unit<'a>(src: (&'a u8,)) -> (&'static u8,) { + unsafe { transmute(src) } //~ ERROR lifetime may not live long enough + } + + fn extend_pair<'a>(src: (&'a u8, u8)) -> (&'static u8, u8) { + unsafe { transmute(src) } //~ ERROR lifetime may not live long enough + } +} + +mod r#struct { + use super::*; + + struct Struct<'a>(&'a u8); + + fn extend_struct<'a>(src: Struct<'a>) -> Struct<'static> { + unsafe { transmute(src) } //~ ERROR lifetime may not live long enough + } +} + +mod r#enum { + use super::*; + + enum Single<'a> { + A(&'a u8), + } + + fn extend_single<'a>(src: Single<'a>) -> Single<'static> { + unsafe { transmute(src) } //~ ERROR lifetime may not live long enough + } + + enum Multi<'a> { + A(&'a u8), + B, + C, + } + + fn extend_multi<'a>(src: Multi<'a>) -> Multi<'static> { + unsafe { transmute(src) } //~ ERROR lifetime may not live long enough + } +} + +mod hrtb { + use super::*; + + fn call_extend_hrtb<'a>(src: &'a u8) -> &'static u8 { + unsafe { extend_hrtb(src) } //~ ERROR borrowed data escapes outside of function + } + + unsafe fn extend_hrtb<'a>(src: &'a u8) -> &'static u8 + where + for<'b> &'b u8: TransmuteFrom<&'a u8>, + { + core::intrinsics::transmute_unchecked(src) + } +} + +fn main() {} diff --git a/tests/ui/transmutability/references/reject_lifetime_extension.stderr b/tests/ui/transmutability/references/reject_lifetime_extension.stderr new file mode 100644 index 00000000000..a597041c6ca --- /dev/null +++ b/tests/ui/transmutability/references/reject_lifetime_extension.stderr @@ -0,0 +1,78 @@ +error: lifetime may not live long enough + --> $DIR/reject_lifetime_extension.rs:20:18 + | +LL | fn extend_bare<'a>(src: &'a u8) -> &'static u8 { + | -- lifetime `'a` defined here +LL | unsafe { transmute(src) } + | ^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/reject_lifetime_extension.rs:28:18 + | +LL | fn extend_nested<'a>(src: &'a &'a u8) -> &'a &'static u8 { + | -- lifetime `'a` defined here +LL | unsafe { transmute(src) } + | ^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/reject_lifetime_extension.rs:36:18 + | +LL | fn extend_unit<'a>(src: (&'a u8,)) -> (&'static u8,) { + | -- lifetime `'a` defined here +LL | unsafe { transmute(src) } + | ^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/reject_lifetime_extension.rs:40:18 + | +LL | fn extend_pair<'a>(src: (&'a u8, u8)) -> (&'static u8, u8) { + | -- lifetime `'a` defined here +LL | unsafe { transmute(src) } + | ^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/reject_lifetime_extension.rs:50:18 + | +LL | fn extend_struct<'a>(src: Struct<'a>) -> Struct<'static> { + | -- lifetime `'a` defined here +LL | unsafe { transmute(src) } + | ^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/reject_lifetime_extension.rs:62:18 + | +LL | fn extend_single<'a>(src: Single<'a>) -> Single<'static> { + | -- lifetime `'a` defined here +LL | unsafe { transmute(src) } + | ^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/reject_lifetime_extension.rs:72:18 + | +LL | fn extend_multi<'a>(src: Multi<'a>) -> Multi<'static> { + | -- lifetime `'a` defined here +LL | unsafe { transmute(src) } + | ^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error[E0521]: borrowed data escapes outside of function + --> $DIR/reject_lifetime_extension.rs:80:18 + | +LL | fn call_extend_hrtb<'a>(src: &'a u8) -> &'static u8 { + | -- --- `src` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | unsafe { extend_hrtb(src) } + | ^^^^^^^^^^^^^^^^ + | | + | `src` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/reject_lifetime_extension.rs:85:25 + | +LL | for<'b> &'b u8: TransmuteFrom<&'a u8>, + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/transmutability/references/u8-to-unit.rs b/tests/ui/transmutability/references/u8-to-unit.rs index 017b73d9595..98deb6457cb 100644 --- a/tests/ui/transmutability/references/u8-to-unit.rs +++ b/tests/ui/transmutability/references/u8-to-unit.rs @@ -2,11 +2,11 @@ #![feature(transmutability)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable() where - Dst: BikeshedIntrinsicFrom() where - Dst: BikeshedIntrinsicFrom() where - Dst: BikeshedIntrinsicFrom() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() where - Dst: BikeshedIntrinsicFrom + Dst: TransmuteFrom {} } diff --git a/tests/ui/transmutability/references/unsafecell.stderr b/tests/ui/transmutability/references/unsafecell.stderr index 8bb32359355..6664d8a7d6f 100644 --- a/tests/ui/transmutability/references/unsafecell.stderr +++ b/tests/ui/transmutability/references/unsafecell.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` error[E0277]: `&UnsafeCell` cannot be safely transmuted into `&UnsafeCell` --> $DIR/unsafecell.rs:29:62 @@ -25,8 +25,8 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` error: aborting due to 2 previous errors diff --git a/tests/ui/transmutability/region-infer.rs b/tests/ui/transmutability/region-infer.rs index 0632bc53176..c164f35c447 100644 --- a/tests/ui/transmutability/region-infer.rs +++ b/tests/ui/transmutability/region-infer.rs @@ -1,13 +1,13 @@ #![feature(transmutability)] -use std::mem::{Assume, BikeshedIntrinsicFrom}; +use std::mem::{Assume, TransmuteFrom}; #[repr(C)] struct W<'a>(&'a ()); fn test<'a>() where - W<'a>: BikeshedIntrinsicFrom< + W<'a>: TransmuteFrom< (), { Assume { alignment: true, lifetimes: true, safety: true, validity: true } }, >, diff --git a/tests/ui/transmutability/region-infer.stderr b/tests/ui/transmutability/region-infer.stderr index 03c46823838..09ecf484bc8 100644 --- a/tests/ui/transmutability/region-infer.stderr +++ b/tests/ui/transmutability/region-infer.stderr @@ -10,7 +10,7 @@ note: required by a bound in `test` LL | fn test<'a>() | ---- required by a bound in this function LL | where -LL | W<'a>: BikeshedIntrinsicFrom< +LL | W<'a>: TransmuteFrom< | ____________^ LL | | (), LL | | { Assume { alignment: true, lifetimes: true, safety: true, validity: true } }, diff --git a/tests/ui/transmutability/safety/assume/should_accept_if_dst_has_safety_invariant.rs b/tests/ui/transmutability/safety/assume/should_accept_if_dst_has_safety_invariant.rs index cb3c1cdf46c..0113049f51e 100644 --- a/tests/ui/transmutability/safety/assume/should_accept_if_dst_has_safety_invariant.rs +++ b/tests/ui/transmutability/safety/assume/should_accept_if_dst_has_safety_invariant.rs @@ -8,11 +8,11 @@ #![allow(dead_code)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable() where - Dst: BikeshedIntrinsicFrom + Dst: TransmuteFrom {} } diff --git a/tests/ui/transmutability/safety/assume/should_accept_if_ref_src_has_safety_invariant.rs b/tests/ui/transmutability/safety/assume/should_accept_if_ref_src_has_safety_invariant.rs index b12c4a10d12..eca7a06559d 100644 --- a/tests/ui/transmutability/safety/assume/should_accept_if_ref_src_has_safety_invariant.rs +++ b/tests/ui/transmutability/safety/assume/should_accept_if_ref_src_has_safety_invariant.rs @@ -8,11 +8,11 @@ #![allow(dead_code)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable() where - Dst: BikeshedIntrinsicFrom + Dst: TransmuteFrom {} } diff --git a/tests/ui/transmutability/safety/assume/should_accept_if_src_has_safety_invariant.rs b/tests/ui/transmutability/safety/assume/should_accept_if_src_has_safety_invariant.rs index ff01462ffec..46e84b48044 100644 --- a/tests/ui/transmutability/safety/assume/should_accept_if_src_has_safety_invariant.rs +++ b/tests/ui/transmutability/safety/assume/should_accept_if_src_has_safety_invariant.rs @@ -8,11 +8,11 @@ #![allow(dead_code)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable() where - Dst: BikeshedIntrinsicFrom + Dst: TransmuteFrom {} } diff --git a/tests/ui/transmutability/safety/should_accept_if_src_has_safety_invariant.rs b/tests/ui/transmutability/safety/should_accept_if_src_has_safety_invariant.rs index d516e9a7da5..aaba6febde4 100644 --- a/tests/ui/transmutability/safety/should_accept_if_src_has_safety_invariant.rs +++ b/tests/ui/transmutability/safety/should_accept_if_src_has_safety_invariant.rs @@ -8,11 +8,11 @@ #![allow(dead_code)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable() where - Dst: BikeshedIntrinsicFrom // safety is NOT assumed + Dst: TransmuteFrom // safety is NOT assumed {} } diff --git a/tests/ui/transmutability/safety/should_reject_if_dst_has_safety_invariant.rs b/tests/ui/transmutability/safety/should_reject_if_dst_has_safety_invariant.rs index 4f0aee31548..6f8e383db1f 100644 --- a/tests/ui/transmutability/safety/should_reject_if_dst_has_safety_invariant.rs +++ b/tests/ui/transmutability/safety/should_reject_if_dst_has_safety_invariant.rs @@ -6,11 +6,11 @@ #![allow(dead_code)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable() where - Dst: BikeshedIntrinsicFrom // safety is NOT assumed + Dst: TransmuteFrom // safety is NOT assumed {} } diff --git a/tests/ui/transmutability/safety/should_reject_if_dst_has_safety_invariant.stderr b/tests/ui/transmutability/safety/should_reject_if_dst_has_safety_invariant.stderr index 2339c268326..6445b1e146e 100644 --- a/tests/ui/transmutability/safety/should_reject_if_dst_has_safety_invariant.stderr +++ b/tests/ui/transmutability/safety/should_reject_if_dst_has_safety_invariant.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom // safety is NOT assumed - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom // safety is NOT assumed + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error: aborting due to 1 previous error diff --git a/tests/ui/transmutability/safety/should_reject_if_ref_src_has_safety_invariant.rs b/tests/ui/transmutability/safety/should_reject_if_ref_src_has_safety_invariant.rs index 126059dd7b7..16d163d5420 100644 --- a/tests/ui/transmutability/safety/should_reject_if_ref_src_has_safety_invariant.rs +++ b/tests/ui/transmutability/safety/should_reject_if_ref_src_has_safety_invariant.rs @@ -6,11 +6,11 @@ #![allow(dead_code)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable() where - Dst: BikeshedIntrinsicFrom // safety is NOT assumed + Dst: TransmuteFrom // safety is NOT assumed {} } diff --git a/tests/ui/transmutability/safety/should_reject_if_ref_src_has_safety_invariant.stderr b/tests/ui/transmutability/safety/should_reject_if_ref_src_has_safety_invariant.stderr index 99feebe9211..38ef829f064 100644 --- a/tests/ui/transmutability/safety/should_reject_if_ref_src_has_safety_invariant.stderr +++ b/tests/ui/transmutability/safety/should_reject_if_ref_src_has_safety_invariant.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom // safety is NOT assumed - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom // safety is NOT assumed + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error: aborting due to 1 previous error diff --git a/tests/ui/transmutability/structs/repr/should_handle_align.rs b/tests/ui/transmutability/structs/repr/should_handle_align.rs index 0c207766045..03065298b50 100644 --- a/tests/ui/transmutability/structs/repr/should_handle_align.rs +++ b/tests/ui/transmutability/structs/repr/should_handle_align.rs @@ -6,11 +6,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable() where - Dst: BikeshedIntrinsicFrom() where - Dst: BikeshedIntrinsicFrom() where - Dst: BikeshedIntrinsicFrom() where - Dst: BikeshedIntrinsicFrom, + Dst: TransmuteFrom, { } } @@ -22,5 +22,4 @@ fn should_pad_explicitly_packed_field() { //~^ ERROR: recursive type assert::is_maybe_transmutable::(); - //~^ ERROR: cannot be safely transmuted } diff --git a/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.stderr b/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.stderr index ebfb5361143..bdf2d3b6a58 100644 --- a/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.stderr +++ b/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.stderr @@ -12,25 +12,10 @@ LL | struct ExplicitlyPadded(Box); error[E0391]: cycle detected when computing layout of `should_pad_explicitly_packed_field::ExplicitlyPadded` | = note: ...which immediately requires computing layout of `should_pad_explicitly_packed_field::ExplicitlyPadded` again - = note: cycle used when evaluating trait selection obligation `(): core::mem::transmutability::BikeshedIntrinsicFrom` + = note: cycle used when evaluating trait selection obligation `(): core::mem::transmutability::TransmuteFrom` = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error[E0277]: `ExplicitlyPadded` cannot be safely transmuted into `()` - --> $DIR/transmute_infinitely_recursive_type.rs:24:55 - | -LL | assert::is_maybe_transmutable::(); - | ^^ analyzing the transmutability of `ExplicitlyPadded` is not yet supported - | -note: required by a bound in `is_maybe_transmutable` - --> $DIR/transmute_infinitely_recursive_type.rs:14:14 - | -LL | pub fn is_maybe_transmutable() - | --------------------- required by a bound in this function -LL | where -LL | Dst: BikeshedIntrinsicFrom, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` +error: aborting due to 2 previous errors -error: aborting due to 3 previous errors - -Some errors have detailed explanations: E0072, E0277, E0391. +Some errors have detailed explanations: E0072, E0391. For more information about an error, try `rustc --explain E0072`. diff --git a/tests/ui/transmutability/structs/should_order_fields_correctly.rs b/tests/ui/transmutability/structs/should_order_fields_correctly.rs index 3675e4330ec..aa9ca39eff2 100644 --- a/tests/ui/transmutability/structs/should_order_fields_correctly.rs +++ b/tests/ui/transmutability/structs/should_order_fields_correctly.rs @@ -6,11 +6,11 @@ #![allow(dead_code)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable() where - Dst: BikeshedIntrinsicFrom() where - Dst: BikeshedIntrinsicFrom< + Dst: TransmuteFrom< Src, { Assume { alignment: true, lifetimes: true, safety: true, validity: true } }, >, diff --git a/tests/ui/transmutability/uninhabited.rs b/tests/ui/transmutability/uninhabited.rs index 7524922c16a..74f7a1a2e89 100644 --- a/tests/ui/transmutability/uninhabited.rs +++ b/tests/ui/transmutability/uninhabited.rs @@ -3,11 +3,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable() where - Dst: BikeshedIntrinsicFrom() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() where - Dst: BikeshedIntrinsicFrom + Dst: TransmuteFrom {} } diff --git a/tests/ui/transmutability/unions/repr/should_handle_align.rs b/tests/ui/transmutability/unions/repr/should_handle_align.rs index ba4e904e161..0605651bd7b 100644 --- a/tests/ui/transmutability/unions/repr/should_handle_align.rs +++ b/tests/ui/transmutability/unions/repr/should_handle_align.rs @@ -6,11 +6,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable() where - Dst: BikeshedIntrinsicFrom() where - Dst: BikeshedIntrinsicFrom() where - Dst: BikeshedIntrinsicFrom() where - Dst: BikeshedIntrinsicFrom() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom() where - Dst: BikeshedIntrinsicFrom + Dst: TransmuteFrom {} } diff --git a/tests/ui/transmutability/unions/should_reject_contraction.rs b/tests/ui/transmutability/unions/should_reject_contraction.rs index 62a0ee92919..87398328fc7 100644 --- a/tests/ui/transmutability/unions/should_reject_contraction.rs +++ b/tests/ui/transmutability/unions/should_reject_contraction.rs @@ -5,11 +5,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable() where - Dst: BikeshedIntrinsicFrom + Dst: TransmuteFrom {} } diff --git a/tests/ui/transmutability/unions/should_reject_contraction.stderr b/tests/ui/transmutability/unions/should_reject_contraction.stderr index 20eaa3a6b09..ea68de14efc 100644 --- a/tests/ui/transmutability/unions/should_reject_contraction.stderr +++ b/tests/ui/transmutability/unions/should_reject_contraction.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error: aborting due to 1 previous error diff --git a/tests/ui/transmutability/unions/should_reject_disjoint.rs b/tests/ui/transmutability/unions/should_reject_disjoint.rs index 732f92e8160..0427e3c44a2 100644 --- a/tests/ui/transmutability/unions/should_reject_disjoint.rs +++ b/tests/ui/transmutability/unions/should_reject_disjoint.rs @@ -5,11 +5,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable() where - Dst: BikeshedIntrinsicFrom + Dst: TransmuteFrom {} } diff --git a/tests/ui/transmutability/unions/should_reject_disjoint.stderr b/tests/ui/transmutability/unions/should_reject_disjoint.stderr index ea47797c970..d55abbe0817 100644 --- a/tests/ui/transmutability/unions/should_reject_disjoint.stderr +++ b/tests/ui/transmutability/unions/should_reject_disjoint.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` error[E0277]: `B` cannot be safely transmuted into `A` --> $DIR/should_reject_disjoint.rs:33:40 @@ -25,8 +25,8 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` error: aborting due to 2 previous errors diff --git a/tests/ui/transmutability/unions/should_reject_intersecting.rs b/tests/ui/transmutability/unions/should_reject_intersecting.rs index 752a606c861..9b3b18919f5 100644 --- a/tests/ui/transmutability/unions/should_reject_intersecting.rs +++ b/tests/ui/transmutability/unions/should_reject_intersecting.rs @@ -6,11 +6,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable() where - Dst: BikeshedIntrinsicFrom + Dst: TransmuteFrom // validity is NOT assumed -----^^^^^^^^^^^^^^^^^^ {} } diff --git a/tests/ui/transmutability/unions/should_reject_intersecting.stderr b/tests/ui/transmutability/unions/should_reject_intersecting.stderr index 79dec659d9d..522681d7d15 100644 --- a/tests/ui/transmutability/unions/should_reject_intersecting.stderr +++ b/tests/ui/transmutability/unions/should_reject_intersecting.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `B` cannot be safely transmuted into `A` --> $DIR/should_reject_intersecting.rs:36:34 @@ -25,8 +25,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error: aborting due to 2 previous errors diff --git a/tests/ui/try-trait/bad-interconversion.stderr b/tests/ui/try-trait/bad-interconversion.stderr index 642a93d64e2..9aab2cf6ab8 100644 --- a/tests/ui/try-trait/bad-interconversion.stderr +++ b/tests/ui/try-trait/bad-interconversion.stderr @@ -45,7 +45,7 @@ LL | Some(Err("hello")?) | ^ use `.ok()?` if you want to discard the `Result` error information | = help: the trait `FromResidual>` is not implemented for `Option` - = help: the trait `FromResidual` is implemented for `Option` + = help: the trait `FromResidual>` is implemented for `Option` error[E0277]: the `?` operator can only be used on `Option`s in a function that returns `Option` --> $DIR/bad-interconversion.rs:27:33 @@ -56,7 +56,7 @@ LL | Some(ControlFlow::Break(123)?) | ^ this `?` produces `ControlFlow<{integer}, Infallible>`, which is incompatible with `Option` | = help: the trait `FromResidual>` is not implemented for `Option` - = help: the trait `FromResidual` is implemented for `Option` + = help: the trait `FromResidual>` is implemented for `Option` error[E0277]: the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow` --> $DIR/bad-interconversion.rs:32:39 diff --git a/tests/ui/try-trait/option-to-result.stderr b/tests/ui/try-trait/option-to-result.stderr index 8055b2a0b04..1a5a925f92f 100644 --- a/tests/ui/try-trait/option-to-result.stderr +++ b/tests/ui/try-trait/option-to-result.stderr @@ -20,7 +20,7 @@ LL | a?; | ^ use `.ok()?` if you want to discard the `Result` error information | = help: the trait `FromResidual>` is not implemented for `Option` - = help: the trait `FromResidual` is implemented for `Option` + = help: the trait `FromResidual>` is implemented for `Option` error: aborting due to 2 previous errors diff --git a/tests/ui/try-trait/try-operator-on-main.stderr b/tests/ui/try-trait/try-operator-on-main.stderr index d22117165c1..311e8076ed4 100644 --- a/tests/ui/try-trait/try-operator-on-main.stderr +++ b/tests/ui/try-trait/try-operator-on-main.stderr @@ -14,9 +14,7 @@ LL ~ fn main() -> Result<(), Box> { LL | // error for a `Try` type on a non-`Try` fn ... LL | try_trait_generic::<()>(); -LL + LL + Ok(()) -LL + } | error[E0277]: the `?` operator can only be applied to values that implement `Try` diff --git a/tests/ui/type-alias-impl-trait/different_args_considered_equal2.stderr b/tests/ui/type-alias-impl-trait/different_args_considered_equal2.stderr index 1104c2c498a..213272f5f34 100644 --- a/tests/ui/type-alias-impl-trait/different_args_considered_equal2.stderr +++ b/tests/ui/type-alias-impl-trait/different_args_considered_equal2.stderr @@ -9,11 +9,6 @@ LL | fn get_one<'a>(a: *mut &'a str) -> impl IntoIterator> { ... LL | None::> | ^^^^^^^^^^^^^^^^^^^^^^^ - | -help: to declare that `impl IntoIterator>` captures `'a`, you can add an explicit `'a` lifetime bound - | -LL | fn get_one<'a>(a: *mut &'a str) -> impl IntoIterator> + 'a { - | ++++ error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.stderr b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.stderr index 9bffa94fda1..0bf9dccfad8 100644 --- a/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.stderr +++ b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.stderr @@ -8,10 +8,10 @@ LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne { LL | <&'a mut i32 as Callable>::call(y) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: to declare that `impl PlusOne` captures `'a`, you can add an explicit `'a` lifetime bound +help: add a `use<...>` bound to explicitly capture `'a` | -LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne + 'a { - | ++++ +LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne + use<'a> { + | +++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/variance.rs b/tests/ui/type-alias-impl-trait/variance.rs index ba52eaa0359..113f6a4cc44 100644 --- a/tests/ui/type-alias-impl-trait/variance.rs +++ b/tests/ui/type-alias-impl-trait/variance.rs @@ -5,21 +5,21 @@ trait Captures<'a> {} impl Captures<'_> for T {} -type NotCapturedEarly<'a> = impl Sized; //~ [*, o] +type NotCapturedEarly<'a> = impl Sized; //~ ['a: *, 'a: o] //~^ ERROR: unconstrained opaque type -type CapturedEarly<'a> = impl Sized + Captures<'a>; //~ [*, o] +type CapturedEarly<'a> = impl Sized + Captures<'a>; //~ ['a: *, 'a: o] //~^ ERROR: unconstrained opaque type -type NotCapturedLate<'a> = dyn for<'b> Iterator; //~ [*, o, o] +type NotCapturedLate<'a> = dyn for<'b> Iterator; //~ ['a: *, 'b: o, 'a: o] //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type //~| ERROR: unconstrained opaque type -type Captured<'a> = dyn for<'b> Iterator>; //~ [*, o, o] +type Captured<'a> = dyn for<'b> Iterator>; //~ ['a: *, 'b: o, 'a: o] //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type //~| ERROR: unconstrained opaque type -type Bar<'a, 'b: 'b, T> = impl Sized; //~ ERROR [*, *, o, o, o] +type Bar<'a, 'b: 'b, T> = impl Sized; //~ ERROR ['a: *, 'b: *, T: o, 'a: o, 'b: o] //~^ ERROR: unconstrained opaque type trait Foo<'i> { @@ -31,24 +31,24 @@ trait Foo<'i> { } impl<'i> Foo<'i> for &'i () { - type ImplicitCapture<'a> = impl Sized; //~ [*, *, o, o] + type ImplicitCapture<'a> = impl Sized; //~ ['i: *, 'a: *, 'a: o, 'i: o] //~^ ERROR: unconstrained opaque type - type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ [*, *, o, o] + type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ ['i: *, 'a: *, 'a: o, 'i: o] //~^ ERROR: unconstrained opaque type - type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ [*, *, o, o] + type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ ['i: *, 'a: *, 'a: o, 'i: o] //~^ ERROR: unconstrained opaque type } impl<'i> Foo<'i> for () { - type ImplicitCapture<'a> = impl Sized; //~ [*, *, o, o] + type ImplicitCapture<'a> = impl Sized; //~ ['i: *, 'a: *, 'a: o, 'i: o] //~^ ERROR: unconstrained opaque type - type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ [*, *, o, o] + type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ ['i: *, 'a: *, 'a: o, 'i: o] //~^ ERROR: unconstrained opaque type - type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ [*, *, o, o] + type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ ['i: *, 'a: *, 'a: o, 'i: o] //~^ ERROR: unconstrained opaque type } @@ -59,15 +59,15 @@ impl<'a> Nesting<'a> for &'a () { type Output = &'a (); } type NestedDeeply<'a> = - impl Nesting< //~ [*, o] + impl Nesting< //~ ['a: *, 'a: o] 'a, - Output = impl Nesting< //~ [*, o] + Output = impl Nesting< //~ ['a: *, 'a: o] 'a, - Output = impl Nesting< //~ [*, o] + Output = impl Nesting< //~ ['a: *, 'a: o] 'a, - Output = impl Nesting< //~ [*, o] + Output = impl Nesting< //~ ['a: *, 'a: o] 'a, - Output = impl Nesting<'a> //~ [*, o] + Output = impl Nesting<'a> //~ ['a: *, 'a: o] > >, >, diff --git a/tests/ui/type-alias-impl-trait/variance.stderr b/tests/ui/type-alias-impl-trait/variance.stderr index e5ced7a4981..489dfe03d44 100644 --- a/tests/ui/type-alias-impl-trait/variance.stderr +++ b/tests/ui/type-alias-impl-trait/variance.stderr @@ -110,73 +110,73 @@ LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; | = note: `ExplicitCaptureFromGat` must be used in combination with a concrete type within the same impl -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:8:29 | LL | type NotCapturedEarly<'a> = impl Sized; | ^^^^^^^^^^ -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:11:26 | LL | type CapturedEarly<'a> = impl Sized + Captures<'a>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [*, o, o] +error: ['a: *, 'b: o, 'a: o] --> $DIR/variance.rs:14:56 | LL | type NotCapturedLate<'a> = dyn for<'b> Iterator; | ^^^^^^^^^^ -error: [*, o, o] +error: ['a: *, 'b: o, 'a: o] --> $DIR/variance.rs:18:49 | LL | type Captured<'a> = dyn for<'b> Iterator>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [*, *, o, o, o] +error: ['a: *, 'b: *, T: o, 'a: o, 'b: o] --> $DIR/variance.rs:22:27 | LL | type Bar<'a, 'b: 'b, T> = impl Sized; | ^^^^^^^^^^ -error: [*, *, o, o] +error: ['i: *, 'a: *, 'a: o, 'i: o] --> $DIR/variance.rs:34:32 | LL | type ImplicitCapture<'a> = impl Sized; | ^^^^^^^^^^ -error: [*, *, o, o] +error: ['i: *, 'a: *, 'a: o, 'i: o] --> $DIR/variance.rs:37:42 | LL | type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [*, *, o, o] +error: ['i: *, 'a: *, 'a: o, 'i: o] --> $DIR/variance.rs:40:39 | LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [*, *, o, o] +error: ['i: *, 'a: *, 'a: o, 'i: o] --> $DIR/variance.rs:45:32 | LL | type ImplicitCapture<'a> = impl Sized; | ^^^^^^^^^^ -error: [*, *, o, o] +error: ['i: *, 'a: *, 'a: o, 'i: o] --> $DIR/variance.rs:48:42 | LL | type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [*, *, o, o] +error: ['i: *, 'a: *, 'a: o, 'i: o] --> $DIR/variance.rs:51:39 | LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:62:5 | LL | / impl Nesting< @@ -188,7 +188,7 @@ LL | | >, LL | | >; | |_____^ -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:64:18 | LL | Output = impl Nesting< @@ -201,7 +201,7 @@ LL | | >, LL | | >, | |_________^ -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:66:22 | LL | Output = impl Nesting< @@ -214,7 +214,7 @@ LL | | > LL | | >, | |_____________^ -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:68:26 | LL | Output = impl Nesting< @@ -224,7 +224,7 @@ LL | | Output = impl Nesting<'a> LL | | > | |_________________^ -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:70:30 | LL | Output = impl Nesting<'a> diff --git a/tests/ui/typeck/const-in-fn-call-generics.rs b/tests/ui/typeck/const-in-fn-call-generics.rs new file mode 100644 index 00000000000..675dbcc3054 --- /dev/null +++ b/tests/ui/typeck/const-in-fn-call-generics.rs @@ -0,0 +1,16 @@ +fn generic() {} + +trait Collate { + type Pass; + fn collate(self) -> Self::Pass; +} + +impl Collate for i32 { + type Pass = (); + fn collate(self) -> Self::Pass { + generic::<{ true }>() + //~^ ERROR: mismatched types + } +} + +fn main() {} diff --git a/tests/ui/typeck/const-in-fn-call-generics.stderr b/tests/ui/typeck/const-in-fn-call-generics.stderr new file mode 100644 index 00000000000..12dd454188c --- /dev/null +++ b/tests/ui/typeck/const-in-fn-call-generics.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/const-in-fn-call-generics.rs:11:21 + | +LL | generic::<{ true }>() + | ^^^^ expected `u32`, found `bool` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.rs b/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.rs index 9fc249198d0..92c1999e154 100644 --- a/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.rs +++ b/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.rs @@ -3,16 +3,18 @@ // of an impl fn produces a type mismatch error instead of triggering // a const eval cycle - trait Trait { - fn func() -> [ (); N ]; //~ ERROR the constant `N` is not of type `usize` + fn func() -> [(); N]; + //~^ ERROR: the constant `N` is not of type `usize` + //~| ERROR: mismatched types } struct S {} #[allow(unused_braces)] impl Trait for S { - fn func() -> [ (); { () }] { //~ ERROR mismatched types + fn func() -> [(); { () }] { + //~^ ERROR mismatched types N } } diff --git a/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.stderr b/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.stderr index bff926a2081..bb8025d47a1 100644 --- a/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.stderr +++ b/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.stderr @@ -1,15 +1,21 @@ error[E0308]: mismatched types - --> $DIR/const-in-impl-fn-return-type.rs:15:40 + --> $DIR/const-in-impl-fn-return-type.rs:16:39 | -LL | fn func() -> [ (); { () }] { - | ^^ expected `usize`, found `()` +LL | fn func() -> [(); { () }] { + | ^^ expected `usize`, found `()` error: the constant `N` is not of type `usize` - --> $DIR/const-in-impl-fn-return-type.rs:8:32 + --> $DIR/const-in-impl-fn-return-type.rs:7:32 | -LL | fn func() -> [ (); N ]; - | ^^^^^^^^^ expected `usize`, found `u32` +LL | fn func() -> [(); N]; + | ^^^^^^^ expected `usize`, found `u32` -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/const-in-impl-fn-return-type.rs:7:37 + | +LL | fn func() -> [(); N]; + | ^ expected `usize`, found `u32` + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/uninhabited/uninhabited-patterns.stderr b/tests/ui/uninhabited/uninhabited-patterns.stderr index 4e4aaa93f80..0e1c9d31a73 100644 --- a/tests/ui/uninhabited/uninhabited-patterns.stderr +++ b/tests/ui/uninhabited/uninhabited-patterns.stderr @@ -2,9 +2,9 @@ error: unreachable pattern --> $DIR/uninhabited-patterns.rs:29:9 | LL | Ok(box _) => (), - | ^^^^^^^^^ + | ^^^^^^^^^ matches no values because `NotSoSecretlyEmpty` is uninhabited | - = note: this pattern matches no values because `NotSoSecretlyEmpty` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here --> $DIR/uninhabited-patterns.rs:3:9 | @@ -15,17 +15,17 @@ error: unreachable pattern --> $DIR/uninhabited-patterns.rs:38:9 | LL | Err(Ok(_y)) => (), - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ matches no values because `NotSoSecretlyEmpty` is uninhabited | - = note: this pattern matches no values because `NotSoSecretlyEmpty` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern --> $DIR/uninhabited-patterns.rs:41:15 | LL | while let Some(_y) = foo() { - | ^^^^^^^^ + | ^^^^^^^^ matches no values because `NotSoSecretlyEmpty` is uninhabited | - = note: this pattern matches no values because `NotSoSecretlyEmpty` is uninhabited + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: aborting due to 3 previous errors diff --git a/tests/ui/unpretty/expanded-exhaustive.rs b/tests/ui/unpretty/expanded-exhaustive.rs index 29472df897a..279d723a26c 100644 --- a/tests/ui/unpretty/expanded-exhaustive.rs +++ b/tests/ui/unpretty/expanded-exhaustive.rs @@ -19,7 +19,6 @@ #![feature(never_type)] #![feature(pattern_types)] #![feature(prelude_import)] -#![feature(raw_ref_op)] #![feature(specialization)] #![feature(trace_macros)] #![feature(trait_alias)] diff --git a/tests/ui/unpretty/expanded-exhaustive.stdout b/tests/ui/unpretty/expanded-exhaustive.stdout index cf2f6f8cbaa..149659693ae 100644 --- a/tests/ui/unpretty/expanded-exhaustive.stdout +++ b/tests/ui/unpretty/expanded-exhaustive.stdout @@ -20,7 +20,6 @@ #![feature(never_type)] #![feature(pattern_types)] #![feature(prelude_import)] -#![feature(raw_ref_op)] #![feature(specialization)] #![feature(trace_macros)] #![feature(trait_alias)] diff --git a/tests/ui/unsized/unsized6.stderr b/tests/ui/unsized/unsized6.stderr index 56e7f60f9ff..d406120efc5 100644 --- a/tests/ui/unsized/unsized6.stderr +++ b/tests/ui/unsized/unsized6.stderr @@ -123,6 +123,11 @@ help: consider removing the `?Sized` bound to make the type parameter `Sized` LL - fn f3(x1: Box, x2: Box, x3: Box) { LL + fn f3(x1: Box, x2: Box, x3: Box) { | +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - let y = *x2; +LL + let y = x2; + | error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:26:10 @@ -177,6 +182,11 @@ help: consider removing the `?Sized` bound to make the type parameter `Sized` LL - fn f4(x1: Box, x2: Box, x3: Box) { LL + fn f4(x1: Box, x2: Box, x3: Box) { | +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - let y = *x2; +LL + let y = x2; + | error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:34:10 diff --git a/tests/ui/variance/variance-associated-consts.rs b/tests/ui/variance/variance-associated-consts.rs index 6a44a94df3f..97edb7e266a 100644 --- a/tests/ui/variance/variance-associated-consts.rs +++ b/tests/ui/variance/variance-associated-consts.rs @@ -10,7 +10,7 @@ trait Trait { } #[rustc_variance] -struct Foo { //~ ERROR [o] +struct Foo { //~ ERROR [T: o] field: [u8; ::Const] //~^ ERROR: unconstrained generic constant } diff --git a/tests/ui/variance/variance-associated-consts.stderr b/tests/ui/variance/variance-associated-consts.stderr index b955a7686c2..5c3ed93464a 100644 --- a/tests/ui/variance/variance-associated-consts.stderr +++ b/tests/ui/variance/variance-associated-consts.stderr @@ -9,7 +9,7 @@ help: try adding a `where` bound LL | struct Foo where [(); ::Const]: { | ++++++++++++++++++++++++++++++++ -error: [o] +error: [T: o] --> $DIR/variance-associated-consts.rs:13:1 | LL | struct Foo { diff --git a/tests/ui/variance/variance-associated-types.rs b/tests/ui/variance/variance-associated-types.rs index ecb0821827d..07ff41062e8 100644 --- a/tests/ui/variance/variance-associated-types.rs +++ b/tests/ui/variance/variance-associated-types.rs @@ -10,12 +10,12 @@ trait Trait<'a> { } #[rustc_variance] -struct Foo<'a, T : Trait<'a>> { //~ ERROR [+, +] +struct Foo<'a, T : Trait<'a>> { //~ ERROR ['a: +, T: +] field: (T, &'a ()) } #[rustc_variance] -struct Bar<'a, T : Trait<'a>> { //~ ERROR [o, o] +struct Bar<'a, T : Trait<'a>> { //~ ERROR ['a: o, T: o] field: >::Type } diff --git a/tests/ui/variance/variance-associated-types.stderr b/tests/ui/variance/variance-associated-types.stderr index 70cb246f6e9..ca010b7e7ef 100644 --- a/tests/ui/variance/variance-associated-types.stderr +++ b/tests/ui/variance/variance-associated-types.stderr @@ -1,10 +1,10 @@ -error: [+, +] +error: ['a: +, T: +] --> $DIR/variance-associated-types.rs:13:1 | LL | struct Foo<'a, T : Trait<'a>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [o, o] +error: ['a: o, T: o] --> $DIR/variance-associated-types.rs:18:1 | LL | struct Bar<'a, T : Trait<'a>> { diff --git a/tests/ui/variance/variance-object-types.rs b/tests/ui/variance/variance-object-types.rs index 6ded24cd1e9..fd03dec9824 100644 --- a/tests/ui/variance/variance-object-types.rs +++ b/tests/ui/variance/variance-object-types.rs @@ -4,7 +4,7 @@ // For better or worse, associated types are invariant, and hence we // get an invariant result for `'a`. #[rustc_variance] -struct Foo<'a> { //~ ERROR [o] +struct Foo<'a> { //~ ERROR ['a: o] x: Box &'a i32 + 'static> } diff --git a/tests/ui/variance/variance-object-types.stderr b/tests/ui/variance/variance-object-types.stderr index 963f3454e1b..a6fb9b2403a 100644 --- a/tests/ui/variance/variance-object-types.stderr +++ b/tests/ui/variance/variance-object-types.stderr @@ -1,4 +1,4 @@ -error: [o] +error: ['a: o] --> $DIR/variance-object-types.rs:7:1 | LL | struct Foo<'a> { diff --git a/tests/ui/variance/variance-regions-direct.rs b/tests/ui/variance/variance-regions-direct.rs index f1763c403f1..2bcacec33ea 100644 --- a/tests/ui/variance/variance-regions-direct.rs +++ b/tests/ui/variance/variance-regions-direct.rs @@ -6,7 +6,7 @@ // Regions that just appear in normal spots are contravariant: #[rustc_variance] -struct Test2<'a, 'b, 'c> { //~ ERROR [+, +, +] +struct Test2<'a, 'b, 'c> { //~ ERROR ['a: +, 'b: +, 'c: +] x: &'a isize, y: &'b [isize], c: &'c str @@ -15,7 +15,7 @@ struct Test2<'a, 'b, 'c> { //~ ERROR [+, +, +] // Those same annotations in function arguments become covariant: #[rustc_variance] -struct Test3<'a, 'b, 'c> { //~ ERROR [-, -, -] +struct Test3<'a, 'b, 'c> { //~ ERROR ['a: -, 'b: -, 'c: -] x: extern "Rust" fn(&'a isize), y: extern "Rust" fn(&'b [isize]), c: extern "Rust" fn(&'c str), @@ -24,7 +24,7 @@ struct Test3<'a, 'b, 'c> { //~ ERROR [-, -, -] // Mutability induces invariance: #[rustc_variance] -struct Test4<'a, 'b:'a> { //~ ERROR [+, o] +struct Test4<'a, 'b:'a> { //~ ERROR ['a: +, 'b: o] x: &'a mut &'b isize, } @@ -32,7 +32,7 @@ struct Test4<'a, 'b:'a> { //~ ERROR [+, o] // contravariant context: #[rustc_variance] -struct Test5<'a, 'b:'a> { //~ ERROR [-, o] +struct Test5<'a, 'b:'a> { //~ ERROR ['a: -, 'b: o] x: extern "Rust" fn(&'a mut &'b isize), } @@ -42,14 +42,14 @@ struct Test5<'a, 'b:'a> { //~ ERROR [-, o] // argument list occurs in an invariant context. #[rustc_variance] -struct Test6<'a, 'b:'a> { //~ ERROR [+, o] +struct Test6<'a, 'b:'a> { //~ ERROR ['a: +, 'b: o] x: &'a mut extern "Rust" fn(&'b isize), } // No uses at all is bivariant: #[rustc_variance] -struct Test7<'a> { //~ ERROR [*] +struct Test7<'a> { //~ ERROR ['a: *] //~^ ERROR: `'a` is never used x: isize } @@ -57,7 +57,7 @@ struct Test7<'a> { //~ ERROR [*] // Try enums too. #[rustc_variance] -enum Test8<'a, 'b, 'c:'b> { //~ ERROR [-, +, o] +enum Test8<'a, 'b, 'c:'b> { //~ ERROR ['a: -, 'b: +, 'c: o] Test8A(extern "Rust" fn(&'a isize)), Test8B(&'b [isize]), Test8C(&'b mut &'c str), diff --git a/tests/ui/variance/variance-regions-direct.stderr b/tests/ui/variance/variance-regions-direct.stderr index edfc888f656..45ce0303fb2 100644 --- a/tests/ui/variance/variance-regions-direct.stderr +++ b/tests/ui/variance/variance-regions-direct.stderr @@ -6,43 +6,43 @@ LL | struct Test7<'a> { | = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` -error: [+, +, +] +error: ['a: +, 'b: +, 'c: +] --> $DIR/variance-regions-direct.rs:9:1 | LL | struct Test2<'a, 'b, 'c> { | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: [-, -, -] +error: ['a: -, 'b: -, 'c: -] --> $DIR/variance-regions-direct.rs:18:1 | LL | struct Test3<'a, 'b, 'c> { | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: [+, o] +error: ['a: +, 'b: o] --> $DIR/variance-regions-direct.rs:27:1 | LL | struct Test4<'a, 'b:'a> { | ^^^^^^^^^^^^^^^^^^^^^^^ -error: [-, o] +error: ['a: -, 'b: o] --> $DIR/variance-regions-direct.rs:35:1 | LL | struct Test5<'a, 'b:'a> { | ^^^^^^^^^^^^^^^^^^^^^^^ -error: [+, o] +error: ['a: +, 'b: o] --> $DIR/variance-regions-direct.rs:45:1 | LL | struct Test6<'a, 'b:'a> { | ^^^^^^^^^^^^^^^^^^^^^^^ -error: [*] +error: ['a: *] --> $DIR/variance-regions-direct.rs:52:1 | LL | struct Test7<'a> { | ^^^^^^^^^^^^^^^^ -error: [-, +, o] +error: ['a: -, 'b: +, 'c: o] --> $DIR/variance-regions-direct.rs:60:1 | LL | enum Test8<'a, 'b, 'c:'b> { diff --git a/tests/ui/variance/variance-regions-indirect.rs b/tests/ui/variance/variance-regions-indirect.rs index 31e25641d8c..aaa4d3f8779 100644 --- a/tests/ui/variance/variance-regions-indirect.rs +++ b/tests/ui/variance/variance-regions-indirect.rs @@ -5,7 +5,7 @@ #![feature(rustc_attrs)] #[rustc_variance] -enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR [-, +, o, *] +enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR ['a: -, 'b: +, 'c: o, 'd: *] //~^ ERROR: `'d` is never used Test8A(extern "Rust" fn(&'a isize)), Test8B(&'b [isize]), @@ -13,25 +13,25 @@ enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR [-, +, o, *] } #[rustc_variance] -struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR [*, o, +, -] +struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR ['w: *, 'x: o, 'y: +, 'z: -] //~^ ERROR: `'w` is never used f: Base<'z, 'y, 'x, 'w> } #[rustc_variance] // Combine - and + to yield o -struct Derived2<'a, 'b:'a, 'c> { //~ ERROR [o, o, *] +struct Derived2<'a, 'b:'a, 'c> { //~ ERROR ['a: o, 'b: o, 'c: *] //~^ ERROR: `'c` is never used f: Base<'a, 'a, 'b, 'c> } #[rustc_variance] // Combine + and o to yield o (just pay attention to 'a here) -struct Derived3<'a:'b, 'b, 'c> { //~ ERROR [o, +, *] +struct Derived3<'a:'b, 'b, 'c> { //~ ERROR ['a: o, 'b: +, 'c: *] //~^ ERROR: `'c` is never used f: Base<'a, 'b, 'a, 'c> } #[rustc_variance] // Combine + and * to yield + (just pay attention to 'a here) -struct Derived4<'a, 'b, 'c:'b> { //~ ERROR [-, +, o] +struct Derived4<'a, 'b, 'c:'b> { //~ ERROR ['a: -, 'b: +, 'c: o] f: Base<'a, 'b, 'c, 'a> } diff --git a/tests/ui/variance/variance-regions-indirect.stderr b/tests/ui/variance/variance-regions-indirect.stderr index 901ec0c6a76..ed839b32350 100644 --- a/tests/ui/variance/variance-regions-indirect.stderr +++ b/tests/ui/variance/variance-regions-indirect.stderr @@ -30,31 +30,31 @@ LL | struct Derived3<'a:'b, 'b, 'c> { | = help: consider removing `'c`, referring to it in a field, or using a marker such as `PhantomData` -error: [-, +, o, *] +error: ['a: -, 'b: +, 'c: o, 'd: *] --> $DIR/variance-regions-indirect.rs:8:1 | LL | enum Base<'a, 'b, 'c:'b, 'd> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [*, o, +, -] +error: ['w: *, 'x: o, 'y: +, 'z: -] --> $DIR/variance-regions-indirect.rs:16:1 | LL | struct Derived1<'w, 'x:'y, 'y, 'z> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [o, o, *] +error: ['a: o, 'b: o, 'c: *] --> $DIR/variance-regions-indirect.rs:22:1 | LL | struct Derived2<'a, 'b:'a, 'c> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [o, +, *] +error: ['a: o, 'b: +, 'c: *] --> $DIR/variance-regions-indirect.rs:28:1 | LL | struct Derived3<'a:'b, 'b, 'c> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [-, +, o] +error: ['a: -, 'b: +, 'c: o] --> $DIR/variance-regions-indirect.rs:34:1 | LL | struct Derived4<'a, 'b, 'c:'b> { diff --git a/tests/ui/variance/variance-trait-bounds.rs b/tests/ui/variance/variance-trait-bounds.rs index 25a01b160dd..f86fa2bbef7 100644 --- a/tests/ui/variance/variance-trait-bounds.rs +++ b/tests/ui/variance/variance-trait-bounds.rs @@ -13,24 +13,24 @@ trait Setter { } #[rustc_variance] -struct TestStruct> { //~ ERROR [+, +] +struct TestStruct> { //~ ERROR [U: +, T: +] t: T, u: U } #[rustc_variance] -enum TestEnum> { //~ ERROR [*, +] +enum TestEnum> { //~ ERROR [U: *, T: +] //~^ ERROR: `U` is never used Foo(T) } #[rustc_variance] -struct TestContraStruct> { //~ ERROR [*, +] +struct TestContraStruct> { //~ ERROR [U: *, T: +] //~^ ERROR: `U` is never used t: T } #[rustc_variance] -struct TestBox+Setter> { //~ ERROR [*, +] +struct TestBox+Setter> { //~ ERROR [U: *, T: +] //~^ ERROR: `U` is never used t: T } diff --git a/tests/ui/variance/variance-trait-bounds.stderr b/tests/ui/variance/variance-trait-bounds.stderr index 95ed18c1ad2..49cee3cbeca 100644 --- a/tests/ui/variance/variance-trait-bounds.stderr +++ b/tests/ui/variance/variance-trait-bounds.stderr @@ -25,25 +25,25 @@ LL | struct TestBox+Setter> { = help: consider removing `U`, referring to it in a field, or using a marker such as `PhantomData` = help: if you intended `U` to be a const parameter, use `const U: /* Type */` instead -error: [+, +] +error: [U: +, T: +] --> $DIR/variance-trait-bounds.rs:16:1 | LL | struct TestStruct> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [*, +] +error: [U: *, T: +] --> $DIR/variance-trait-bounds.rs:21:1 | LL | enum TestEnum> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [*, +] +error: [U: *, T: +] --> $DIR/variance-trait-bounds.rs:27:1 | LL | struct TestContraStruct> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [*, +] +error: [U: *, T: +] --> $DIR/variance-trait-bounds.rs:33:1 | LL | struct TestBox+Setter> { diff --git a/tests/ui/variance/variance-trait-object-bound.rs b/tests/ui/variance/variance-trait-object-bound.rs index 11303c46520..ca80c6b6dce 100644 --- a/tests/ui/variance/variance-trait-object-bound.rs +++ b/tests/ui/variance/variance-trait-object-bound.rs @@ -11,7 +11,7 @@ use std::mem; trait T { fn foo(&self); } #[rustc_variance] -struct TOption<'a> { //~ ERROR [+] +struct TOption<'a> { //~ ERROR ['a: +] v: Option>, } diff --git a/tests/ui/variance/variance-trait-object-bound.stderr b/tests/ui/variance/variance-trait-object-bound.stderr index f0471a34619..0af21ec12cc 100644 --- a/tests/ui/variance/variance-trait-object-bound.stderr +++ b/tests/ui/variance/variance-trait-object-bound.stderr @@ -1,4 +1,4 @@ -error: [+] +error: ['a: +] --> $DIR/variance-trait-object-bound.rs:14:1 | LL | struct TOption<'a> { diff --git a/tests/ui/variance/variance-types-bounds.rs b/tests/ui/variance/variance-types-bounds.rs index d1814dd97a0..f4738a2dae1 100644 --- a/tests/ui/variance/variance-types-bounds.rs +++ b/tests/ui/variance/variance-types-bounds.rs @@ -4,24 +4,24 @@ #![feature(rustc_attrs)] #[rustc_variance] -struct TestImm { //~ ERROR [+, +] +struct TestImm { //~ ERROR [A: +, B: +] x: A, y: B, } #[rustc_variance] -struct TestMut { //~ ERROR [+, o] +struct TestMut { //~ ERROR [A: +, B: o] x: A, y: &'static mut B, } #[rustc_variance] -struct TestIndirect { //~ ERROR [+, o] +struct TestIndirect { //~ ERROR [A: +, B: o] m: TestMut } #[rustc_variance] -struct TestIndirect2 { //~ ERROR [o, o] +struct TestIndirect2 { //~ ERROR [A: o, B: o] n: TestMut, m: TestMut } @@ -35,7 +35,7 @@ trait Setter { } #[rustc_variance] -struct TestObject { //~ ERROR [o, o] +struct TestObject { //~ ERROR [A: o, R: o] n: Box+Send>, m: Box+Send>, } diff --git a/tests/ui/variance/variance-types-bounds.stderr b/tests/ui/variance/variance-types-bounds.stderr index bb816443476..408c2ae8d36 100644 --- a/tests/ui/variance/variance-types-bounds.stderr +++ b/tests/ui/variance/variance-types-bounds.stderr @@ -1,28 +1,28 @@ -error: [+, +] +error: [A: +, B: +] --> $DIR/variance-types-bounds.rs:7:1 | LL | struct TestImm { | ^^^^^^^^^^^^^^^^^^^^ -error: [+, o] +error: [A: +, B: o] --> $DIR/variance-types-bounds.rs:13:1 | LL | struct TestMut { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [+, o] +error: [A: +, B: o] --> $DIR/variance-types-bounds.rs:19:1 | LL | struct TestIndirect { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [o, o] +error: [A: o, B: o] --> $DIR/variance-types-bounds.rs:24:1 | LL | struct TestIndirect2 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [o, o] +error: [A: o, R: o] --> $DIR/variance-types-bounds.rs:38:1 | LL | struct TestObject { diff --git a/tests/ui/variance/variance-types.rs b/tests/ui/variance/variance-types.rs index cfc03b75473..aa336d1b424 100644 --- a/tests/ui/variance/variance-types.rs +++ b/tests/ui/variance/variance-types.rs @@ -7,32 +7,32 @@ use std::cell::Cell; // not considered bivariant. #[rustc_variance] -struct InvariantMut<'a,A:'a,B:'a> { //~ ERROR [+, o, o] +struct InvariantMut<'a,A:'a,B:'a> { //~ ERROR ['a: +, A: o, B: o] t: &'a mut (A,B) } #[rustc_variance] -struct InvariantCell { //~ ERROR [o] +struct InvariantCell { //~ ERROR [A: o] t: Cell } #[rustc_variance] -struct InvariantIndirect { //~ ERROR [o] +struct InvariantIndirect { //~ ERROR [A: o] t: InvariantCell } #[rustc_variance] -struct Covariant { //~ ERROR [+] +struct Covariant { //~ ERROR [A: +] t: A, u: fn() -> A } #[rustc_variance] -struct Contravariant { //~ ERROR [-] +struct Contravariant { //~ ERROR [A: -] t: fn(A) } #[rustc_variance] -enum Enum { //~ ERROR [+, -, o] +enum Enum { //~ ERROR [A: +, B: -, C: o] Foo(Covariant), Bar(Contravariant), Zed(Covariant,Contravariant) diff --git a/tests/ui/variance/variance-types.stderr b/tests/ui/variance/variance-types.stderr index 0fda4b8036e..f2a67949425 100644 --- a/tests/ui/variance/variance-types.stderr +++ b/tests/ui/variance/variance-types.stderr @@ -1,34 +1,34 @@ -error: [+, o, o] +error: ['a: +, A: o, B: o] --> $DIR/variance-types.rs:10:1 | LL | struct InvariantMut<'a,A:'a,B:'a> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [o] +error: [A: o] --> $DIR/variance-types.rs:15:1 | LL | struct InvariantCell { | ^^^^^^^^^^^^^^^^^^^^^^^ -error: [o] +error: [A: o] --> $DIR/variance-types.rs:20:1 | LL | struct InvariantIndirect { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [+] +error: [A: +] --> $DIR/variance-types.rs:25:1 | LL | struct Covariant { | ^^^^^^^^^^^^^^^^^^^ -error: [-] +error: [A: -] --> $DIR/variance-types.rs:30:1 | LL | struct Contravariant { | ^^^^^^^^^^^^^^^^^^^^^^^ -error: [+, -, o] +error: [A: +, B: -, C: o] --> $DIR/variance-types.rs:35:1 | LL | enum Enum { diff --git a/triagebot.toml b/triagebot.toml index 33108f743cb..d7bc60e6c6f 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -913,7 +913,7 @@ cc = ["@kobzol"] [assign] warn_non_default_branch = true contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" -users_on_vacation = ["jyn514", "jhpratt", "oli-obk", "michaelwoerister"] +users_on_vacation = ["jyn514", "jhpratt", "oli-obk", "kobzol"] [assign.adhoc_groups] compiler-team = [ @@ -951,6 +951,7 @@ libs = [ "@joboet", "@jhpratt", "@tgross35", + "@thomcc", ] bootstrap = [ "@Mark-Simulacrum", @@ -970,7 +971,6 @@ rustdoc = [ docs = [ "@ehuss", "@GuillaumeGomez", - "@JohnTitor", ] query-system = [ "@cjgillot",