diff options
384 files changed, 5487 insertions, 3609 deletions
diff --git a/.github/workflows/ghcr.yml b/.github/workflows/ghcr.yml index c2c0c11f008..6d050d98cb2 100644 --- a/.github/workflows/ghcr.yml +++ b/.github/workflows/ghcr.yml @@ -53,9 +53,9 @@ jobs: run: | # List of DockerHub images to mirror to ghcr.io images=( - # Mirrored because used by the mingw-check-tidy, which doesn't cache Docker images + # Mirrored because used by the tidy job, which doesn't cache Docker images "ubuntu:22.04" - # Mirrored because used by all linux CI jobs, including mingw-check-tidy + # Mirrored because used by all linux CI jobs, including tidy "moby/buildkit:buildx-stable-1" # Mirrored because used when CI is running inside a Docker container "alpine:3.4" diff --git a/.github/workflows/spellcheck.yml b/.github/workflows/spellcheck.yml new file mode 100644 index 00000000000..7e21bb1b7ff --- /dev/null +++ b/.github/workflows/spellcheck.yml @@ -0,0 +1,23 @@ +# This workflow runs spellcheck job + +name: Spellcheck +on: + pull_request: + branches: + - "**" + +jobs: + spellcheck: + name: run spellchecker + runs-on: ubuntu-latest + steps: + - name: Checkout the source code + uses: actions/checkout@v4 + + - name: check typos + # sync version with src/tools/tidy/src/ext_tool_checks.rs in spellcheck_runner + uses: crate-ci/typos@v1.34.0 + with: + # sync target files with src/tools/tidy/src/ext_tool_checks.rs in check_impl + files: ./compiler ./library ./src/bootstrap ./src/librustdoc + config: ./typos.toml diff --git a/Cargo.lock b/Cargo.lock index da3eb92ece8..7cf10628b00 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -128,9 +128,9 @@ dependencies = [ [[package]] name = "anstyle-svg" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c681338396641f4e32a29f045d0c70950da7207b4376685b51396c481ee36f1a" +checksum = "0a43964079ef399480603125d5afae2b219aceffb77478956e25f17b9bc3435c" dependencies = [ "anstyle", "anstyle-lossy", @@ -204,7 +204,7 @@ dependencies = [ "rustc-hash 2.1.1", "serde", "serde_derive", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -221,9 +221,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "backtrace" @@ -341,9 +341,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.18.1" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "bytecount" @@ -546,7 +546,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -579,7 +579,7 @@ dependencies = [ "rustc_tools_util 0.4.2", "serde", "serde_json", - "syn 2.0.103", + "syn 2.0.104", "tempfile", "termize", "tokio", @@ -673,7 +673,7 @@ dependencies = [ "eyre", "indenter", "once_cell", - "owo-colors 4.2.1", + "owo-colors 4.2.2", "tracing-error", ] @@ -695,7 +695,7 @@ dependencies = [ "nom", "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -705,7 +705,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8b88ea9df13354b55bc7234ebcce36e6ef896aca2e42a15de9e10edce01b427" dependencies = [ "once_cell", - "owo-colors 4.2.1", + "owo-colors 4.2.2", "tracing-core", "tracing-error", ] @@ -922,7 +922,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -933,7 +933,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -959,13 +959,13 @@ version = "0.1.90" [[package]] name = "derive-where" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e73f2692d4bd3cac41dca28934a39894200c9fabf49586d77d0e5954af1d7902" +checksum = "510c292c8cf384b1a340b816a9a6cf2599eb8f566a44949024af88418000c50b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -986,7 +986,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -996,7 +996,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -1008,7 +1008,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -1098,7 +1098,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -1168,12 +1168,12 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" +checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -1378,7 +1378,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -1812,7 +1812,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -1878,9 +1878,9 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] name = "indexmap" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" +checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" dependencies = [ "equivalent", "hashbrown", @@ -2008,7 +2008,7 @@ checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -2152,9 +2152,9 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "libredox" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +checksum = "1580801010e535496706ba011c15f8532df6b42297d2e471fec38ceadd8c0638" dependencies = [ "bitflags", "libc", @@ -2279,7 +2279,7 @@ checksum = "88a9689d8d44bf9964484516275f5cd4c9b59457a6940c1d5d0ecbb94510a36b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -2691,9 +2691,9 @@ checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" [[package]] name = "owo-colors" -version = "4.2.1" +version = "4.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26995317201fa17f3656c36716aed4a7c81743a9634ac4c99c0eeda495db0cec" +checksum = "48dd4f4a2c8405440fd0462561f0e5806bd0f77e86f51c761481bdd4018b545e" [[package]] name = "pad" @@ -2770,9 +2770,9 @@ dependencies = [ [[package]] name = "pest" -version = "2.8.0" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "198db74531d58c70a361c42201efde7e2591e976d518caf7662a47dc5720e7b6" +checksum = "1db05f56d34358a8b1066f67cbb203ee3e7ed2ba674a6263a1d5ec6db2204323" dependencies = [ "memchr", "thiserror 2.0.12", @@ -2781,9 +2781,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.8.0" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d725d9cfd79e87dccc9341a2ef39d1b6f6353d68c4b33c177febbe1a402c97c5" +checksum = "bb056d9e8ea77922845ec74a1c4e8fb17e7c218cc4fc11a15c5d25e189aa40bc" dependencies = [ "pest", "pest_generator", @@ -2791,24 +2791,23 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.8.0" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db7d01726be8ab66ab32f9df467ae8b1148906685bbe75c82d1e65d7f5b3f841" +checksum = "87e404e638f781eb3202dc82db6760c8ae8a1eeef7fb3fa8264b2ef280504966" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] name = "pest_meta" -version = "2.8.0" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9f832470494906d1fca5329f8ab5791cc60beb230c74815dff541cbd2b5ca0" +checksum = "edd1101f170f5903fde0914f899bb503d9ff5271d7ba76bbb70bea63690cc0d5" dependencies = [ - "once_cell", "pest", "sha2", ] @@ -2994,9 +2993,9 @@ dependencies = [ [[package]] name = "r-efi" -version = "5.2.0" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "rand" @@ -3218,14 +3217,14 @@ dependencies = [ [[package]] name = "rustc-build-sysroot" -version = "0.5.8" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16d115ad7e26e0d1337f64ae6598f758194696afc2e9f34c8a6f24582529c3dc" +checksum = "fdb13874a0e55baf4ac3d49d38206aecb31a55b75d6c4d04fd850b53942c8cc8" dependencies = [ "anyhow", - "regex", "rustc_version", "tempfile", + "toml 0.8.23", "walkdir", ] @@ -3814,7 +3813,7 @@ dependencies = [ "fluent-syntax", "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", "unic-langid", ] @@ -3963,7 +3962,7 @@ version = "0.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -4110,7 +4109,7 @@ version = "0.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", "synstructure", ] @@ -4629,6 +4628,7 @@ dependencies = [ "itertools", "rustc_abi", "rustc_ast", + "rustc_attr_data_structures", "rustc_data_structures", "rustc_errors", "rustc_fluent_macro", @@ -4722,7 +4722,7 @@ version = "0.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", "synstructure", ] @@ -4813,7 +4813,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -4950,7 +4950,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -5025,12 +5025,9 @@ checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] name = "slab" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] +checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" [[package]] name = "smallvec" @@ -5190,9 +5187,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.103" +version = "2.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4307e30089d6fd6aff212f2da3a1f9e32f3223b1f010fb09b7c95f90f3ca1e8" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" dependencies = [ "proc-macro2", "quote", @@ -5207,7 +5204,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -5340,7 +5337,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -5351,7 +5348,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -5481,7 +5478,20 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit", + "toml_edit 0.19.15", +] + +[[package]] +name = "toml" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.22.27", ] [[package]] @@ -5507,6 +5517,26 @@ dependencies = [ ] [[package]] +name = "toml_edit" +version = "0.22.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "toml_write", + "winnow 0.7.11", +] + +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + +[[package]] name = "tracing" version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -5520,13 +5550,13 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.29" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1ffbcf9c6f6b99d386e7444eb608ba646ae452a36b39737deb9663b610f662" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -5703,7 +5733,7 @@ checksum = "a1249a628de3ad34b821ecb1001355bca3940bcb2f88558f1a8bd82e977f75b5" dependencies = [ "proc-macro-hack", "quote", - "syn 2.0.103", + "syn 2.0.104", "unic-langid-impl", ] @@ -5915,7 +5945,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", "wasm-bindgen-shared", ] @@ -5937,7 +5967,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -6205,7 +6235,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -6216,7 +6246,7 @@ checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -6227,7 +6257,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -6238,7 +6268,7 @@ checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -6612,9 +6642,9 @@ version = "0.1.1" [[package]] name = "xattr" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d65cbf2f12c15564212d48f4e3dfb87923d25d611f2aed18f4cb23f0413d89e" +checksum = "af3a19837351dc82ba89f8a125e22a3c475f05aba604acc023d62b2739ae2909" dependencies = [ "libc", "rustix", @@ -6670,7 +6700,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", "synstructure", ] @@ -6682,28 +6712,28 @@ checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.25" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.25" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -6723,7 +6753,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", "synstructure", ] @@ -6768,7 +6798,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -6779,5 +6809,5 @@ checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] diff --git a/REUSE.toml b/REUSE.toml index 816c6d730c8..027b4ccbe25 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -36,6 +36,7 @@ path = [ "rustfmt.toml", "rust-bors.toml", "triagebot.toml", + "typos.toml", "x", "x.ps1", "x.py", diff --git a/bootstrap.example.toml b/bootstrap.example.toml index cc1ea796a02..b59f112bdfb 100644 --- a/bootstrap.example.toml +++ b/bootstrap.example.toml @@ -467,6 +467,15 @@ # Whether to use the precompiled stage0 libtest with compiletest. #build.compiletest-use-stage0-libtest = true +# Default value for the `--extra-checks` flag of tidy. +# +# See `./x test tidy --help` for details. +# +# Note that if any value is manually given to bootstrap such as +# `./x test tidy --extra-checks=js`, this value is ignored. +# Use `--extra-checks=''` to temporarily disable all extra checks. +#build.tidy-extra-checks = "" + # Indicates whether ccache is used when building certain artifacts (e.g. LLVM). # Set to `true` to use the first `ccache` in PATH, or set an absolute path to use # a specific version. diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 286bbfb5ae8..ac6daba3901 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1344,7 +1344,7 @@ impl Expr { } } - /// Returns an expression with (when possible) *one* outter brace removed + /// Returns an expression with (when possible) *one* outer brace removed pub fn maybe_unwrap_block(&self) -> &Expr { if let ExprKind::Block(block, None) = &self.kind && let [stmt] = block.stmts.as_slice() @@ -1390,6 +1390,7 @@ impl Expr { path.clone(), TraitBoundModifiers::NONE, self.span, + Parens::No, ))), _ => None, } @@ -3366,6 +3367,13 @@ pub struct TraitRef { pub ref_id: NodeId, } +/// Whether enclosing parentheses are present or not. +#[derive(Clone, Encodable, Decodable, Debug)] +pub enum Parens { + Yes, + No, +} + #[derive(Clone, Encodable, Decodable, Debug)] pub struct PolyTraitRef { /// The `'a` in `for<'a> Foo<&'a T>`. @@ -3378,6 +3386,10 @@ pub struct PolyTraitRef { pub trait_ref: TraitRef, pub span: Span, + + /// When `Yes`, the first and last character of `span` are an opening + /// and a closing paren respectively. + pub parens: Parens, } impl PolyTraitRef { @@ -3386,12 +3398,14 @@ impl PolyTraitRef { path: Path, modifiers: TraitBoundModifiers, span: Span, + parens: Parens, ) -> Self { PolyTraitRef { bound_generic_params: generic_params, modifiers, trait_ref: TraitRef { path, ref_id: DUMMY_NODE_ID }, span, + parens, } } } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index d0c2b2bf68b..42de5b727c5 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -142,7 +142,7 @@ macro_rules! common_visitor_and_walkers { )? // Methods in this trait have one of three forms, with the last two forms - // only occuring on `MutVisitor`: + // only occurring on `MutVisitor`: // // fn visit_t(&mut self, t: &mut T); // common // fn flat_map_t(&mut self, t: T) -> SmallVec<[T; 1]>; // rare @@ -1142,7 +1142,7 @@ macro_rules! common_visitor_and_walkers { vis: &mut V, p: &$($lt)? $($mut)? PolyTraitRef, ) -> V::Result { - let PolyTraitRef { bound_generic_params, modifiers, trait_ref, span } = p; + let PolyTraitRef { bound_generic_params, modifiers, trait_ref, span, parens: _ } = p; try_visit!(visit_modifiers(vis, modifiers)); try_visit!(visit_generic_params(vis, bound_generic_params)); try_visit!(vis.visit_trait_ref(trait_ref)); diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 8acb5105773..bdcb750ba26 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -2,6 +2,7 @@ use rustc_abi::ExternAbi; use rustc_ast::ptr::P; use rustc_ast::visit::AssocCtxt; use rustc_ast::*; +use rustc_attr_data_structures::{AttributeKind, find_attr}; use rustc_errors::{E0570, ErrorGuaranteed, struct_span_code_err}; use rustc_hir::def::{DefKind, PerNS, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId}; @@ -1621,7 +1622,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let safety = self.lower_safety(h.safety, default_safety); // Treat safe `#[target_feature]` functions as unsafe, but also remember that we did so. - let safety = if attrs.iter().any(|attr| attr.has_name(sym::target_feature)) + let safety = if find_attr!(attrs, AttributeKind::TargetFeature { .. }) && safety.is_safe() && !self.tcx.sess.target.is_like_wasm { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 26d7c0cd6d3..d14e27982ef 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1209,6 +1209,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { modifiers: TraitBoundModifiers::NONE, trait_ref: TraitRef { path: path.clone(), ref_id: t.id }, span: t.span, + parens: ast::Parens::No, }, itctx, ); diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index 4290f7b7ede..d58c140c696 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -1,6 +1,6 @@ ast_passes_abi_cannot_be_coroutine = functions with the {$abi} ABI cannot be `{$coroutine_kind_str}` - .suggestion = remove the `{$coroutine_kind_str}` keyword from this definiton + .suggestion = remove the `{$coroutine_kind_str}` keyword from this definition ast_passes_abi_custom_safe_foreign_function = foreign functions with the "custom" ABI cannot be safe diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index c7f41fc3cb1..5d8ee07178d 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -469,7 +469,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { "`if let` guards are experimental", "you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`" ); - gate_all!(let_chains, "`let` expressions in this position are unstable"); gate_all!( async_trait_bounds, "`async` trait bounds are unstable", diff --git a/compiler/rustc_attr_data_structures/src/attributes.rs b/compiler/rustc_attr_data_structures/src/attributes.rs index 6f4cc83fd10..61ef31b8f9f 100644 --- a/compiler/rustc_attr_data_structures/src/attributes.rs +++ b/compiler/rustc_attr_data_structures/src/attributes.rs @@ -198,10 +198,10 @@ pub enum AttributeKind { Align { align: Align, span: Span }, /// Represents `#[rustc_allow_const_fn_unstable]`. - AllowConstFnUnstable(ThinVec<Symbol>), + AllowConstFnUnstable(ThinVec<Symbol>, Span), /// Represents `#[allow_internal_unstable]`. - AllowInternalUnstable(ThinVec<(Symbol, Span)>), + AllowInternalUnstable(ThinVec<(Symbol, Span)>, Span), /// Represents `#[rustc_as_ptr]` (used by the `dangling_pointers_from_temporaries` lint). AsPtr(Span), @@ -309,6 +309,9 @@ pub enum AttributeKind { span: Span, }, + /// Represents `#[target_feature(enable = "...")]` + TargetFeature(ThinVec<(Symbol, Span)>, Span), + /// Represents `#[track_caller]` TrackCaller(Span), diff --git a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs index 58ced8e3281..a1b1d670cfe 100644 --- a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs +++ b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs @@ -42,6 +42,7 @@ impl AttributeKind { RustcLayoutScalarValidRangeStart(..) => Yes, RustcObjectLifetimeDefault => No, SkipDuringMethodDispatch { .. } => No, + TargetFeature(..) => No, TrackCaller(..) => Yes, Used { .. } => No, } diff --git a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs index 21b01a8d071..1c51c3eee4e 100644 --- a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs +++ b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs @@ -13,7 +13,8 @@ pub(crate) struct AllowInternalUnstableParser; impl<S: Stage> CombineAttributeParser<S> for AllowInternalUnstableParser { const PATH: &[Symbol] = &[sym::allow_internal_unstable]; type Item = (Symbol, Span); - const CONVERT: ConvertFn<Self::Item> = AttributeKind::AllowInternalUnstable; + const CONVERT: ConvertFn<Self::Item> = + |items, span| AttributeKind::AllowInternalUnstable(items, span); const TEMPLATE: AttributeTemplate = template!(Word, List: "feat1, feat2, ..."); fn extend<'c>( @@ -30,7 +31,8 @@ pub(crate) struct AllowConstFnUnstableParser; impl<S: Stage> CombineAttributeParser<S> for AllowConstFnUnstableParser { const PATH: &[Symbol] = &[sym::rustc_allow_const_fn_unstable]; type Item = Symbol; - const CONVERT: ConvertFn<Self::Item> = AttributeKind::AllowConstFnUnstable; + const CONVERT: ConvertFn<Self::Item> = + |items, first_span| AttributeKind::AllowConstFnUnstable(items, first_span); const TEMPLATE: AttributeTemplate = template!(Word, List: "feat1, feat2, ..."); fn extend<'c>( diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg.rs b/compiler/rustc_attr_parsing/src/attributes/cfg.rs index f4d23012af7..a8d9229cbc3 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg.rs @@ -14,7 +14,7 @@ use crate::{fluent_generated, parse_version}; /// Emitter of a builtin lint from `cfg_matches`. /// -/// Used to support emiting a lint (currently on check-cfg), either: +/// Used to support emitting a lint (currently on check-cfg), either: /// - as an early buffered lint (in `rustc`) /// - or has a "normal" lint from HIR (in `rustdoc`) pub trait CfgMatchesLintEmitter { diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index 7c412d4fa89..13f560dff38 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -3,7 +3,10 @@ use rustc_feature::{AttributeTemplate, template}; use rustc_session::parse::feature_err; use rustc_span::{Span, Symbol, sym}; -use super::{AcceptMapping, AttributeOrder, AttributeParser, OnDuplicate, SingleAttributeParser}; +use super::{ + AcceptMapping, AttributeOrder, AttributeParser, CombineAttributeParser, ConvertFn, + NoArgsAttributeParser, OnDuplicate, SingleAttributeParser, +}; use crate::context::{AcceptContext, FinalizeContext, Stage}; use crate::parser::ArgParser; use crate::session_diagnostics::{NakedFunctionIncompatibleAttribute, NullOnExport}; @@ -43,20 +46,10 @@ impl<S: Stage> SingleAttributeParser<S> for OptimizeParser { pub(crate) struct ColdParser; -impl<S: Stage> SingleAttributeParser<S> for ColdParser { +impl<S: Stage> NoArgsAttributeParser<S> for ColdParser { const PATH: &[Symbol] = &[sym::cold]; - const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn; - const TEMPLATE: AttributeTemplate = template!(Word); - - fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { - if let Err(span) = args.no_args() { - cx.expected_no_args(span); - return None; - } - - Some(AttributeKind::Cold(cx.attr_span)) - } + const CREATE: fn(Span) -> AttributeKind = AttributeKind::Cold; } pub(crate) struct ExportNameParser; @@ -194,39 +187,17 @@ impl<S: Stage> AttributeParser<S> for NakedParser { } pub(crate) struct TrackCallerParser; - -impl<S: Stage> SingleAttributeParser<S> for TrackCallerParser { +impl<S: Stage> NoArgsAttributeParser<S> for TrackCallerParser { const PATH: &[Symbol] = &[sym::track_caller]; - const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn; - const TEMPLATE: AttributeTemplate = template!(Word); - - fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { - if let Err(span) = args.no_args() { - cx.expected_no_args(span); - return None; - } - - Some(AttributeKind::TrackCaller(cx.attr_span)) - } + const CREATE: fn(Span) -> AttributeKind = AttributeKind::TrackCaller; } pub(crate) struct NoMangleParser; - -impl<S: Stage> SingleAttributeParser<S> for NoMangleParser { - const PATH: &[rustc_span::Symbol] = &[sym::no_mangle]; - const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast; +impl<S: Stage> NoArgsAttributeParser<S> for NoMangleParser { + const PATH: &[Symbol] = &[sym::no_mangle]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn; - const TEMPLATE: AttributeTemplate = template!(Word); - - fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { - if let Err(span) = args.no_args() { - cx.expected_no_args(span); - return None; - } - - Some(AttributeKind::NoMangle(cx.attr_span)) - } + const CREATE: fn(Span) -> AttributeKind = AttributeKind::NoMangle; } #[derive(Default)] @@ -309,3 +280,53 @@ impl<S: Stage> AttributeParser<S> for UsedParser { }) } } + +pub(crate) struct TargetFeatureParser; + +impl<S: Stage> CombineAttributeParser<S> for TargetFeatureParser { + type Item = (Symbol, Span); + const PATH: &[Symbol] = &[sym::target_feature]; + const CONVERT: ConvertFn<Self::Item> = |items, span| AttributeKind::TargetFeature(items, span); + const TEMPLATE: AttributeTemplate = template!(List: "enable = \"feat1, feat2\""); + + fn extend<'c>( + cx: &'c mut AcceptContext<'_, '_, S>, + args: &'c ArgParser<'_>, + ) -> impl IntoIterator<Item = Self::Item> + 'c { + let mut features = Vec::new(); + let ArgParser::List(list) = args else { + cx.expected_list(cx.attr_span); + return features; + }; + for item in list.mixed() { + let Some(name_value) = item.meta_item() else { + cx.expected_name_value(item.span(), Some(sym::enable)); + return features; + }; + + // Validate name + let Some(name) = name_value.path().word_sym() else { + cx.expected_name_value(name_value.path().span(), Some(sym::enable)); + return features; + }; + if name != sym::enable { + cx.expected_name_value(name_value.path().span(), Some(sym::enable)); + return features; + } + + // Use value + let Some(name_value) = name_value.args().name_value() else { + cx.expected_name_value(item.span(), Some(sym::enable)); + return features; + }; + let Some(value_str) = name_value.value_as_str() else { + cx.expected_string_literal(name_value.value_span, Some(name_value.value_as_lit())); + return features; + }; + for feature in value_str.as_str().split(",") { + features.push((Symbol::intern(feature), item.span())); + } + } + features + } +} diff --git a/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs b/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs index 1c8fc5079da..5437803d781 100644 --- a/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs +++ b/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs @@ -1,38 +1,19 @@ use rustc_attr_data_structures::AttributeKind; -use rustc_feature::{AttributeTemplate, template}; -use rustc_span::{Symbol, sym}; +use rustc_span::{Span, Symbol, sym}; -use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser}; -use crate::context::{AcceptContext, Stage}; -use crate::parser::ArgParser; +use crate::attributes::{NoArgsAttributeParser, OnDuplicate}; +use crate::context::Stage; pub(crate) struct AsPtrParser; - -impl<S: Stage> SingleAttributeParser<S> for AsPtrParser { +impl<S: Stage> NoArgsAttributeParser<S> for AsPtrParser { const PATH: &[Symbol] = &[sym::rustc_as_ptr]; - const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; - const TEMPLATE: AttributeTemplate = template!(Word); - - fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { - if let Err(span) = args.no_args() { - cx.expected_no_args(span); - } - Some(AttributeKind::AsPtr(cx.attr_span)) - } + const CREATE: fn(Span) -> AttributeKind = AttributeKind::AsPtr; } pub(crate) struct PubTransparentParser; -impl<S: Stage> SingleAttributeParser<S> for PubTransparentParser { +impl<S: Stage> NoArgsAttributeParser<S> for PubTransparentParser { const PATH: &[Symbol] = &[sym::rustc_pub_transparent]; - const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; - const TEMPLATE: AttributeTemplate = template!(Word); - - fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { - if let Err(span) = args.no_args() { - cx.expected_no_args(span); - } - Some(AttributeKind::PubTransparent(cx.attr_span)) - } + const CREATE: fn(Span) -> AttributeKind = AttributeKind::PubTransparent; } diff --git a/compiler/rustc_attr_parsing/src/attributes/loop_match.rs b/compiler/rustc_attr_parsing/src/attributes/loop_match.rs index f6c7ac5e3a3..80808b90dc6 100644 --- a/compiler/rustc_attr_parsing/src/attributes/loop_match.rs +++ b/compiler/rustc_attr_parsing/src/attributes/loop_match.rs @@ -1,31 +1,19 @@ use rustc_attr_data_structures::AttributeKind; -use rustc_feature::{AttributeTemplate, template}; -use rustc_span::{Symbol, sym}; +use rustc_span::{Span, Symbol, sym}; -use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser}; -use crate::context::{AcceptContext, Stage}; -use crate::parser::ArgParser; +use crate::attributes::{NoArgsAttributeParser, OnDuplicate}; +use crate::context::Stage; pub(crate) struct LoopMatchParser; -impl<S: Stage> SingleAttributeParser<S> for LoopMatchParser { +impl<S: Stage> NoArgsAttributeParser<S> for LoopMatchParser { const PATH: &[Symbol] = &[sym::loop_match]; - const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn; - const TEMPLATE: AttributeTemplate = template!(Word); - - fn convert(cx: &mut AcceptContext<'_, '_, S>, _args: &ArgParser<'_>) -> Option<AttributeKind> { - Some(AttributeKind::LoopMatch(cx.attr_span)) - } + const CREATE: fn(Span) -> AttributeKind = AttributeKind::LoopMatch; } pub(crate) struct ConstContinueParser; -impl<S: Stage> SingleAttributeParser<S> for ConstContinueParser { +impl<S: Stage> NoArgsAttributeParser<S> for ConstContinueParser { const PATH: &[Symbol] = &[sym::const_continue]; - const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn; - const TEMPLATE: AttributeTemplate = template!(Word); - - fn convert(cx: &mut AcceptContext<'_, '_, S>, _args: &ArgParser<'_>) -> Option<AttributeKind> { - Some(AttributeKind::ConstContinue(cx.attr_span)) - } + const CREATE: fn(Span) -> AttributeKind = AttributeKind::ConstContinue; } diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index b3a9c69c055..0215504b52b 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -17,7 +17,7 @@ use std::marker::PhantomData; use rustc_attr_data_structures::AttributeKind; -use rustc_feature::AttributeTemplate; +use rustc_feature::{AttributeTemplate, template}; use rustc_span::{Span, Symbol}; use thin_vec::ThinVec; @@ -229,7 +229,42 @@ pub(crate) enum AttributeOrder { KeepLast, } -type ConvertFn<E> = fn(ThinVec<E>) -> AttributeKind; +/// An even simpler version of [`SingleAttributeParser`]: +/// now automatically check that there are no arguments provided to the attribute. +/// +/// [`WithoutArgs<T> where T: NoArgsAttributeParser`](WithoutArgs) implements [`SingleAttributeParser`]. +// +pub(crate) trait NoArgsAttributeParser<S: Stage>: 'static { + const PATH: &[Symbol]; + const ON_DUPLICATE: OnDuplicate<S>; + + /// Create the [`AttributeKind`] given attribute's [`Span`]. + const CREATE: fn(Span) -> AttributeKind; +} + +pub(crate) struct WithoutArgs<T: NoArgsAttributeParser<S>, S: Stage>(PhantomData<(S, T)>); + +impl<T: NoArgsAttributeParser<S>, S: Stage> Default for WithoutArgs<T, S> { + fn default() -> Self { + Self(Default::default()) + } +} + +impl<T: NoArgsAttributeParser<S>, S: Stage> SingleAttributeParser<S> for WithoutArgs<T, S> { + const PATH: &[Symbol] = T::PATH; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast; + const ON_DUPLICATE: OnDuplicate<S> = T::ON_DUPLICATE; + const TEMPLATE: AttributeTemplate = template!(Word); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { + if let Err(span) = args.no_args() { + cx.expected_no_args(span); + } + Some(T::CREATE(cx.attr_span)) + } +} + +type ConvertFn<E> = fn(ThinVec<E>, Span) -> AttributeKind; /// Alternative to [`AttributeParser`] that automatically handles state management. /// If multiple attributes appear on an element, combines the values of each into a @@ -260,14 +295,21 @@ pub(crate) trait CombineAttributeParser<S: Stage>: 'static { /// Use in combination with [`CombineAttributeParser`]. /// `Combine<T: CombineAttributeParser>` implements [`AttributeParser`]. -pub(crate) struct Combine<T: CombineAttributeParser<S>, S: Stage>( - PhantomData<(S, T)>, - ThinVec<<T as CombineAttributeParser<S>>::Item>, -); +pub(crate) struct Combine<T: CombineAttributeParser<S>, S: Stage> { + phantom: PhantomData<(S, T)>, + /// A list of all items produced by parsing attributes so far. One attribute can produce any amount of items. + items: ThinVec<<T as CombineAttributeParser<S>>::Item>, + /// The full span of the first attribute that was encountered. + first_span: Option<Span>, +} impl<T: CombineAttributeParser<S>, S: Stage> Default for Combine<T, S> { fn default() -> Self { - Self(Default::default(), Default::default()) + Self { + phantom: Default::default(), + items: Default::default(), + first_span: Default::default(), + } } } @@ -275,10 +317,18 @@ impl<T: CombineAttributeParser<S>, S: Stage> AttributeParser<S> for Combine<T, S const ATTRIBUTES: AcceptMapping<Self, S> = &[( T::PATH, <T as CombineAttributeParser<S>>::TEMPLATE, - |group: &mut Combine<T, S>, cx, args| group.1.extend(T::extend(cx, args)), + |group: &mut Combine<T, S>, cx, args| { + // Keep track of the span of the first attribute, for diagnostics + group.first_span.get_or_insert(cx.attr_span); + group.items.extend(T::extend(cx, args)) + }, )]; fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> { - if self.1.is_empty() { None } else { Some(T::CONVERT(self.1)) } + if let Some(first_span) = self.first_span { + Some(T::CONVERT(self.items, first_span)) + } else { + None + } } } diff --git a/compiler/rustc_attr_parsing/src/attributes/repr.rs b/compiler/rustc_attr_parsing/src/attributes/repr.rs index 4aa27043e98..1c070dc2685 100644 --- a/compiler/rustc_attr_parsing/src/attributes/repr.rs +++ b/compiler/rustc_attr_parsing/src/attributes/repr.rs @@ -23,7 +23,7 @@ pub(crate) struct ReprParser; impl<S: Stage> CombineAttributeParser<S> for ReprParser { type Item = (ReprAttr, Span); const PATH: &[Symbol] = &[sym::repr]; - const CONVERT: ConvertFn<Self::Item> = AttributeKind::Repr; + const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::Repr(items); // FIXME(jdonszelmann): never used const TEMPLATE: AttributeTemplate = template!(List: "C | Rust | align(...) | packed(...) | <integer type> | transparent"); diff --git a/compiler/rustc_attr_parsing/src/attributes/semantics.rs b/compiler/rustc_attr_parsing/src/attributes/semantics.rs index 54f50445fbd..74fdff5d2e1 100644 --- a/compiler/rustc_attr_parsing/src/attributes/semantics.rs +++ b/compiler/rustc_attr_parsing/src/attributes/semantics.rs @@ -1,22 +1,12 @@ use rustc_attr_data_structures::AttributeKind; -use rustc_feature::{AttributeTemplate, template}; -use rustc_span::{Symbol, sym}; +use rustc_span::{Span, Symbol, sym}; -use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser}; -use crate::context::{AcceptContext, Stage}; -use crate::parser::ArgParser; +use crate::attributes::{NoArgsAttributeParser, OnDuplicate}; +use crate::context::Stage; pub(crate) struct MayDangleParser; -impl<S: Stage> SingleAttributeParser<S> for MayDangleParser { +impl<S: Stage> NoArgsAttributeParser<S> for MayDangleParser { const PATH: &[Symbol] = &[sym::may_dangle]; - const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn; - const TEMPLATE: AttributeTemplate = template!(Word); - - fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { - if let Err(span) = args.no_args() { - cx.expected_no_args(span); - } - Some(AttributeKind::MayDangle(cx.attr_span)) - } + const CREATE: fn(span: Span) -> AttributeKind = AttributeKind::MayDangle; } diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index 37104855623..6bccd0042a8 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -5,11 +5,12 @@ use rustc_attr_data_structures::{ StableSince, UnstableReason, VERSION_PLACEHOLDER, }; use rustc_errors::ErrorGuaranteed; -use rustc_feature::{AttributeTemplate, template}; +use rustc_feature::template; use rustc_span::{Ident, Span, Symbol, sym}; use super::util::parse_version; -use super::{AcceptMapping, AttributeOrder, AttributeParser, OnDuplicate, SingleAttributeParser}; +use super::{AcceptMapping, AttributeParser, OnDuplicate}; +use crate::attributes::NoArgsAttributeParser; use crate::context::{AcceptContext, FinalizeContext, Stage}; use crate::parser::{ArgParser, MetaItemParser}; use crate::session_diagnostics::{self, UnsupportedLiteralReason}; @@ -132,19 +133,10 @@ impl<S: Stage> AttributeParser<S> for BodyStabilityParser { } pub(crate) struct ConstStabilityIndirectParser; -// FIXME(jdonszelmann): single word attribute group when we have these -impl<S: Stage> SingleAttributeParser<S> for ConstStabilityIndirectParser { +impl<S: Stage> NoArgsAttributeParser<S> for ConstStabilityIndirectParser { const PATH: &[Symbol] = &[sym::rustc_const_stable_indirect]; - const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Ignore; - const TEMPLATE: AttributeTemplate = template!(Word); - - fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { - if let Err(span) = args.no_args() { - cx.expected_no_args(span); - } - Some(AttributeKind::ConstStabilityIndirect) - } + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::ConstStabilityIndirect; } #[derive(Default)] diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index cfba0650932..bf8b1438df7 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -16,8 +16,8 @@ use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym}; use crate::attributes::allow_unstable::{AllowConstFnUnstableParser, AllowInternalUnstableParser}; use crate::attributes::codegen_attrs::{ - ColdParser, ExportNameParser, NakedParser, NoMangleParser, OptimizeParser, TrackCallerParser, - UsedParser, + ColdParser, ExportNameParser, NakedParser, NoMangleParser, OptimizeParser, TargetFeatureParser, + TrackCallerParser, UsedParser, }; use crate::attributes::confusables::ConfusablesParser; use crate::attributes::deprecation::DeprecationParser; @@ -37,7 +37,7 @@ use crate::attributes::stability::{ }; use crate::attributes::traits::SkipDuringMethodDispatchParser; use crate::attributes::transparency::TransparencyParser; -use crate::attributes::{AttributeParser as _, Combine, Single}; +use crate::attributes::{AttributeParser as _, Combine, Single, WithoutArgs}; use crate::parser::{ArgParser, MetaItemParser, PathParser}; use crate::session_diagnostics::{AttributeParseError, AttributeParseErrorReason, UnknownMetaItem}; @@ -58,6 +58,7 @@ macro_rules! attribute_parsers { use super::*; type Combine<T> = super::Combine<T, Early>; type Single<T> = super::Single<T, Early>; + type WithoutArgs<T> = super::WithoutArgs<T, Early>; attribute_parsers!(@[Early] pub(crate) static $name = [$($names),*];); } @@ -65,6 +66,7 @@ macro_rules! attribute_parsers { use super::*; type Combine<T> = super::Combine<T, Late>; type Single<T> = super::Single<T, Late>; + type WithoutArgs<T> = super::WithoutArgs<T, Late>; attribute_parsers!(@[Late] pub(crate) static $name = [$($names),*];); } @@ -116,31 +118,32 @@ attribute_parsers!( Combine<AllowConstFnUnstableParser>, Combine<AllowInternalUnstableParser>, Combine<ReprParser>, + Combine<TargetFeatureParser>, // tidy-alphabetical-end // tidy-alphabetical-start - Single<AsPtrParser>, - Single<ColdParser>, - Single<ConstContinueParser>, - Single<ConstStabilityIndirectParser>, Single<DeprecationParser>, Single<ExportNameParser>, Single<InlineParser>, Single<LinkNameParser>, Single<LinkSectionParser>, - Single<LoopMatchParser>, - Single<MayDangleParser>, Single<MustUseParser>, - Single<NoMangleParser>, Single<OptimizeParser>, - Single<PubTransparentParser>, Single<RustcForceInlineParser>, Single<RustcLayoutScalarValidRangeEnd>, Single<RustcLayoutScalarValidRangeStart>, Single<RustcObjectLifetimeDefaultParser>, Single<SkipDuringMethodDispatchParser>, - Single<TrackCallerParser>, Single<TransparencyParser>, + Single<WithoutArgs<AsPtrParser>>, + Single<WithoutArgs<ColdParser>>, + Single<WithoutArgs<ConstContinueParser>>, + Single<WithoutArgs<ConstStabilityIndirectParser>>, + Single<WithoutArgs<LoopMatchParser>>, + Single<WithoutArgs<MayDangleParser>>, + Single<WithoutArgs<NoMangleParser>>, + Single<WithoutArgs<PubTransparentParser>>, + Single<WithoutArgs<TrackCallerParser>>, // tidy-alphabetical-end ]; ); @@ -187,7 +190,7 @@ impl Stage for Late { } } -/// used when parsing attributes for miscelaneous things *before* ast lowering +/// used when parsing attributes for miscellaneous things *before* ast lowering pub struct Early; /// used when parsing attributes during ast lowering pub struct Late; diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs index df1b1eb60e1..c7844778332 100644 --- a/compiler/rustc_builtin_macros/src/autodiff.rs +++ b/compiler/rustc_builtin_macros/src/autodiff.rs @@ -562,7 +562,7 @@ mod llvm_enzyme { /// so instead we manually build something that should pass the type checker. /// We also add a inline_asm line, as one more barrier for rustc to prevent inlining /// or const propagation. inline_asm will also triggers an Enzyme crash if due to another - /// bug would ever try to accidentially differentiate this placeholder function body. + /// bug would ever try to accidentally differentiate this placeholder function body. /// Finally, we also add back_box usages of all input arguments, to prevent rustc /// from optimizing any arguments away. fn gen_enzyme_body( @@ -606,7 +606,7 @@ mod llvm_enzyme { return body; } - // Everything from here onwards just tries to fullfil the return type. Fun! + // Everything from here onwards just tries to fulfil the return type. Fun! // having an active-only return means we'll drop the original return type. // So that can be treated identical to not having one in the first place. diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 9930eae3fe7..776658b9cca 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -107,7 +107,7 @@ fn call_simple_intrinsic<'ll, 'tcx>( sym::minimumf32 => ("llvm.minimum", &[bx.type_f32()]), sym::minimumf64 => ("llvm.minimum", &[bx.type_f64()]), // There are issues on x86_64 and aarch64 with the f128 variant, - // let's instead use the instrinsic fallback body. + // let's instead use the intrinsic fallback body. // sym::minimumf128 => ("llvm.minimum", &[cx.type_f128()]), sym::maxnumf16 => ("llvm.maxnum", &[bx.type_f16()]), sym::maxnumf32 => ("llvm.maxnum", &[bx.type_f32()]), @@ -118,7 +118,7 @@ fn call_simple_intrinsic<'ll, 'tcx>( sym::maximumf32 => ("llvm.maximum", &[bx.type_f32()]), sym::maximumf64 => ("llvm.maximum", &[bx.type_f64()]), // There are issues on x86_64 and aarch64 with the f128 variant, - // let's instead use the instrinsic fallback body. + // let's instead use the intrinsic fallback body. // sym::maximumf128 => ("llvm.maximum", &[cx.type_f128()]), sym::copysignf16 => ("llvm.copysign", &[bx.type_f16()]), sym::copysignf32 => ("llvm.copysign", &[bx.type_f32()]), diff --git a/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs index b94716b89d6..7b00b2da6ba 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs @@ -40,7 +40,7 @@ unsafe extern "C" { pub(crate) fn LLVMDumpValue(V: &Value); pub(crate) fn LLVMGetFunctionCallConv(F: &Value) -> c_uint; pub(crate) fn LLVMGetReturnType(T: &Type) -> &Type; - pub(crate) fn LLVMGetParams(Fnc: &Value, parms: *mut &Value); + pub(crate) fn LLVMGetParams(Fnc: &Value, params: *mut &Value); pub(crate) fn LLVMGetNamedFunction(M: &Module, Name: *const c_char) -> Option<&Value>; } diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs index 236568590be..4fe4c9bcbf2 100644 --- a/compiler/rustc_codegen_llvm/src/va_arg.rs +++ b/compiler/rustc_codegen_llvm/src/va_arg.rs @@ -861,7 +861,7 @@ fn emit_xtensa_va_arg<'ll, 'tcx>( // On big-endian, for values smaller than the slot size we'd have to align the read to the end // of the slot rather than the start. While the ISA and GCC support big-endian, all the Xtensa - // targets supported by rustc are litte-endian so don't worry about it. + // targets supported by rustc are little-endian so don't worry about it. // if from_regsave { // unsafe { *regsave_value_ptr } diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index 84d63819343..63e9005da45 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -62,6 +62,10 @@ codegen_ssa_failed_to_get_layout = failed to get layout for {$ty}: {$err} codegen_ssa_failed_to_write = failed to write {$path}: {$error} +codegen_ssa_feature_not_valid = the feature named `{$feature}` is not valid for this target + .label = `{$feature}` is not valid for this target + .help = consider removing the leading `+` in the feature name + codegen_ssa_field_associated_value_expected = associated value expected for `{$name}` codegen_ssa_forbidden_ctarget_feature = @@ -289,7 +293,7 @@ codegen_ssa_thorin_missing_referenced_unit = unit {$unit} referenced by executab codegen_ssa_thorin_missing_required_section = input object missing required section `{$section}` -codegen_ssa_thorin_mixed_input_encodings = input objects haved mixed encodings +codegen_ssa_thorin_mixed_input_encodings = input objects have mixed encodings codegen_ssa_thorin_multiple_debug_info_section = multiple `.debug_info.dwo` sections diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 4a2425967e4..343cb0eeca9 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2767,7 +2767,7 @@ fn add_upstream_rust_crates( if sess.target.is_like_aix { // Unlike ELF linkers, AIX doesn't feature `DT_SONAME` to override - // the dependency name when outputing a shared library. Thus, `ld` will + // the dependency name when outputting a shared library. Thus, `ld` will // use the full path to shared libraries as the dependency if passed it // by default unless `noipath` is passed. // https://www.ibm.com/docs/en/aix/7.3?topic=l-ld-command. @@ -3051,7 +3051,7 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo // Supported architecture names can be found in the source: // https://github.com/apple-oss-distributions/ld64/blob/ld64-951.9/src/abstraction/MachOFileAbstraction.hpp#L578-L648 // - // Intentially verbose to ensure that the list always matches correctly + // Intentionally verbose to ensure that the list always matches correctly // with the list in the source above. let ld64_arch = match llvm_arch { "armv7k" => "armv7k", @@ -3118,7 +3118,7 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo // We do not currently know the actual SDK version though, so we have a few options: // 1. Use the minimum version supported by rustc. // 2. Use the same as the deployment target. - // 3. Use an arbitary recent version. + // 3. Use an arbitrary recent version. // 4. Omit the version. // // The first option is too low / too conservative, and means that users will not get the diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index d091c46d9c1..bf38c02e908 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -301,7 +301,7 @@ pub(super) fn elf_e_flags(architecture: Architecture, sess: &Session) -> u32 { "n32" if !is_32bit => e_flags |= elf::EF_MIPS_ABI2, "n64" if !is_32bit => {} "" if is_32bit => e_flags |= elf::EF_MIPS_ABI_O32, - "" => sess.dcx().fatal("LLVM ABI must be specifed for 64-bit MIPS targets"), + "" => sess.dcx().fatal("LLVM ABI must be specified for 64-bit MIPS targets"), s if is_32bit => { sess.dcx().fatal(format!("invalid LLVM ABI `{}` for 32-bit MIPS target", s)) } diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 6e2143858de..2713ec07f97 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -141,6 +141,49 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { }); } } + AttributeKind::TargetFeature(features, attr_span) => { + let Some(sig) = tcx.hir_node_by_def_id(did).fn_sig() else { + tcx.dcx().span_delayed_bug(*attr_span, "target_feature applied to non-fn"); + continue; + }; + let safe_target_features = + matches!(sig.header.safety, hir::HeaderSafety::SafeTargetFeatures); + codegen_fn_attrs.safe_target_features = safe_target_features; + if safe_target_features { + if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc { + // The `#[target_feature]` attribute is allowed on + // WebAssembly targets on all functions. Prior to stabilizing + // the `target_feature_11` feature, `#[target_feature]` was + // only permitted on unsafe functions because on most targets + // execution of instructions that are not supported is + // considered undefined behavior. For WebAssembly which is a + // 100% safe target at execution time it's not possible to + // execute undefined instructions, and even if a future + // feature was added in some form for this it would be a + // deterministic trap. There is no undefined behavior when + // executing WebAssembly so `#[target_feature]` is allowed + // on safe functions (but again, only for WebAssembly) + // + // Note that this is also allowed if `actually_rustdoc` so + // if a target is documenting some wasm-specific code then + // it's not spuriously denied. + // + // Now that `#[target_feature]` is permitted on safe functions, + // this exception must still exist for allowing the attribute on + // `main`, `start`, and other functions that are not usually + // allowed. + } else { + check_target_feature_trait_unsafe(tcx, did, *attr_span); + } + } + from_target_feature_attr( + tcx, + did, + features, + rust_target_features, + &mut codegen_fn_attrs.target_features, + ); + } AttributeKind::TrackCaller(attr_span) => { let is_closure = tcx.is_closure_like(did.to_def_id()); @@ -190,49 +233,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL } sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL, - sym::target_feature => { - let Some(sig) = tcx.hir_node_by_def_id(did).fn_sig() else { - tcx.dcx().span_delayed_bug(attr.span(), "target_feature applied to non-fn"); - continue; - }; - let safe_target_features = - matches!(sig.header.safety, hir::HeaderSafety::SafeTargetFeatures); - codegen_fn_attrs.safe_target_features = safe_target_features; - if safe_target_features { - if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc { - // The `#[target_feature]` attribute is allowed on - // WebAssembly targets on all functions. Prior to stabilizing - // the `target_feature_11` feature, `#[target_feature]` was - // only permitted on unsafe functions because on most targets - // execution of instructions that are not supported is - // considered undefined behavior. For WebAssembly which is a - // 100% safe target at execution time it's not possible to - // execute undefined instructions, and even if a future - // feature was added in some form for this it would be a - // deterministic trap. There is no undefined behavior when - // executing WebAssembly so `#[target_feature]` is allowed - // on safe functions (but again, only for WebAssembly) - // - // Note that this is also allowed if `actually_rustdoc` so - // if a target is documenting some wasm-specific code then - // it's not spuriously denied. - // - // Now that `#[target_feature]` is permitted on safe functions, - // this exception must still exist for allowing the attribute on - // `main`, `start`, and other functions that are not usually - // allowed. - } else { - check_target_feature_trait_unsafe(tcx, did, attr.span()); - } - } - from_target_feature_attr( - tcx, - did, - attr, - rust_target_features, - &mut codegen_fn_attrs.target_features, - ); - } sym::linkage => { if let Some(val) = attr.value_str() { let linkage = Some(linkage_by_name(tcx, did, val.as_str())); @@ -536,10 +536,10 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { .map(|features| (features.name.as_str(), true)) .collect(), ) { - let span = tcx - .get_attrs(did, sym::target_feature) - .next() - .map_or_else(|| tcx.def_span(did), |a| a.span()); + let span = + find_attr!(tcx.get_all_attrs(did), AttributeKind::TargetFeature(_, span) => *span) + .unwrap_or_else(|| tcx.def_span(did)); + tcx.dcx() .create_err(errors::TargetFeatureDisableOrEnable { features, diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 1950a35b364..086c069745c 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -1292,3 +1292,14 @@ pub(crate) struct NoMangleNameless { pub span: Span, pub definition: String, } + +#[derive(Diagnostic)] +#[diag(codegen_ssa_feature_not_valid)] +pub(crate) struct FeatureNotValid<'a> { + pub feature: &'a str, + #[primary_span] + #[label] + pub span: Span, + #[help] + pub plus_hint: bool, +} diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 7ef04213d32..60cf4e28b5a 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -1117,7 +1117,7 @@ pub(super) fn transmute_immediate<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // While optimizations will remove no-op transmutes, they might still be // there in debug or things that aren't no-op in MIR because they change // the Rust type but not the underlying layout/niche. - if from_scalar == to_scalar { + if from_scalar == to_scalar && from_backend_ty == to_backend_ty { return imm; } @@ -1136,13 +1136,7 @@ pub(super) fn transmute_immediate<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( assume_scalar_range(bx, imm, from_scalar, from_backend_ty); imm = match (from_scalar.primitive(), to_scalar.primitive()) { - (Int(..) | Float(_), Int(..) | Float(_)) => { - if from_backend_ty == to_backend_ty { - imm - } else { - bx.bitcast(imm, to_backend_ty) - } - } + (Int(..) | Float(_), Int(..) | Float(_)) => bx.bitcast(imm, to_backend_ty), (Pointer(..), Pointer(..)) => bx.pointercast(imm, to_backend_ty), (Int(..), Pointer(..)) => bx.ptradd(bx.const_null(bx.type_ptr()), imm), (Pointer(..), Int(..)) => { diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index 67ac619091b..53df99993f0 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -1,8 +1,6 @@ use rustc_attr_data_structures::InstructionSetAttr; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_data_structures::unord::{UnordMap, UnordSet}; -use rustc_errors::Applicability; -use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; use rustc_middle::middle::codegen_fn_attrs::TargetFeature; @@ -12,110 +10,85 @@ use rustc_session::Session; use rustc_session::lint::builtin::AARCH64_SOFTFLOAT_NEON; use rustc_session::parse::feature_err; use rustc_span::{Span, Symbol, sym}; -use rustc_target::target_features::{self, RUSTC_SPECIFIC_FEATURES, Stability}; +use rustc_target::target_features::{RUSTC_SPECIFIC_FEATURES, Stability}; use smallvec::SmallVec; -use crate::errors; +use crate::errors::FeatureNotValid; +use crate::{errors, target_features}; /// Compute the enabled target features from the `#[target_feature]` function attribute. /// Enabled target features are added to `target_features`. pub(crate) fn from_target_feature_attr( tcx: TyCtxt<'_>, did: LocalDefId, - attr: &hir::Attribute, + features: &[(Symbol, Span)], rust_target_features: &UnordMap<String, target_features::Stability>, target_features: &mut Vec<TargetFeature>, ) { - let Some(list) = attr.meta_item_list() else { return }; - let bad_item = |span| { - let msg = "malformed `target_feature` attribute input"; - let code = "enable = \"..\""; - tcx.dcx() - .struct_span_err(span, msg) - .with_span_suggestion(span, "must be of the form", code, Applicability::HasPlaceholders) - .emit(); - }; let rust_features = tcx.features(); let abi_feature_constraints = tcx.sess.target.abi_required_features(); - for item in list { - // Only `enable = ...` is accepted in the meta-item list. - if !item.has_name(sym::enable) { - bad_item(item.span()); - continue; - } - - // Must be of the form `enable = "..."` (a string). - let Some(value) = item.value_str() else { - bad_item(item.span()); + for &(feature, feature_span) in features { + let feature_str = feature.as_str(); + let Some(stability) = rust_target_features.get(feature_str) else { + let plus_hint = feature_str + .strip_prefix('+') + .is_some_and(|stripped| rust_target_features.contains_key(stripped)); + tcx.dcx().emit_err(FeatureNotValid { + feature: feature_str, + span: feature_span, + plus_hint, + }); continue; }; - // We allow comma separation to enable multiple features. - for feature in value.as_str().split(',') { - let Some(stability) = rust_target_features.get(feature) else { - let msg = format!("the feature named `{feature}` is not valid for this target"); - let mut err = tcx.dcx().struct_span_err(item.span(), msg); - err.span_label(item.span(), format!("`{feature}` is not valid for this target")); - if let Some(stripped) = feature.strip_prefix('+') { - let valid = rust_target_features.contains_key(stripped); - if valid { - err.help("consider removing the leading `+` in the feature name"); - } - } - err.emit(); - continue; - }; - - // Only allow target features whose feature gates have been enabled - // and which are permitted to be toggled. - if let Err(reason) = stability.toggle_allowed() { - tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr { - span: item.span(), - feature, - reason, - }); - } else if let Some(nightly_feature) = stability.requires_nightly() - && !rust_features.enabled(nightly_feature) - { - feature_err( - &tcx.sess, - nightly_feature, - item.span(), - format!("the target feature `{feature}` is currently unstable"), - ) - .emit(); - } else { - // Add this and the implied features. - let feature_sym = Symbol::intern(feature); - for &name in tcx.implied_target_features(feature_sym) { - // But ensure the ABI does not forbid enabling this. - // Here we do assume that the backend doesn't add even more implied features - // we don't know about, at least no features that would have ABI effects! - // We skip this logic in rustdoc, where we want to allow all target features of - // all targets, so we can't check their ABI compatibility and anyway we are not - // generating code so "it's fine". - if !tcx.sess.opts.actually_rustdoc { - if abi_feature_constraints.incompatible.contains(&name.as_str()) { - // For "neon" specifically, we emit an FCW instead of a hard error. - // See <https://github.com/rust-lang/rust/issues/134375>. - if tcx.sess.target.arch == "aarch64" && name.as_str() == "neon" { - tcx.emit_node_span_lint( - AARCH64_SOFTFLOAT_NEON, - tcx.local_def_id_to_hir_id(did), - item.span(), - errors::Aarch64SoftfloatNeon, - ); - } else { - tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr { - span: item.span(), - feature: name.as_str(), - reason: "this feature is incompatible with the target ABI", - }); - } + // Only allow target features whose feature gates have been enabled + // and which are permitted to be toggled. + if let Err(reason) = stability.toggle_allowed() { + tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr { + span: feature_span, + feature: feature_str, + reason, + }); + } else if let Some(nightly_feature) = stability.requires_nightly() + && !rust_features.enabled(nightly_feature) + { + feature_err( + &tcx.sess, + nightly_feature, + feature_span, + format!("the target feature `{feature}` is currently unstable"), + ) + .emit(); + } else { + // Add this and the implied features. + for &name in tcx.implied_target_features(feature) { + // But ensure the ABI does not forbid enabling this. + // Here we do assume that the backend doesn't add even more implied features + // we don't know about, at least no features that would have ABI effects! + // We skip this logic in rustdoc, where we want to allow all target features of + // all targets, so we can't check their ABI compatibility and anyway we are not + // generating code so "it's fine". + if !tcx.sess.opts.actually_rustdoc { + if abi_feature_constraints.incompatible.contains(&name.as_str()) { + // For "neon" specifically, we emit an FCW instead of a hard error. + // See <https://github.com/rust-lang/rust/issues/134375>. + if tcx.sess.target.arch == "aarch64" && name.as_str() == "neon" { + tcx.emit_node_span_lint( + AARCH64_SOFTFLOAT_NEON, + tcx.local_def_id_to_hir_id(did), + feature_span, + errors::Aarch64SoftfloatNeon, + ); + } else { + tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr { + span: feature_span, + feature: name.as_str(), + reason: "this feature is incompatible with the target ABI", + }); } } - target_features.push(TargetFeature { name, implied: name != feature_sym }) } + target_features.push(TargetFeature { name, implied: name != feature }) } } } @@ -457,7 +430,7 @@ pub(crate) fn provide(providers: &mut Providers) { // one, just keep it. } _ => { - // Overwrite stabilite. + // Overwrite stability. occupied_entry.insert(stability); } } diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index d19de6f5d26..9d367748c2a 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -87,7 +87,7 @@ pub trait BuilderMethods<'a, 'tcx>: // // This function is opt-in for back ends. // - // The default implementation calls `self.expect()` before emiting the branch + // The default implementation calls `self.expect()` before emitting the branch // by calling `self.cond_br()` fn cond_br_with_expect( &mut self, diff --git a/compiler/rustc_const_eval/src/check_consts/mod.rs b/compiler/rustc_const_eval/src/check_consts/mod.rs index d8421415225..9ab8e0692e1 100644 --- a/compiler/rustc_const_eval/src/check_consts/mod.rs +++ b/compiler/rustc_const_eval/src/check_consts/mod.rs @@ -82,7 +82,7 @@ pub fn rustc_allow_const_fn_unstable( ) -> bool { let attrs = tcx.hir_attrs(tcx.local_def_id_to_hir_id(def_id)); - attrs::find_attr!(attrs, attrs::AttributeKind::AllowConstFnUnstable(syms) if syms.contains(&feature_gate)) + attrs::find_attr!(attrs, attrs::AttributeKind::AllowConstFnUnstable(syms, _) if syms.contains(&feature_gate)) } /// Returns `true` if the given `def_id` (trait or function) is "safe to expose on stable". diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 317b1229a90..76fa744361a 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -10,7 +10,7 @@ use rustc_hir::{self as hir, CRATE_HIR_ID, LangItem}; use rustc_middle::mir::AssertMessage; use rustc_middle::mir::interpret::ReportedErrorInfo; use rustc_middle::query::TyCtxtAt; -use rustc_middle::ty::layout::{HasTypingEnv, TyAndLayout}; +use rustc_middle::ty::layout::{HasTypingEnv, TyAndLayout, ValidityRequirement}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::{bug, mir}; use rustc_span::{Span, Symbol, sym}; @@ -23,8 +23,8 @@ use crate::fluent_generated as fluent; use crate::interpret::{ self, AllocId, AllocInit, AllocRange, ConstAllocation, CtfeProvenance, FnArg, Frame, GlobalAlloc, ImmTy, InterpCx, InterpResult, OpTy, PlaceTy, Pointer, RangeSet, Scalar, - compile_time_machine, interp_ok, throw_exhaust, throw_inval, throw_ub, throw_ub_custom, - throw_unsup, throw_unsup_format, + compile_time_machine, err_inval, interp_ok, throw_exhaust, throw_inval, throw_ub, + throw_ub_custom, throw_unsup, throw_unsup_format, }; /// When hitting this many interpreted terminators we emit a deny by default lint @@ -462,6 +462,44 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { // (We know the value here in the machine of course, but this is the runtime of that code, // not the optimization stage.) sym::is_val_statically_known => ecx.write_scalar(Scalar::from_bool(false), dest)?, + + // We handle these here since Miri does not want to have them. + sym::assert_inhabited + | sym::assert_zero_valid + | sym::assert_mem_uninitialized_valid => { + let ty = instance.args.type_at(0); + let requirement = ValidityRequirement::from_intrinsic(intrinsic_name).unwrap(); + + let should_panic = !ecx + .tcx + .check_validity_requirement((requirement, ecx.typing_env().as_query_input(ty))) + .map_err(|_| err_inval!(TooGeneric))?; + + if should_panic { + let layout = ecx.layout_of(ty)?; + + let msg = match requirement { + // For *all* intrinsics we first check `is_uninhabited` to give a more specific + // error message. + _ if layout.is_uninhabited() => format!( + "aborted execution: attempted to instantiate uninhabited type `{ty}`" + ), + ValidityRequirement::Inhabited => bug!("handled earlier"), + ValidityRequirement::Zero => format!( + "aborted execution: attempted to zero-initialize type `{ty}`, which is invalid" + ), + ValidityRequirement::UninitMitigated0x01Fill => format!( + "aborted execution: attempted to leave type `{ty}` uninitialized, which is invalid" + ), + ValidityRequirement::Uninit => bug!("assert_uninit_valid doesn't exist"), + }; + + Self::panic_nounwind(ecx, &msg)?; + // Skip the `return_to_block` at the end (we panicked, we do not return). + return interp_ok(None); + } + } + _ => { // We haven't handled the intrinsic, let's see if we can use a fallback body. if ecx.tcx.intrinsic(instance.def_id()).unwrap().must_be_overridden { diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index d7cede71293..378ed6d0e10 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -7,7 +7,7 @@ use std::assert_matches::assert_matches; use rustc_abi::Size; use rustc_apfloat::ieee::{Double, Half, Quad, Single}; use rustc_middle::mir::{self, BinOp, ConstValue, NonDivergingIntrinsic}; -use rustc_middle::ty::layout::{TyAndLayout, ValidityRequirement}; +use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{Ty, TyCtxt}; use rustc_middle::{bug, ty}; use rustc_span::{Symbol, sym}; @@ -17,8 +17,8 @@ use super::memory::MemoryKind; use super::util::ensure_monomorphic_enough; use super::{ Allocation, CheckInAllocMsg, ConstAllocation, ImmTy, InterpCx, InterpResult, Machine, OpTy, - PlaceTy, Pointer, PointerArithmetic, Provenance, Scalar, err_inval, err_ub_custom, - err_unsup_format, interp_ok, throw_inval, throw_ub_custom, throw_ub_format, + PlaceTy, Pointer, PointerArithmetic, Provenance, Scalar, err_ub_custom, err_unsup_format, + interp_ok, throw_inval, throw_ub_custom, throw_ub_format, }; use crate::fluent_generated as fluent; @@ -372,41 +372,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { self.exact_div(&val, &size, dest)?; } - sym::assert_inhabited - | sym::assert_zero_valid - | sym::assert_mem_uninitialized_valid => { - let ty = instance.args.type_at(0); - let requirement = ValidityRequirement::from_intrinsic(intrinsic_name).unwrap(); - - let should_panic = !self - .tcx - .check_validity_requirement((requirement, self.typing_env.as_query_input(ty))) - .map_err(|_| err_inval!(TooGeneric))?; - - if should_panic { - let layout = self.layout_of(ty)?; - - let msg = match requirement { - // For *all* intrinsics we first check `is_uninhabited` to give a more specific - // error message. - _ if layout.is_uninhabited() => format!( - "aborted execution: attempted to instantiate uninhabited type `{ty}`" - ), - ValidityRequirement::Inhabited => bug!("handled earlier"), - ValidityRequirement::Zero => format!( - "aborted execution: attempted to zero-initialize type `{ty}`, which is invalid" - ), - ValidityRequirement::UninitMitigated0x01Fill => format!( - "aborted execution: attempted to leave type `{ty}` uninitialized, which is invalid" - ), - ValidityRequirement::Uninit => bug!("assert_uninit_valid doesn't exist"), - }; - - M::panic_nounwind(self, &msg)?; - // Skip the `return_to_block` at the end (we panicked, we do not return). - return interp_ok(true); - } - } sym::simd_insert => { let index = u64::from(self.read_scalar(&args[1])?.to_u32()?); let elem = &args[2]; diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 3b36bb85985..ff822b52a8d 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -655,7 +655,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// The caller is responsible for calling the access hooks! /// /// You almost certainly want to use `get_ptr_alloc`/`get_ptr_alloc_mut` instead. - fn get_alloc_raw( + pub fn get_alloc_raw( &self, id: AllocId, ) -> InterpResult<'tcx, &Allocation<M::Provenance, M::AllocExtra, M::Bytes>> { @@ -757,7 +757,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// /// Also returns a ptr to `self.extra` so that the caller can use it in parallel with the /// allocation. - fn get_alloc_raw_mut( + /// + /// You almost certainly want to use `get_ptr_alloc`/`get_ptr_alloc_mut` instead. + pub fn get_alloc_raw_mut( &mut self, id: AllocId, ) -> InterpResult<'tcx, (&mut Allocation<M::Provenance, M::AllocExtra, M::Bytes>, &mut M)> { @@ -976,15 +978,15 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { interp_ok(()) } - /// Handle the effect an FFI call might have on the state of allocations. - /// This overapproximates the modifications which external code might make to memory: - /// We set all reachable allocations as initialized, mark all reachable provenances as exposed - /// and overwrite them with `Provenance::WILDCARD`. - /// - /// The allocations in `ids` are assumed to be already exposed. - pub fn prepare_for_native_call(&mut self, ids: Vec<AllocId>) -> InterpResult<'tcx> { + /// Visit all allocations reachable from the given start set, by recursively traversing the + /// provenance information of those allocations. + pub fn visit_reachable_allocs( + &mut self, + start: Vec<AllocId>, + mut visit: impl FnMut(&mut Self, AllocId, &AllocInfo) -> InterpResult<'tcx>, + ) -> InterpResult<'tcx> { let mut done = FxHashSet::default(); - let mut todo = ids; + let mut todo = start; while let Some(id) = todo.pop() { if !done.insert(id) { // We already saw this allocation before, don't process it again. @@ -992,31 +994,20 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } let info = self.get_alloc_info(id); - // If there is no data behind this pointer, skip this. - if !matches!(info.kind, AllocKind::LiveData) { - continue; - } - - // Expose all provenances in this allocation, and add them to `todo`. - let alloc = self.get_alloc_raw(id)?; - for prov in alloc.provenance().provenances() { - M::expose_provenance(self, prov)?; - if let Some(id) = prov.get_alloc_id() { - todo.push(id); + // Recurse, if there is data here. + // Do this *before* invoking the callback, as the callback might mutate the + // allocation and e.g. replace all provenance by wildcards! + if matches!(info.kind, AllocKind::LiveData) { + let alloc = self.get_alloc_raw(id)?; + for prov in alloc.provenance().provenances() { + if let Some(id) = prov.get_alloc_id() { + todo.push(id); + } } } - // Also expose the provenance of the interpreter-level allocation, so it can - // be read by FFI. The `black_box` is defensive programming as LLVM likes - // to (incorrectly) optimize away ptr2int casts whose result is unused. - std::hint::black_box(alloc.get_bytes_unchecked_raw().expose_provenance()); - - // Prepare for possible write from native code if mutable. - if info.mutbl.is_mut() { - self.get_alloc_raw_mut(id)? - .0 - .prepare_for_native_write() - .map_err(|e| e.to_interp_error(id))?; - } + + // Call the callback. + visit(self, id, &info)?; } interp_ok(()) } @@ -1073,7 +1064,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { todo.extend(static_roots(self)); while let Some(id) = todo.pop() { if reachable.insert(id) { - // This is a new allocation, add the allocation it points to `todo`. + // This is a new allocation, add the allocations it points to `todo`. + // We only need to care about `alloc_map` memory here, as entirely unchanged + // global memory cannot point to memory relevant for the leak check. if let Some((_, alloc)) = self.memory.alloc_map.get(id) { todo.extend( alloc.provenance().provenances().filter_map(|prov| prov.get_alloc_id()), diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index a3cd35ff0bb..e2284729efd 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -572,7 +572,7 @@ where Right((local, offset, locals_addr, layout)) => { if offset.is_some() { // This has been projected to a part of this local, or had the type changed. - // FIMXE: there are cases where we could still avoid allocating an mplace. + // FIXME: there are cases where we could still avoid allocating an mplace. Left(place.force_mplace(self)?) } else { debug_assert_eq!(locals_addr, self.frame().locals_addr()); diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index e26cf0a4900..fc4d13af8c4 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -865,7 +865,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { fn add_data_range(&mut self, ptr: Pointer<Option<M::Provenance>>, size: Size) { if let Some(data_bytes) = self.data_bytes.as_mut() { // We only have to store the offset, the rest is the same for all pointers here. - // The logic is agnostic to wether the offset is relative or absolute as long as + // The logic is agnostic to whether the offset is relative or absolute as long as // it is consistent. let (_prov, offset) = ptr.into_raw_parts(); // Add this. diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs index d7e97f32bae..4ca39bbc68e 100644 --- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs +++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs @@ -69,7 +69,7 @@ fn check_validity_requirement_strict<'tcx>( // require dereferenceability also require non-null, we don't actually get any false negatives // due to this. // The value we are validating is temporary and discarded at the end of this function, so - // there is no point in reseting provenance and padding. + // there is no point in resetting provenance and padding. cx.validate_operand( &allocated.into(), /*recursive*/ false, diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs index 36649a36070..1b4db7adc27 100644 --- a/compiler/rustc_data_structures/src/profiling.rs +++ b/compiler/rustc_data_structures/src/profiling.rs @@ -88,6 +88,7 @@ use std::fmt::Display; use std::intrinsics::unlikely; use std::path::Path; use std::sync::Arc; +use std::sync::atomic::Ordering; use std::time::{Duration, Instant}; use std::{fs, process}; @@ -99,12 +100,15 @@ use tracing::warn; use crate::fx::FxHashMap; use crate::outline; +use crate::sync::AtomicU64; bitflags::bitflags! { #[derive(Clone, Copy)] struct EventFilter: u16 { const GENERIC_ACTIVITIES = 1 << 0; const QUERY_PROVIDERS = 1 << 1; + /// Store detailed instant events, including timestamp and thread ID, + /// per each query cache hit. Note that this is quite expensive. const QUERY_CACHE_HITS = 1 << 2; const QUERY_BLOCKED = 1 << 3; const INCR_CACHE_LOADS = 1 << 4; @@ -113,16 +117,20 @@ bitflags::bitflags! { const FUNCTION_ARGS = 1 << 6; const LLVM = 1 << 7; const INCR_RESULT_HASHING = 1 << 8; - const ARTIFACT_SIZES = 1 << 9; + const ARTIFACT_SIZES = 1 << 9; + /// Store aggregated counts of cache hits per query invocation. + const QUERY_CACHE_HIT_COUNTS = 1 << 10; const DEFAULT = Self::GENERIC_ACTIVITIES.bits() | Self::QUERY_PROVIDERS.bits() | Self::QUERY_BLOCKED.bits() | Self::INCR_CACHE_LOADS.bits() | Self::INCR_RESULT_HASHING.bits() | - Self::ARTIFACT_SIZES.bits(); + Self::ARTIFACT_SIZES.bits() | + Self::QUERY_CACHE_HIT_COUNTS.bits(); const ARGS = Self::QUERY_KEYS.bits() | Self::FUNCTION_ARGS.bits(); + const QUERY_CACHE_HIT_COMBINED = Self::QUERY_CACHE_HITS.bits() | Self::QUERY_CACHE_HIT_COUNTS.bits(); } } @@ -134,6 +142,7 @@ const EVENT_FILTERS_BY_NAME: &[(&str, EventFilter)] = &[ ("generic-activity", EventFilter::GENERIC_ACTIVITIES), ("query-provider", EventFilter::QUERY_PROVIDERS), ("query-cache-hit", EventFilter::QUERY_CACHE_HITS), + ("query-cache-hit-count", EventFilter::QUERY_CACHE_HITS), ("query-blocked", EventFilter::QUERY_BLOCKED), ("incr-cache-load", EventFilter::INCR_CACHE_LOADS), ("query-keys", EventFilter::QUERY_KEYS), @@ -411,13 +420,24 @@ impl SelfProfilerRef { #[inline(never)] #[cold] fn cold_call(profiler_ref: &SelfProfilerRef, query_invocation_id: QueryInvocationId) { - profiler_ref.instant_query_event( - |profiler| profiler.query_cache_hit_event_kind, - query_invocation_id, - ); + if profiler_ref.event_filter_mask.contains(EventFilter::QUERY_CACHE_HIT_COUNTS) { + profiler_ref + .profiler + .as_ref() + .unwrap() + .increment_query_cache_hit_counters(QueryInvocationId(query_invocation_id.0)); + } + if unlikely(profiler_ref.event_filter_mask.contains(EventFilter::QUERY_CACHE_HITS)) { + profiler_ref.instant_query_event( + |profiler| profiler.query_cache_hit_event_kind, + query_invocation_id, + ); + } } - if unlikely(self.event_filter_mask.contains(EventFilter::QUERY_CACHE_HITS)) { + // We check both kinds of query cache hit events at once, to reduce overhead in the + // common case (with self-profile disabled). + if unlikely(self.event_filter_mask.intersects(EventFilter::QUERY_CACHE_HIT_COMBINED)) { cold_call(self, query_invocation_id); } } @@ -489,6 +509,35 @@ impl SelfProfilerRef { self.profiler.as_ref().map(|p| p.get_or_alloc_cached_string(s)) } + /// Store query cache hits to the self-profile log. + /// Should be called once at the end of the compilation session. + /// + /// The cache hits are stored per **query invocation**, not **per query kind/type**. + /// `analyzeme` can later deduplicate individual query labels from the QueryInvocationId event + /// IDs. + pub fn store_query_cache_hits(&self) { + if self.event_filter_mask.contains(EventFilter::QUERY_CACHE_HIT_COUNTS) { + let profiler = self.profiler.as_ref().unwrap(); + let query_hits = profiler.query_hits.read(); + let builder = EventIdBuilder::new(&profiler.profiler); + let thread_id = get_thread_id(); + for (query_invocation, hit_count) in query_hits.iter().enumerate() { + let hit_count = hit_count.load(Ordering::Relaxed); + // No need to record empty cache hit counts + if hit_count > 0 { + let event_id = + builder.from_label(StringId::new_virtual(query_invocation as u64)); + profiler.profiler.record_integer_event( + profiler.query_cache_hit_count_event_kind, + event_id, + thread_id, + hit_count, + ); + } + } + } + } + #[inline] pub fn enabled(&self) -> bool { self.profiler.is_some() @@ -537,6 +586,19 @@ pub struct SelfProfiler { string_cache: RwLock<FxHashMap<String, StringId>>, + /// Recording individual query cache hits as "instant" measureme events + /// is incredibly expensive. Instead of doing that, we simply aggregate + /// cache hit *counts* per query invocation, and then store the final count + /// of cache hits per invocation at the end of the compilation session. + /// + /// With this approach, we don't know the individual thread IDs and timestamps + /// of cache hits, but it has very little overhead on top of `-Zself-profile`. + /// Recording the cache hits as individual events made compilation 3-5x slower. + /// + /// Query invocation IDs should be monotonic integers, so we can store them in a vec, + /// rather than using a hashmap. + query_hits: RwLock<Vec<AtomicU64>>, + query_event_kind: StringId, generic_activity_event_kind: StringId, incremental_load_result_event_kind: StringId, @@ -544,6 +606,8 @@ pub struct SelfProfiler { query_blocked_event_kind: StringId, query_cache_hit_event_kind: StringId, artifact_size_event_kind: StringId, + /// Total cache hits per query invocation + query_cache_hit_count_event_kind: StringId, } impl SelfProfiler { @@ -573,6 +637,7 @@ impl SelfProfiler { let query_blocked_event_kind = profiler.alloc_string("QueryBlocked"); let query_cache_hit_event_kind = profiler.alloc_string("QueryCacheHit"); let artifact_size_event_kind = profiler.alloc_string("ArtifactSize"); + let query_cache_hit_count_event_kind = profiler.alloc_string("QueryCacheHitCount"); let mut event_filter_mask = EventFilter::empty(); @@ -618,6 +683,8 @@ impl SelfProfiler { query_blocked_event_kind, query_cache_hit_event_kind, artifact_size_event_kind, + query_cache_hit_count_event_kind, + query_hits: Default::default(), }) } @@ -627,6 +694,25 @@ impl SelfProfiler { self.profiler.alloc_string(s) } + /// Store a cache hit of a query invocation + pub fn increment_query_cache_hit_counters(&self, id: QueryInvocationId) { + // Fast path: assume that the query was already encountered before, and just record + // a cache hit. + let mut guard = self.query_hits.upgradable_read(); + let query_hits = &guard; + let index = id.0 as usize; + if index < query_hits.len() { + // We only want to increment the count, no other synchronization is required + query_hits[index].fetch_add(1, Ordering::Relaxed); + } else { + // If not, we need to extend the query hit map to the highest observed ID + guard.with_upgraded(|vec| { + vec.resize_with(index + 1, || AtomicU64::new(0)); + vec[index] = AtomicU64::from(1); + }); + } + } + /// Gets a `StringId` for the given string. This method makes sure that /// any strings going through it will only be allocated once in the /// profiling data. diff --git a/compiler/rustc_data_structures/src/vec_cache.rs b/compiler/rustc_data_structures/src/vec_cache.rs index 3b448c056b7..0ffa6b3205f 100644 --- a/compiler/rustc_data_structures/src/vec_cache.rs +++ b/compiler/rustc_data_structures/src/vec_cache.rs @@ -257,7 +257,7 @@ unsafe impl<K: Idx, #[may_dangle] V, I> Drop for VecCache<K, V, I> { // we are also guaranteed to just need to deallocate any large arrays (not iterate over // contents). // - // Confirm no need to deallocate invidual entries. Note that `V: Copy` is asserted on + // Confirm no need to deallocate individual entries. Note that `V: Copy` is asserted on // insert/lookup but not necessarily construction, primarily to avoid annoyingly propagating // the bounds into struct definitions everywhere. assert!(!std::mem::needs_drop::<K>()); diff --git a/compiler/rustc_errors/src/markdown/parse.rs b/compiler/rustc_errors/src/markdown/parse.rs index f02387d8335..e1b1b32cd3e 100644 --- a/compiler/rustc_errors/src/markdown/parse.rs +++ b/compiler/rustc_errors/src/markdown/parse.rs @@ -352,7 +352,7 @@ fn normalize<'a>(MdStream(stream): MdStream<'a>, linkdefs: &mut Vec<MdTree<'a>>) let new_defs = stream.iter().filter(|tt| matches!(tt, MdTree::LinkDef { .. })); linkdefs.extend(new_defs.cloned()); - // Run plaintest expansions on types that need it, call this function on nested types + // Run plaintext expansions on types that need it, call this function on nested types for item in stream { match item { MdTree::PlainText(txt) => expand_plaintext(txt, &mut new_stream, MdTree::PlainText), diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index fe76d9e0b64..80f6e9d9fc4 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -880,7 +880,7 @@ impl SyntaxExtension { is_local: bool, ) -> SyntaxExtension { let allow_internal_unstable = - find_attr!(attrs, AttributeKind::AllowInternalUnstable(i) => i) + find_attr!(attrs, AttributeKind::AllowInternalUnstable(i, _) => i) .map(|i| i.as_slice()) .unwrap_or_default(); // FIXME(jdonszelman): allow_internal_unsafe isn't yet new-style diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 14b8cc90d97..a333f2c7cb7 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -195,6 +195,7 @@ impl<'a> ExtCtxt<'a> { }, trait_ref: self.trait_ref(path), span, + parens: ast::Parens::No, } } diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs index 99aa376626d..c607a3a3652 100644 --- a/compiler/rustc_expand/src/mbe/diagnostics.rs +++ b/compiler/rustc_expand/src/mbe/diagnostics.rs @@ -195,38 +195,6 @@ impl<'dcx> CollectTrackerAndEmitter<'dcx, '_> { } } -/// 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(crate) fn new() -> Self { - Self { expected_token: None } - } -} - -impl<'matcher> Tracker<'matcher> for FailureForwarder<'matcher> { - type Failure = (Token, u32, &'static str); - - fn build_failure(tok: Token, position: u32, msg: &'static str) -> Self::Failure { - (tok, position, msg) - } - - fn description() -> &'static str { - "failure-forwarder" - } - - fn set_expected_token(&mut self, tok: &'matcher Token) { - self.expected_token = Some(tok); - } - - fn get_expected_token(&self) -> Option<&'matcher Token> { - self.expected_token - } -} - pub(super) fn emit_frag_parse_err( mut e: Diag<'_>, parser: &Parser<'_>, @@ -321,7 +289,7 @@ enum ExplainDocComment { }, } -pub(super) fn annotate_doc_comment(err: &mut Diag<'_>, sm: &SourceMap, span: Span) { +fn annotate_doc_comment(err: &mut Diag<'_>, sm: &SourceMap, span: Span) { if let Ok(src) = sm.span_to_snippet(span) { if src.starts_with("///") || src.starts_with("/**") { err.subdiagnostic(ExplainDocComment::Outer { span }); @@ -333,7 +301,7 @@ pub(super) fn annotate_doc_comment(err: &mut Diag<'_>, sm: &SourceMap, span: Spa /// Generates an appropriate parsing failure message. For EOF, this is "unexpected end...". For /// other tokens, this is "unexpected token...". -pub(super) fn parse_failure_msg(tok: &Token, expected_token: Option<&Token>) -> Cow<'static, str> { +fn parse_failure_msg(tok: &Token, expected_token: Option<&Token>) -> Cow<'static, str> { if let Some(expected_token) = expected_token { Cow::from(format!("expected {}, found {}", token_descr(expected_token), token_descr(tok))) } else { diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs index dc2d46c4a14..bbdff866feb 100644 --- a/compiler/rustc_expand/src/mbe/macro_check.rs +++ b/compiler/rustc_expand/src/mbe/macro_check.rs @@ -105,8 +105,6 @@ //! stored when entering a macro definition starting from the state in which the meta-variable is //! bound. -use std::iter; - use rustc_ast::token::{Delimiter, IdentIsRaw, Token, TokenKind}; use rustc_ast::{DUMMY_NODE_ID, NodeId}; use rustc_data_structures::fx::FxHashMap; @@ -190,29 +188,22 @@ struct MacroState<'a> { ops: SmallVec<[KleeneToken; 1]>, } -/// Checks that meta-variables are used correctly in a macro definition. +/// Checks that meta-variables are used correctly in one rule of a macro definition. /// /// Arguments: /// - `psess` is used to emit diagnostics and lints /// - `node_id` is used to emit lints -/// - `span` is used when no spans are available -/// - `lhses` and `rhses` should have the same length and represent the macro definition +/// - `lhs` and `rhs` represent the rule pub(super) fn check_meta_variables( psess: &ParseSess, node_id: NodeId, - span: Span, - lhses: &[TokenTree], - rhses: &[TokenTree], + lhs: &TokenTree, + rhs: &TokenTree, ) -> Result<(), ErrorGuaranteed> { - if lhses.len() != rhses.len() { - psess.dcx().span_bug(span, "length mismatch between LHSes and RHSes") - } let mut guar = None; - for (lhs, rhs) in iter::zip(lhses, rhses) { - let mut binders = Binders::default(); - check_binders(psess, node_id, lhs, &Stack::Empty, &mut binders, &Stack::Empty, &mut guar); - check_occurrences(psess, node_id, rhs, &Stack::Empty, &binders, &Stack::Empty, &mut guar); - } + let mut binders = Binders::default(); + check_binders(psess, node_id, lhs, &Stack::Empty, &mut binders, &Stack::Empty, &mut guar); + check_occurrences(psess, node_id, rhs, &Stack::Empty, &binders, &Stack::Empty, &mut guar); guar.map_or(Ok(()), Err) } diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index 802e43209a5..3f1fc841ea3 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -536,8 +536,6 @@ impl TtParser { // The separator matches the current token. Advance past it. mp.idx += 1; self.next_mps.push(mp); - } else { - track.set_expected_token(separator); } } &MatcherLoc::SequenceKleeneOpAfterSep { idx_first } => { diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 432ab324740..dad2fd99ef2 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -19,12 +19,13 @@ use rustc_lint_defs::BuiltinLintDiag; use rustc_lint_defs::builtin::{ RUST_2021_INCOMPATIBLE_OR_PATTERNS, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS, }; -use rustc_parse::parser::{ParseNtResult, Parser, Recovery}; +use rustc_parse::exp; +use rustc_parse::parser::{Parser, Recovery}; use rustc_session::Session; use rustc_session::parse::ParseSess; use rustc_span::edition::Edition; use rustc_span::hygiene::Transparency; -use rustc_span::{Ident, MacroRulesNormalizedIdent, Span, kw, sym}; +use rustc_span::{Ident, Span, kw, sym}; use tracing::{debug, instrument, trace, trace_span}; use super::macro_parser::{NamedMatches, NamedParseResult}; @@ -34,8 +35,6 @@ use crate::base::{ SyntaxExtensionKind, TTMacroExpander, }; use crate::expand::{AstFragment, AstFragmentKind, ensure_complete_parse, parse_ast_fragment}; -use crate::mbe::diagnostics::{annotate_doc_comment, parse_failure_msg}; -use crate::mbe::macro_parser::NamedMatch::*; use crate::mbe::macro_parser::{Error, ErrorReported, Failure, MatcherLoc, Success, TtParser}; use crate::mbe::transcribe::transcribe; use crate::mbe::{self, KleeneOp, macro_check}; @@ -168,11 +167,6 @@ pub(super) trait Tracker<'matcher> { fn recovery() -> Recovery { Recovery::Forbidden } - - fn set_expected_token(&mut self, _tok: &'matcher Token) {} - fn get_expected_token(&self) -> Option<&'matcher Token> { - None - } } /// A noop tracker that is used in the hot path of the expansion, has zero overhead thanks to @@ -360,11 +354,6 @@ pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>( Err(CanRetry::Yes) } -// Note that macro-by-example's input is also matched against a token tree: -// $( $lhs:tt => $rhs:tt );+ -// -// Holy self-referential! - /// Converts a macro item into a syntax extension. pub fn compile_declarative_macro( sess: &Session, @@ -390,157 +379,66 @@ pub fn compile_declarative_macro( }; let dummy_syn_ext = |guar| (mk_syn_ext(Arc::new(DummyExpander(guar))), Vec::new()); - let lhs_nm = Ident::new(sym::lhs, span); - let rhs_nm = Ident::new(sym::rhs, span); - let tt_spec = NonterminalKind::TT; let macro_rules = macro_def.macro_rules; + let exp_sep = if macro_rules { exp!(Semi) } else { exp!(Comma) }; - // Parse the macro_rules! invocation - - // The pattern that macro_rules matches. - // The grammar for macro_rules! is: - // $( $lhs:tt => $rhs:tt );+ - // ...quasiquoting this would be nice. - // These spans won't matter, anyways - let argument_gram = vec![ - mbe::TokenTree::Sequence( - DelimSpan::dummy(), - mbe::SequenceRepetition { - tts: vec![ - mbe::TokenTree::MetaVarDecl { span, name: lhs_nm, kind: tt_spec }, - mbe::TokenTree::token(token::FatArrow, span), - mbe::TokenTree::MetaVarDecl { span, name: rhs_nm, kind: tt_spec }, - ], - separator: Some(Token::new( - if macro_rules { token::Semi } else { token::Comma }, - span, - )), - kleene: mbe::KleeneToken::new(mbe::KleeneOp::OneOrMore, span), - num_captures: 2, - }, - ), - // to phase into semicolon-termination instead of semicolon-separation - mbe::TokenTree::Sequence( - DelimSpan::dummy(), - mbe::SequenceRepetition { - tts: vec![mbe::TokenTree::token( - if macro_rules { token::Semi } else { token::Comma }, - span, - )], - separator: None, - kleene: mbe::KleeneToken::new(mbe::KleeneOp::ZeroOrMore, span), - num_captures: 0, - }, - ), - ]; - // Convert it into `MatcherLoc` form. - let argument_gram = mbe::macro_parser::compute_locs(&argument_gram); - - let create_parser = || { - let body = macro_def.body.tokens.clone(); - Parser::new(&sess.psess, body, rustc_parse::MACRO_ARGUMENTS) - }; - - let parser = create_parser(); - let mut tt_parser = - TtParser::new(Ident::with_dummy_span(if macro_rules { kw::MacroRules } else { kw::Macro })); - let argument_map = - match tt_parser.parse_tt(&mut Cow::Owned(parser), &argument_gram, &mut NoopTracker) { - Success(m) => m, - Failure(()) => { - debug!("failed to parse macro tt"); - // The fast `NoopTracker` doesn't have any info on failure, so we need to retry it - // with another one that gives us the information we need. - // For this we need to reclone the macro body as the previous parser consumed it. - let retry_parser = create_parser(); - - let mut track = diagnostics::FailureForwarder::new(); - let parse_result = - tt_parser.parse_tt(&mut Cow::Owned(retry_parser), &argument_gram, &mut track); - let Failure((token, _, msg)) = parse_result else { - unreachable!("matcher returned something other than Failure after retry"); - }; - - let s = parse_failure_msg(&token, track.get_expected_token()); - let sp = token.span.substitute_dummy(span); - let mut err = sess.dcx().struct_span_err(sp, s); - err.span_label(sp, msg); - annotate_doc_comment(&mut err, sess.source_map(), sp); - let guar = err.emit(); - return dummy_syn_ext(guar); - } - Error(sp, msg) => { - let guar = sess.dcx().span_err(sp.substitute_dummy(span), msg); - return dummy_syn_ext(guar); - } - ErrorReported(guar) => { - return dummy_syn_ext(guar); - } - }; + let body = macro_def.body.tokens.clone(); + let mut p = Parser::new(&sess.psess, body, rustc_parse::MACRO_ARGUMENTS); + // Don't abort iteration early, so that multiple errors can be reported. let mut guar = None; let mut check_emission = |ret: Result<(), ErrorGuaranteed>| guar = guar.or(ret.err()); - // Extract the arguments: - let lhses = match &argument_map[&MacroRulesNormalizedIdent::new(lhs_nm)] { - MatchedSeq(s) => s - .iter() - .map(|m| { - if let MatchedSingle(ParseNtResult::Tt(tt)) = m { - let tt = mbe::quoted::parse( - &TokenStream::new(vec![tt.clone()]), - true, - sess, - node_id, - features, - edition, - ) - .pop() - .unwrap(); - // We don't handle errors here, the driver will abort - // after parsing/expansion. We can report every error in every macro this way. - check_emission(check_lhs_nt_follows(sess, node_id, &tt)); - return tt; - } - sess.dcx().span_bug(span, "wrong-structured lhs") - }) - .collect::<Vec<mbe::TokenTree>>(), - _ => sess.dcx().span_bug(span, "wrong-structured lhs"), - }; + let mut lhses = Vec::new(); + let mut rhses = Vec::new(); - let rhses = match &argument_map[&MacroRulesNormalizedIdent::new(rhs_nm)] { - MatchedSeq(s) => s - .iter() - .map(|m| { - if let MatchedSingle(ParseNtResult::Tt(tt)) = m { - return mbe::quoted::parse( - &TokenStream::new(vec![tt.clone()]), - false, - sess, - node_id, - features, - edition, - ) - .pop() - .unwrap(); - } - sess.dcx().span_bug(span, "wrong-structured rhs") - }) - .collect::<Vec<mbe::TokenTree>>(), - _ => sess.dcx().span_bug(span, "wrong-structured rhs"), - }; - - for rhs in &rhses { - check_emission(check_rhs(sess, rhs)); + while p.token != token::Eof { + let lhs_tt = p.parse_token_tree(); + let lhs_tt = mbe::quoted::parse( + &TokenStream::new(vec![lhs_tt]), + true, // LHS + sess, + node_id, + features, + edition, + ) + .pop() + .unwrap(); + // We don't handle errors here, the driver will abort after parsing/expansion. We can + // report every error in every macro this way. + check_emission(check_lhs_nt_follows(sess, node_id, &lhs_tt)); + check_emission(check_lhs_no_empty_seq(sess, slice::from_ref(&lhs_tt))); + if let Err(e) = p.expect(exp!(FatArrow)) { + return dummy_syn_ext(e.emit()); + } + let rhs_tt = p.parse_token_tree(); + let rhs_tt = mbe::quoted::parse( + &TokenStream::new(vec![rhs_tt]), + false, // RHS + sess, + node_id, + features, + edition, + ) + .pop() + .unwrap(); + check_emission(check_rhs(sess, &rhs_tt)); + check_emission(macro_check::check_meta_variables(&sess.psess, node_id, &lhs_tt, &rhs_tt)); + lhses.push(lhs_tt); + rhses.push(rhs_tt); + if p.token == token::Eof { + break; + } + if let Err(e) = p.expect(exp_sep) { + return dummy_syn_ext(e.emit()); + } } - // Don't abort iteration early, so that errors for multiple lhses can be reported. - for lhs in &lhses { - check_emission(check_lhs_no_empty_seq(sess, slice::from_ref(lhs))); + if lhses.is_empty() { + let guar = sess.dcx().span_err(span, "macros must contain at least one rule"); + return dummy_syn_ext(guar); } - check_emission(macro_check::check_meta_variables(&sess.psess, node_id, span, &lhses, &rhses)); - let transparency = find_attr!(attrs, AttributeKind::MacroTransparency(x) => *x) .unwrap_or(Transparency::fallback(macro_rules)); diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index af91c8b8f00..fd71f2ce948 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -681,7 +681,7 @@ impl server::Span for Rustc<'_, '_> { .lookup_char_pos(span.lo()) .file .name - .prefer_remapped_unconditionaly() + .prefer_remapped_unconditionally() .to_string() } diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index db67c507b70..83be3241b12 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -265,6 +265,8 @@ declare_features! ( (accepted, keylocker_x86, "1.89.0", Some(134813)), /// Allows `'a: { break 'a; }`. (accepted, label_break_value, "1.65.0", Some(48594)), + /// Allows `if/while p && let q = r && ...` chains. + (accepted, let_chains, "1.88.0", Some(53667)), /// Allows `let...else` statements. (accepted, let_else, "1.65.0", Some(87335)), /// Allows using `reason` in lint attributes and the `#[expect(lint)]` lint check. diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 269a9c60d86..efd8bde71d7 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -550,8 +550,6 @@ declare_features! ( (unstable, large_assignments, "1.52.0", Some(83518)), /// Allow to have type alias types for inter-crate use. (incomplete, lazy_type_alias, "1.72.0", Some(112792)), - /// Allows `if/while p && let q = r && ...` chains. - (unstable, let_chains, "1.37.0", Some(53667)), /// Allows using `#[link(kind = "link-arg", name = "...")]` /// to pass custom arguments to the linker. (unstable, link_arg_attribute, "1.76.0", Some(99427)), diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index c90cd93ff07..ca6405ea209 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -439,7 +439,7 @@ impl<'hir> ConstArg<'hir, AmbigArg> { } impl<'hir> ConstArg<'hir> { - /// Converts a `ConstArg` in an unambigous position to one in an ambiguous position. This is + /// Converts a `ConstArg` in an unambiguous position to one in an ambiguous position. This is /// fallible as the [`ConstArgKind::Infer`] variant is not present in ambiguous positions. /// /// Functions accepting ambiguous consts will not handle the [`ConstArgKind::Infer`] variant, if @@ -508,7 +508,7 @@ pub enum GenericArg<'hir> { Lifetime(&'hir Lifetime), Type(&'hir Ty<'hir, AmbigArg>), Const(&'hir ConstArg<'hir, AmbigArg>), - /// Inference variables in [`GenericArg`] are always represnted by + /// Inference variables in [`GenericArg`] are always represented by /// `GenericArg::Infer` instead of the `Infer` variants on [`TyKind`] and /// [`ConstArgKind`] as it is not clear until hir ty lowering whether a /// `_` argument is a type or const argument. @@ -3323,7 +3323,7 @@ impl<'hir> Ty<'hir, AmbigArg> { } impl<'hir> Ty<'hir> { - /// Converts a `Ty` in an unambigous position to one in an ambiguous position. This is + /// Converts a `Ty` in an unambiguous position to one in an ambiguous position. This is /// fallible as the [`TyKind::Infer`] variant is not present in ambiguous positions. /// /// Functions accepting ambiguous types will not handle the [`TyKind::Infer`] variant, if @@ -4224,7 +4224,7 @@ impl fmt::Display for Constness { } } -/// The actualy safety specified in syntax. We may treat +/// The actual safety specified in syntax. We may treat /// its safety different within the type system to create a /// "sound by default" system that needs checking this enum /// explicitly to allow unsafe operations. diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 7eb896f0bf1..573af01a62d 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -1,12 +1,11 @@ use std::assert_matches::assert_matches; use std::ops::ControlFlow; -use hir::intravisit::{self, Visitor}; -use hir::{GenericParamKind, HirId, Node}; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; -use rustc_hir::intravisit::VisitorExt; -use rustc_hir::{self as hir, AmbigArg}; +use rustc_hir::intravisit::{self, Visitor, VisitorExt}; +use rustc_hir::{self as hir, AmbigArg, GenericParamKind, HirId, Node}; +use rustc_middle::span_bug; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::lint; use rustc_span::{Span, Symbol, kw}; @@ -212,7 +211,19 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { // inherit the generics of the item. Some(parent.to_def_id()) } - _ => None, + + // All of these nodes have no parent from which to inherit generics. + Node::Item(_) | Node::ForeignItem(_) => None, + + // Params don't really have generics, but we use it when instantiating their value paths. + Node::GenericParam(_) => None, + + Node::Synthetic => span_bug!( + tcx.def_span(def_id), + "synthetic HIR should have its `generics_of` explicitly fed" + ), + + _ => span_bug!(tcx.def_span(def_id), "unhandled node {node:?}"), }; enum Defaults { 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 6b2854d96af..e13daabeb50 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -1088,7 +1088,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // FIXME(#97583): Print associated item bindings properly (i.e., not as equality // predicates!). - // FIXME: Turn this into a structured, translateable & more actionable suggestion. + // FIXME: Turn this into a structured, translatable & more actionable suggestion. let mut where_bounds = vec![]; for bound in [bound, bound2].into_iter().chain(matching_candidates) { let bound_id = bound.def_id(); @@ -1588,7 +1588,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { &infcx_ }; - tcx.all_traits() + tcx.all_traits_including_private() .filter(|trait_def_id| { // Consider only traits with the associated type tcx.associated_items(*trait_def_id) @@ -2459,13 +2459,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // type a projection. let in_trait = match opaque_ty.origin { hir::OpaqueTyOrigin::FnReturn { + parent, in_trait_or_impl: Some(hir::RpitContext::Trait), .. } | hir::OpaqueTyOrigin::AsyncFn { + parent, in_trait_or_impl: Some(hir::RpitContext::Trait), .. - } => true, + } => Some(parent), hir::OpaqueTyOrigin::FnReturn { in_trait_or_impl: None | Some(hir::RpitContext::TraitImpl), .. @@ -2474,7 +2476,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { in_trait_or_impl: None | Some(hir::RpitContext::TraitImpl), .. } - | hir::OpaqueTyOrigin::TyAlias { .. } => false, + | hir::OpaqueTyOrigin::TyAlias { .. } => None, }; self.lower_opaque_ty(opaque_ty.def_id, in_trait) @@ -2594,17 +2596,25 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// Lower an opaque type (i.e., an existential impl-Trait type) from the HIR. #[instrument(level = "debug", skip(self), ret)] - fn lower_opaque_ty(&self, def_id: LocalDefId, in_trait: bool) -> Ty<'tcx> { + fn lower_opaque_ty(&self, def_id: LocalDefId, in_trait: Option<LocalDefId>) -> Ty<'tcx> { let tcx = self.tcx(); let lifetimes = tcx.opaque_captured_lifetimes(def_id); debug!(?lifetimes); - // If this is an RPITIT and we are using the new RPITIT lowering scheme, we - // generate the def_id of an associated type for the trait and return as - // type a projection. - let def_id = if in_trait { - tcx.associated_type_for_impl_trait_in_trait(def_id).to_def_id() + // If this is an RPITIT and we are using the new RPITIT lowering scheme, + // do a linear search to map this to the synthetic associated type that + // it will be lowered to. + let def_id = if let Some(parent_def_id) = in_trait { + *tcx.associated_types_for_impl_traits_in_associated_fn(parent_def_id) + .iter() + .find(|rpitit| match tcx.opt_rpitit_info(**rpitit) { + Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => { + opaque_def_id.expect_local() == def_id + } + _ => unreachable!(), + }) + .unwrap() } else { def_id.to_def_id() }; @@ -2627,7 +2637,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }); debug!(?args); - if in_trait { + if in_trait.is_some() { Ty::new_projection_from_args(tcx, def_id, args) } else { Ty::new_opaque(tcx, def_id, args) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 3ca04ba330b..b2a229ad651 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -726,7 +726,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { Err(SelectionError::TraitDynIncompatible(_)) => { // Dyn compatibility errors in coercion will *always* be due to the // fact that the RHS of the coercion is a non-dyn compatible `dyn Trait` - // writen in source somewhere (otherwise we will never have lowered + // written in source somewhere (otherwise we will never have lowered // the dyn trait from HIR to middle). // // There's no reason to emit yet another dyn compatibility error, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 3c53a060f7f..eeb8d33ef65 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -121,7 +121,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => {} } - // We want to emit an error if the const is not structurally resolveable + // We want to emit an error if the const is not structurally resolvable // as otherwise we can wind up conservatively proving `Copy` which may // infer the repeat expr count to something that never required `Copy` in // the first place. @@ -2461,7 +2461,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { spans.push_span_label(param.param.span(), ""); } } - // Highligh each parameter being depended on for a generic type. + // Highlight each parameter being depended on for a generic type. for ((&(_, param), deps), &(_, expected_ty)) in params_with_generics.iter().zip(&dependants).zip(formal_and_expected_inputs) { diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 9563cf734f6..4c343bb7c22 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -588,7 +588,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { let def_id = pick.item.def_id; let method_predicates = self.tcx.predicates_of(def_id).instantiate(self.tcx, all_args); - debug!("method_predicates after instantitation = {:?}", method_predicates); + debug!("method_predicates after instantiation = {:?}", method_predicates); let sig = self.tcx.fn_sig(def_id).instantiate(self.tcx, all_args); debug!("type scheme instantiated, sig={:?}", sig); diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index 085e7a2f5df..8380c3710e6 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -375,7 +375,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // type parameters or early-bound regions. let tcx = self.tcx; // We use `Ident::with_dummy_span` since no built-in operator methods have - // any macro-specific hygeine, so the span's context doesn't really matter. + // any macro-specific hygiene, so the span's context doesn't really matter. let Some(method_item) = self.associated_value(trait_def_id, Ident::with_dummy_span(method_name)) else { diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index df1ee0e79c2..2815621ffde 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1725,7 +1725,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if unsatisfied_predicates.is_empty() // ...or if we already suggested that name because of `rustc_confusable` annotation && Some(similar_candidate.name()) != confusable_suggested - // and if the we aren't in an expansion. + // and if we aren't in an expansion. && !span.from_expansion() { self.find_likely_intended_associated_item( @@ -3481,9 +3481,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, err: &mut Diag<'_>, item_name: Ident, - valid_out_of_scope_traits: Vec<DefId>, + mut valid_out_of_scope_traits: Vec<DefId>, explain: bool, ) -> bool { + valid_out_of_scope_traits.retain(|id| self.tcx.is_user_visible_dep(id.krate)); if !valid_out_of_scope_traits.is_empty() { let mut candidates = valid_out_of_scope_traits; candidates.sort_by_key(|id| self.tcx.def_path_str(id)); @@ -4388,7 +4389,7 @@ pub(crate) struct TraitInfo { /// Retrieves all traits in this crate and any dependent crates, /// and wraps them into `TraitInfo` for custom sorting. pub(crate) fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> { - tcx.all_traits().map(|def_id| TraitInfo { def_id }).collect() + tcx.all_traits_including_private().map(|def_id| TraitInfo { def_id }).collect() } fn print_disambiguation_help<'tcx>( diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 349e72090d3..43475521a0f 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -723,7 +723,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // This is maximally flexible, allowing e.g., `Some(mut x) | &Some(mut x)`. // In that example, `Some(mut x)` results in `Peel` whereas `&Some(mut x)` in `Reset`. | PatKind::Or(_) - // Like or-patterns, guard patterns just propogate to their subpatterns. + // Like or-patterns, guard patterns just propagate to their subpatterns. | PatKind::Guard(..) => AdjustMode::Pass, } } diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index b2bd5e188ef..e30dbe80248 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -566,7 +566,7 @@ impl Cursor<'_> { } if !found { - // recovery strategy: a closing statement might have precending whitespace/newline + // recovery strategy: a closing statement might have preceding whitespace/newline // but not have enough dashes to properly close. In this case, we eat until there, // and report a mismatch in the parser. let mut rest = self.as_str(); diff --git a/compiler/rustc_lint/src/autorefs.rs b/compiler/rustc_lint/src/autorefs.rs index 845a1f1b81f..5490a3aac9b 100644 --- a/compiler/rustc_lint/src/autorefs.rs +++ b/compiler/rustc_lint/src/autorefs.rs @@ -41,7 +41,7 @@ declare_lint! { /// } /// ``` /// - /// Otherwise try to find an alternative way to achive your goals using only raw pointers: + /// Otherwise try to find an alternative way to achieve your goals using only raw pointers: /// /// ```rust /// use std::ptr; diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 95663204ec3..b694d3dd49b 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -504,6 +504,7 @@ pub trait LintContext { /// /// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature #[rustc_lint_diagnostics] + #[track_caller] fn opt_span_lint<S: Into<MultiSpan>>( &self, lint: &'static Lint, @@ -542,6 +543,7 @@ pub trait LintContext { /// /// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature #[rustc_lint_diagnostics] + #[track_caller] fn span_lint<S: Into<MultiSpan>>( &self, lint: &'static Lint, diff --git a/compiler/rustc_lint/src/default_could_be_derived.rs b/compiler/rustc_lint/src/default_could_be_derived.rs index 7734f441df2..0bc772d081f 100644 --- a/compiler/rustc_lint/src/default_could_be_derived.rs +++ b/compiler/rustc_lint/src/default_could_be_derived.rs @@ -133,7 +133,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultCouldBeDerived { // } // } // where `something()` would have to be a call or path. - // We have nothing meaninful to do with this. + // We have nothing meaningful to do with this. return; } diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs index a9b04511c6b..263ea6fa070 100644 --- a/compiler/rustc_lint/src/if_let_rescope.rs +++ b/compiler/rustc_lint/src/if_let_rescope.rs @@ -230,7 +230,7 @@ impl IfLetRescope { } } } - // At this point, any `if let` fragment in the cascade is definitely preceeded by `else`, + // At this point, any `if let` fragment in the cascade is definitely preceded by `else`, // so a opening bracket is mandatory before each `match`. add_bracket_to_match_head = true; if let Some(alt) = alt { diff --git a/compiler/rustc_lint/src/reference_casting.rs b/compiler/rustc_lint/src/reference_casting.rs index 1d4d380cb68..6ef9d4e9769 100644 --- a/compiler/rustc_lint/src/reference_casting.rs +++ b/compiler/rustc_lint/src/reference_casting.rs @@ -45,7 +45,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidReferenceCasting { let init = cx.expr_or_init(e); let orig_cast = if init.span != e.span { Some(init.span) } else { None }; - // small cache to avoid recomputing needlesly computing peel_casts of init + // small cache to avoid recomputing needlessly computing peel_casts of init let mut peel_casts = { let mut peel_casts_cache = None; move || *peel_casts_cache.get_or_insert_with(|| peel_casts(cx, init)) diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index a206f71e153..0627f70507c 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -3,6 +3,7 @@ use std::iter; use rustc_ast::util::{classify, parser}; use rustc_ast::{self as ast, ExprKind, HasAttrs as _, StmtKind}; use rustc_attr_data_structures::{AttributeKind, find_attr}; +use rustc_data_structures::fx::FxHashMap; use rustc_errors::{MultiSpan, pluralize}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; @@ -10,6 +11,7 @@ use rustc_hir::{self as hir, LangItem}; use rustc_infer::traits::util::elaborate; use rustc_middle::ty::{self, Ty, adjustment}; use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass}; +use rustc_span::edition::Edition::Edition2015; use rustc_span::{BytePos, Span, Symbol, kw, sym}; use tracing::instrument; @@ -1034,6 +1036,31 @@ pub(crate) struct UnusedParens { /// `1 as (i32) < 2` parses to ExprKind::Lt /// `1 as i32 < 2` parses to i32::<2[missing angle bracket] parens_in_cast_in_lt: Vec<ast::NodeId>, + /// Ty nodes in this map are in TypeNoBounds position. Any bounds they + /// contain may be ambiguous w/r/t trailing `+` operators. + in_no_bounds_pos: FxHashMap<ast::NodeId, NoBoundsException>, +} + +/// Whether parentheses may be omitted from a type without resulting in ambiguity. +/// +/// ``` +/// type Example = Box<dyn Fn() -> &'static (dyn Send) + Sync>; +/// ``` +/// +/// Here, `&'static (dyn Send) + Sync` is a `TypeNoBounds`. As such, it may not directly +/// contain `ImplTraitType` or `TraitObjectType` which is why `(dyn Send)` is parenthesized. +/// However, an exception is made for `ImplTraitTypeOneBound` and `TraitObjectTypeOneBound`. +/// The following is accepted because there is no `+`. +/// +/// ``` +/// type Example = Box<dyn Fn() -> &'static dyn Send>; +/// ``` +enum NoBoundsException { + /// The type must be parenthesized. + None, + /// The type is the last bound of the containing type expression. If it has exactly one bound, + /// parentheses around the type are unnecessary. + OneBound, } impl_lint_pass!(UnusedParens => [UNUSED_PARENS]); @@ -1277,23 +1304,100 @@ impl EarlyLintPass for UnusedParens { ); } ast::TyKind::Paren(r) => { - match &r.kind { - ast::TyKind::TraitObject(..) => {} - ast::TyKind::BareFn(b) - if self.with_self_ty_parens && b.generic_params.len() > 0 => {} - ast::TyKind::ImplTrait(_, bounds) if bounds.len() > 1 => {} - _ => { - let spans = if !ty.span.from_expansion() { + let unused_parens = match &r.kind { + ast::TyKind::ImplTrait(_, bounds) | ast::TyKind::TraitObject(bounds, _) => { + match self.in_no_bounds_pos.get(&ty.id) { + Some(NoBoundsException::None) => false, + Some(NoBoundsException::OneBound) => bounds.len() <= 1, + None => true, + } + } + ast::TyKind::BareFn(b) => { + !self.with_self_ty_parens || b.generic_params.is_empty() + } + _ => true, + }; + + if unused_parens { + let spans = (!ty.span.from_expansion()) + .then(|| { r.span .find_ancestor_inside(ty.span) .map(|r| (ty.span.with_hi(r.lo()), ty.span.with_lo(r.hi()))) + }) + .flatten(); + + self.emit_unused_delims(cx, ty.span, spans, "type", (false, false), false); + } + + self.with_self_ty_parens = false; + } + ast::TyKind::Ref(_, mut_ty) | ast::TyKind::Ptr(mut_ty) => { + self.in_no_bounds_pos.insert(mut_ty.ty.id, NoBoundsException::OneBound); + } + ast::TyKind::TraitObject(bounds, _) | ast::TyKind::ImplTrait(_, bounds) => { + for i in 0..bounds.len() { + let is_last = i == bounds.len() - 1; + + if let ast::GenericBound::Trait(poly_trait_ref) = &bounds[i] { + let fn_with_explicit_ret_ty = if let [.., segment] = + &*poly_trait_ref.trait_ref.path.segments + && let Some(args) = segment.args.as_ref() + && let ast::GenericArgs::Parenthesized(paren_args) = &**args + && let ast::FnRetTy::Ty(ret_ty) = &paren_args.output + { + self.in_no_bounds_pos.insert( + ret_ty.id, + if is_last { + NoBoundsException::OneBound + } else { + NoBoundsException::None + }, + ); + + true } else { - None + false }; - self.emit_unused_delims(cx, ty.span, spans, "type", (false, false), false); + + // In edition 2015, dyn is a contextual keyword and `dyn::foo::Bar` is + // parsed as a path, so parens are necessary to disambiguate. See + // - tests/ui/lint/unused/unused-parens-trait-obj-e2015.rs and + // - https://doc.rust-lang.org/reference/types/trait-object.html#r-type.trait-object.syntax-edition2018 + let dyn2015_exception = cx.sess().psess.edition == Edition2015 + && matches!(ty.kind, ast::TyKind::TraitObject(..)) + && i == 0 + && poly_trait_ref + .trait_ref + .path + .segments + .first() + .map(|s| s.ident.name == kw::PathRoot) + .unwrap_or(false); + + if let ast::Parens::Yes = poly_trait_ref.parens + && (is_last || !fn_with_explicit_ret_ty) + && !dyn2015_exception + { + let s = poly_trait_ref.span; + let spans = (!s.from_expansion()).then(|| { + ( + s.with_hi(s.lo() + rustc_span::BytePos(1)), + s.with_lo(s.hi() - rustc_span::BytePos(1)), + ) + }); + + self.emit_unused_delims( + cx, + poly_trait_ref.span, + spans, + "type", + (false, false), + false, + ); + } } } - self.with_self_ty_parens = false; } _ => {} } @@ -1303,6 +1407,10 @@ impl EarlyLintPass for UnusedParens { <Self as UnusedDelimLint>::check_item(self, cx, item) } + fn check_item_post(&mut self, _: &EarlyContext<'_>, _: &rustc_ast::Item) { + self.in_no_bounds_pos.clear(); + } + fn enter_where_predicate(&mut self, _: &EarlyContext<'_>, pred: &ast::WherePredicate) { use rustc_ast::{WhereBoundPredicate, WherePredicateKind}; if let WherePredicateKind::BoundPredicate(WhereBoundPredicate { diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 10ac14a2fbf..b37548b281c 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -1224,7 +1224,7 @@ declare_lint! { /// /// ### Explanation /// - /// A public `use` declaration should not be used to publicly re-export a + /// A public `use` declaration should not be used to publically re-export a /// private `extern crate`. `pub extern crate` should be used instead. /// /// This was historically allowed, but is not the intended behavior diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index 42d006ef301..1006ea3ba10 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -177,7 +177,7 @@ decl_derive! { [PrintAttribute] => /// Derives `PrintAttribute` for `AttributeKind`. /// This macro is pretty specific to `rustc_attr_data_structures` and likely not that useful in - /// other places. It's deriving something close to `Debug` without printing some extraenous + /// other places. It's deriving something close to `Debug` without printing some extraneous /// things like spans. print_attribute::print_attribute } diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 2196f71299a..5821ffa3a30 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -273,8 +273,8 @@ fn add_query_desc_cached_impl( // macro producing a higher order macro that has all its token in the macro declaration we lose // any meaningful spans, resulting in rust-analyzer being unable to make the connection between // the query name and the corresponding providers field. The trick to fix this is to have - // `rustc_queries` emit a field access with the given name's span which allows it to succesfully - // show references / go to definition to the correspondig provider assignment which is usually + // `rustc_queries` emit a field access with the given name's span which allows it to successfully + // show references / go to definition to the corresponding provider assignment which is usually // the more interesting place. let ra_hint = quote! { let crate::query::Providers { #name: _, .. }; @@ -413,7 +413,6 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream { "Query {name} cannot be both `feedable` and `eval_always`." ); feedable_queries.extend(quote! { - #(#doc_comments)* [#attribute_stream] fn #name(#arg) #result, }); } diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 2c882b84c58..e65c7a68426 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -24,8 +24,7 @@ use rustc_middle::ty::data_structures::IndexSet; use rustc_middle::ty::{TyCtxt, TyCtxtFeed}; use rustc_proc_macro::bridge::client::ProcMacro; use rustc_session::config::{ - self, CrateType, ExtendedTargetModifierInfo, ExternLocation, OptionsTargetModifiers, - TargetModifier, + CrateType, ExtendedTargetModifierInfo, ExternLocation, OptionsTargetModifiers, TargetModifier, }; use rustc_session::cstore::{CrateDepKind, CrateSource, ExternCrate, ExternCrateSource}; use rustc_session::lint::{self, BuiltinLintDiag}; @@ -33,11 +32,11 @@ use rustc_session::output::validate_crate_name; use rustc_session::search_paths::PathKind; use rustc_span::edition::Edition; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, sym}; -use rustc_target::spec::{PanicStrategy, Target, TargetTuple}; +use rustc_target::spec::{PanicStrategy, Target}; use tracing::{debug, info, trace}; use crate::errors; -use crate::locator::{CrateError, CrateLocator, CratePaths}; +use crate::locator::{CrateError, CrateLocator, CratePaths, CrateRejections}; use crate::rmeta::{ CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob, TargetModifiers, }; @@ -684,61 +683,67 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { fn load_proc_macro<'b>( &self, locator: &mut CrateLocator<'b>, + crate_rejections: &mut CrateRejections, path_kind: PathKind, host_hash: Option<Svh>, ) -> Result<Option<(LoadResult, Option<Library>)>, CrateError> where 'a: 'b, { - // Use a new crate locator so trying to load a proc macro doesn't affect the error - // message we emit - let mut proc_macro_locator = locator.clone(); - - // Try to load a proc macro - proc_macro_locator.is_proc_macro = true; - - // Load the proc macro crate for the target - let (locator, target_result) = if self.sess.opts.unstable_opts.dual_proc_macros { - proc_macro_locator.reset(); - let result = match self.load(&mut proc_macro_locator)? { - Some(LoadResult::Previous(cnum)) => { - return Ok(Some((LoadResult::Previous(cnum), None))); - } - Some(LoadResult::Loaded(library)) => Some(LoadResult::Loaded(library)), - None => return Ok(None), - }; - locator.hash = host_hash; - // Use the locator when looking for the host proc macro crate, as that is required - // so we want it to affect the error message - (locator, result) - } else { - (&mut proc_macro_locator, None) - }; + if self.sess.opts.unstable_opts.dual_proc_macros { + // Use a new crate locator and crate rejections so trying to load a proc macro doesn't + // affect the error message we emit + let mut proc_macro_locator = locator.clone(); + + // Try to load a proc macro + proc_macro_locator.for_target_proc_macro(self.sess, path_kind); + + // Load the proc macro crate for the target + let target_result = + match self.load(&mut proc_macro_locator, &mut CrateRejections::default())? { + Some(LoadResult::Previous(cnum)) => { + return Ok(Some((LoadResult::Previous(cnum), None))); + } + Some(LoadResult::Loaded(library)) => Some(LoadResult::Loaded(library)), + None => return Ok(None), + }; - // Load the proc macro crate for the host + // Use the existing crate_rejections as we want the error message to be affected by + // loading the host proc macro. + *crate_rejections = CrateRejections::default(); - locator.reset(); - locator.is_proc_macro = true; - locator.target = &self.sess.host; - locator.tuple = TargetTuple::from_tuple(config::host_tuple()); - locator.filesearch = self.sess.host_filesearch(); - locator.path_kind = path_kind; + // Load the proc macro crate for the host + locator.for_proc_macro(self.sess, path_kind); - let Some(host_result) = self.load(locator)? else { - return Ok(None); - }; + locator.hash = host_hash; + + let Some(host_result) = self.load(locator, crate_rejections)? else { + return Ok(None); + }; - Ok(Some(if self.sess.opts.unstable_opts.dual_proc_macros { let host_result = match host_result { LoadResult::Previous(..) => { panic!("host and target proc macros must be loaded in lock-step") } LoadResult::Loaded(library) => library, }; - (target_result.unwrap(), Some(host_result)) + Ok(Some((target_result.unwrap(), Some(host_result)))) } else { - (host_result, None) - })) + // Use a new crate locator and crate rejections so trying to load a proc macro doesn't + // affect the error message we emit + let mut proc_macro_locator = locator.clone(); + + // Load the proc macro crate for the host + proc_macro_locator.for_proc_macro(self.sess, path_kind); + + let Some(host_result) = + self.load(&mut proc_macro_locator, &mut CrateRejections::default())? + else { + return Ok(None); + }; + + Ok(Some((host_result, None))) + } } fn resolve_crate( @@ -799,15 +804,21 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { extra_filename, path_kind, ); + let mut crate_rejections = CrateRejections::default(); - match self.load(&mut locator)? { + match self.load(&mut locator, &mut crate_rejections)? { Some(res) => (res, None), None => { info!("falling back to loading proc_macro"); dep_kind = CrateDepKind::MacrosOnly; - match self.load_proc_macro(&mut locator, path_kind, host_hash)? { + match self.load_proc_macro( + &mut locator, + &mut crate_rejections, + path_kind, + host_hash, + )? { Some(res) => res, - None => return Err(locator.into_error(dep_root.cloned())), + None => return Err(locator.into_error(crate_rejections, dep_root.cloned())), } } } @@ -837,8 +848,12 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } } - fn load(&self, locator: &mut CrateLocator<'_>) -> Result<Option<LoadResult>, CrateError> { - let Some(library) = locator.maybe_load_library_crate()? else { + fn load( + &self, + locator: &CrateLocator<'_>, + crate_rejections: &mut CrateRejections, + ) -> Result<Option<LoadResult>, CrateError> { + let Some(library) = locator.maybe_load_library_crate(crate_rejections)? else { return Ok(None); }; diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 941f16bd960..c30cfd1fcf7 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -224,11 +224,11 @@ use rustc_data_structures::owned_slice::{OwnedSlice, slice_owned}; use rustc_data_structures::svh::Svh; use rustc_errors::{DiagArgValue, IntoDiagArg}; use rustc_fs_util::try_canonicalize; -use rustc_session::Session; use rustc_session::cstore::CrateSource; use rustc_session::filesearch::FileSearch; use rustc_session::search_paths::PathKind; use rustc_session::utils::CanonicalizedPath; +use rustc_session::{Session, config}; use rustc_span::{Span, Symbol}; use rustc_target::spec::{Target, TargetTuple}; use tempfile::Builder as TempFileBuilder; @@ -251,14 +251,11 @@ pub(crate) struct CrateLocator<'a> { exact_paths: Vec<CanonicalizedPath>, pub hash: Option<Svh>, extra_filename: Option<&'a str>, - pub target: &'a Target, - pub tuple: TargetTuple, - pub filesearch: &'a FileSearch, - pub is_proc_macro: bool, - - pub path_kind: PathKind, - // Mutable in-progress state or output. - crate_rejections: CrateRejections, + target: &'a Target, + tuple: TargetTuple, + filesearch: &'a FileSearch, + is_proc_macro: bool, + path_kind: PathKind, } #[derive(Clone, Debug)] @@ -346,34 +343,46 @@ impl<'a> CrateLocator<'a> { filesearch: sess.target_filesearch(), path_kind, is_proc_macro: false, - crate_rejections: CrateRejections::default(), } } - pub(crate) fn reset(&mut self) { - self.crate_rejections.via_hash.clear(); - self.crate_rejections.via_triple.clear(); - self.crate_rejections.via_kind.clear(); - self.crate_rejections.via_version.clear(); - self.crate_rejections.via_filename.clear(); - self.crate_rejections.via_invalid.clear(); + pub(crate) fn for_proc_macro(&mut self, sess: &'a Session, path_kind: PathKind) { + self.is_proc_macro = true; + self.target = &sess.host; + self.tuple = TargetTuple::from_tuple(config::host_tuple()); + self.filesearch = sess.host_filesearch(); + self.path_kind = path_kind; } - pub(crate) fn maybe_load_library_crate(&mut self) -> Result<Option<Library>, CrateError> { + pub(crate) fn for_target_proc_macro(&mut self, sess: &'a Session, path_kind: PathKind) { + self.is_proc_macro = true; + self.target = &sess.target; + self.tuple = sess.opts.target_triple.clone(); + self.filesearch = sess.target_filesearch(); + self.path_kind = path_kind; + } + + pub(crate) fn maybe_load_library_crate( + &self, + crate_rejections: &mut CrateRejections, + ) -> Result<Option<Library>, CrateError> { if !self.exact_paths.is_empty() { - return self.find_commandline_library(); + return self.find_commandline_library(crate_rejections); } let mut seen_paths = FxHashSet::default(); if let Some(extra_filename) = self.extra_filename { - if let library @ Some(_) = self.find_library_crate(extra_filename, &mut seen_paths)? { + if let library @ Some(_) = + self.find_library_crate(crate_rejections, extra_filename, &mut seen_paths)? + { return Ok(library); } } - self.find_library_crate("", &mut seen_paths) + self.find_library_crate(crate_rejections, "", &mut seen_paths) } fn find_library_crate( - &mut self, + &self, + crate_rejections: &mut CrateRejections, extra_prefix: &str, seen_paths: &mut FxHashSet<PathBuf>, ) -> Result<Option<Library>, CrateError> { @@ -437,8 +446,8 @@ impl<'a> CrateLocator<'a> { let (rlibs, rmetas, dylibs, interfaces) = candidates.entry(hash).or_default(); { - // As a perforamnce optimisation we canonicalize the path and skip - // ones we've already seeen. This allows us to ignore crates + // As a performance optimisation we canonicalize the path and skip + // ones we've already seen. This allows us to ignore crates // we know are exactual equal to ones we've already found. // Going to the same crate through different symlinks does not change the result. let path = try_canonicalize(&spf.path) @@ -465,7 +474,7 @@ impl<'a> CrateLocator<'a> { .flatten() { for (_, spf) in static_matches { - self.crate_rejections.via_kind.push(CrateMismatch { + crate_rejections.via_kind.push(CrateMismatch { path: spf.path.to_path_buf(), got: "static".to_string(), }); @@ -483,7 +492,9 @@ impl<'a> CrateLocator<'a> { // search is being performed for. let mut libraries = FxIndexMap::default(); for (_hash, (rlibs, rmetas, dylibs, interfaces)) in candidates { - if let Some((svh, lib)) = self.extract_lib(rlibs, rmetas, dylibs, interfaces)? { + if let Some((svh, lib)) = + self.extract_lib(crate_rejections, rlibs, rmetas, dylibs, interfaces)? + { libraries.insert(svh, lib); } } @@ -495,13 +506,11 @@ impl<'a> CrateLocator<'a> { 0 => Ok(None), 1 => Ok(Some(libraries.into_iter().next().unwrap().1)), _ => { - let mut libraries: Vec<_> = libraries.into_values().collect(); - - libraries.sort_by_cached_key(|lib| lib.source.paths().next().unwrap().clone()); - let candidates = libraries - .iter() + let mut candidates: Vec<PathBuf> = libraries + .into_values() .map(|lib| lib.source.paths().next().unwrap().clone()) - .collect::<Vec<_>>(); + .collect(); + candidates.sort(); Err(CrateError::MultipleCandidates( self.crate_name, @@ -514,7 +523,8 @@ impl<'a> CrateLocator<'a> { } fn extract_lib( - &mut self, + &self, + crate_rejections: &mut CrateRejections, rlibs: FxIndexMap<PathBuf, PathKind>, rmetas: FxIndexMap<PathBuf, PathKind>, dylibs: FxIndexMap<PathBuf, PathKind>, @@ -526,10 +536,11 @@ impl<'a> CrateLocator<'a> { // Make sure there's at most one rlib and at most one dylib. // // See comment in `extract_one` below. - let rmeta = self.extract_one(rmetas, CrateFlavor::Rmeta, &mut slot)?; - let rlib = self.extract_one(rlibs, CrateFlavor::Rlib, &mut slot)?; - let sdylib_interface = self.extract_one(interfaces, CrateFlavor::SDylib, &mut slot)?; - let dylib = self.extract_one(dylibs, CrateFlavor::Dylib, &mut slot)?; + let rmeta = self.extract_one(crate_rejections, rmetas, CrateFlavor::Rmeta, &mut slot)?; + let rlib = self.extract_one(crate_rejections, rlibs, CrateFlavor::Rlib, &mut slot)?; + let sdylib_interface = + self.extract_one(crate_rejections, interfaces, CrateFlavor::SDylib, &mut slot)?; + let dylib = self.extract_one(crate_rejections, dylibs, CrateFlavor::Dylib, &mut slot)?; if sdylib_interface.is_some() && dylib.is_none() { return Err(CrateError::FullMetadataNotFound(self.crate_name, CrateFlavor::SDylib)); @@ -563,7 +574,8 @@ impl<'a> CrateLocator<'a> { // // The `PathBuf` in `slot` will only be used for diagnostic purposes. fn extract_one( - &mut self, + &self, + crate_rejections: &mut CrateRejections, m: FxIndexMap<PathBuf, PathKind>, flavor: CrateFlavor, slot: &mut Option<(Svh, MetadataBlob, PathBuf, CrateFlavor)>, @@ -605,7 +617,7 @@ impl<'a> CrateLocator<'a> { Some(self.crate_name), ) { Ok(blob) => { - if let Some(h) = self.crate_matches(&blob, &lib) { + if let Some(h) = self.crate_matches(crate_rejections, &blob, &lib) { (h, blob) } else { info!("metadata mismatch"); @@ -620,7 +632,7 @@ impl<'a> CrateLocator<'a> { "Rejecting via version: expected {} got {}", expected_version, found_version ); - self.crate_rejections + crate_rejections .via_version .push(CrateMismatch { path: lib, got: found_version }); continue; @@ -635,7 +647,7 @@ impl<'a> CrateLocator<'a> { // The file was present and created by the same compiler version, but we // couldn't load it for some reason. Give a hard error instead of silently // ignoring it, but only if we would have given an error anyway. - self.crate_rejections.via_invalid.push(CrateMismatch { path: lib, got: err }); + crate_rejections.via_invalid.push(CrateMismatch { path: lib, got: err }); continue; } Err(err @ MetadataError::NotPresent(_)) => { @@ -713,7 +725,12 @@ impl<'a> CrateLocator<'a> { } } - fn crate_matches(&mut self, metadata: &MetadataBlob, libpath: &Path) -> Option<Svh> { + fn crate_matches( + &self, + crate_rejections: &mut CrateRejections, + metadata: &MetadataBlob, + libpath: &Path, + ) -> Option<Svh> { let header = metadata.get_header(); if header.is_proc_macro_crate != self.is_proc_macro { info!( @@ -730,7 +747,7 @@ impl<'a> CrateLocator<'a> { if header.triple != self.tuple { info!("Rejecting via crate triple: expected {} got {}", self.tuple, header.triple); - self.crate_rejections.via_triple.push(CrateMismatch { + crate_rejections.via_triple.push(CrateMismatch { path: libpath.to_path_buf(), got: header.triple.to_string(), }); @@ -741,7 +758,7 @@ impl<'a> CrateLocator<'a> { if let Some(expected_hash) = self.hash { if hash != expected_hash { info!("Rejecting via hash: expected {} got {}", expected_hash, hash); - self.crate_rejections + crate_rejections .via_hash .push(CrateMismatch { path: libpath.to_path_buf(), got: hash.to_string() }); return None; @@ -751,7 +768,10 @@ impl<'a> CrateLocator<'a> { Some(hash) } - fn find_commandline_library(&mut self) -> Result<Option<Library>, CrateError> { + fn find_commandline_library( + &self, + crate_rejections: &mut CrateRejections, + ) -> Result<Option<Library>, CrateError> { // First, filter out all libraries that look suspicious. We only accept // files which actually exist that have the correct naming scheme for // rlibs/dylibs. @@ -796,24 +816,28 @@ impl<'a> CrateLocator<'a> { dylibs.insert(loc_canon.clone(), PathKind::ExternFlag); continue; } - self.crate_rejections + crate_rejections .via_filename .push(CrateMismatch { path: loc_orig.clone(), got: String::new() }); } // Extract the dylib/rlib/rmeta triple. - self.extract_lib(rlibs, rmetas, dylibs, sdylib_interfaces) + self.extract_lib(crate_rejections, rlibs, rmetas, dylibs, sdylib_interfaces) .map(|opt| opt.map(|(_, lib)| lib)) } - pub(crate) fn into_error(self, dep_root: Option<CratePaths>) -> CrateError { + pub(crate) fn into_error( + self, + crate_rejections: CrateRejections, + dep_root: Option<CratePaths>, + ) -> CrateError { CrateError::LocatorCombined(Box::new(CombinedLocatorError { crate_name: self.crate_name, dep_root, triple: self.tuple, dll_prefix: self.target.dll_prefix.to_string(), dll_suffix: self.target.dll_suffix.to_string(), - crate_rejections: self.crate_rejections, + crate_rejections, })) } } @@ -993,7 +1017,7 @@ struct CrateMismatch { } #[derive(Clone, Debug, Default)] -struct CrateRejections { +pub(crate) struct CrateRejections { via_hash: Vec<CrateMismatch>, via_triple: Vec<CrateMismatch>, via_kind: Vec<CrateMismatch>, diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 4198b198ab1..d2cadc96b63 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -799,7 +799,7 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes> /// Initialize all previously uninitialized bytes in the entire allocation, and set /// provenance of everything to `Wildcard`. Before calling this, make sure all /// provenance in this allocation is exposed! - pub fn prepare_for_native_write(&mut self) -> AllocResult { + pub fn prepare_for_native_access(&mut self) { let full_range = AllocRange { start: Size::ZERO, size: Size::from_bytes(self.len()) }; // Overwrite uninitialized bytes with 0, to ensure we don't leak whatever their value happens to be. for chunk in self.init_mask.range_as_init_chunks(full_range) { @@ -814,13 +814,6 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes> // Set provenance of all bytes to wildcard. self.provenance.write_wildcards(self.len()); - - // Also expose the provenance of the interpreter-level allocation, so it can - // be written by FFI. The `black_box` is defensive programming as LLVM likes - // to (incorrectly) optimize away ptr2int casts whose result is unused. - std::hint::black_box(self.get_bytes_unchecked_raw_mut().expose_provenance()); - - Ok(()) } /// Remove all provenance in the given memory range. diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs index c9525df1f79..63608947eb3 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs @@ -120,7 +120,7 @@ impl<Prov: Provenance> ProvenanceMap<Prov> { } } - /// Check if here is ptr-sized provenance at the given index. + /// Check if there is ptr-sized provenance at the given index. /// Does not mean anything for bytewise provenance! But can be useful as an optimization. pub fn get_ptr(&self, offset: Size) -> Option<Prov> { self.ptrs.get(&offset).copied() diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 41a166083d0..8acb8fa9f80 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -116,7 +116,7 @@ impl<'tcx> From<ErrorHandled> for ValTreeCreationError<'tcx> { impl<'tcx> From<InterpErrorInfo<'tcx>> for ValTreeCreationError<'tcx> { fn from(err: InterpErrorInfo<'tcx>) -> Self { - // An error ocurred outside the const-eval query, as part of constructing the valtree. We + // An error occurred outside the const-eval query, as part of constructing the valtree. We // don't currently preserve the details of this error, since `InterpErrorInfo` cannot be put // into a query result and it can only be access of some mutable or external memory. let (_kind, backtrace) = err.into_parts(); diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 33e97766a02..e819aa2d8f8 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -262,7 +262,7 @@ pub struct Body<'tcx> { /// us to see the difference and forego optimization on the inlined promoted items. pub phase: MirPhase, - /// How many passses we have executed since starting the current phase. Used for debug output. + /// How many passes we have executed since starting the current phase. Used for debug output. pub pass_count: usize, pub source: MirSource<'tcx>, diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 92eefd89848..6039a03aa29 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -381,7 +381,7 @@ pub enum StatementKind<'tcx> { /// computing these locals. /// /// If the local is already allocated, calling `StorageLive` again will implicitly free the - /// local and then allocate fresh uninitilized memory. If a local is already deallocated, + /// local and then allocate fresh uninitialized memory. If a local is already deallocated, /// calling `StorageDead` again is a NOP. StorageLive(Local), diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 3e68f0f784e..8c20e71e26a 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -355,7 +355,7 @@ rustc_queries! { /// Returns whether the type alias given by `DefId` is lazy. /// /// I.e., if the type alias expands / ought to expand to a [free] [alias type] - /// instead of the underyling aliased type. + /// instead of the underlying aliased type. /// /// Relevant for features `lazy_type_alias` and `type_alias_impl_trait`. /// @@ -440,7 +440,6 @@ rustc_queries! { 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( @@ -1093,13 +1092,6 @@ rustc_queries! { separate_provide_extern } - /// Given an impl trait in trait `opaque_ty_def_id`, create and return the corresponding - /// associated item. - query associated_type_for_impl_trait_in_trait(opaque_ty_def_id: LocalDefId) -> LocalDefId { - desc { |tcx| "creating the associated item corresponding to the opaque type `{}`", tcx.def_path_str(opaque_ty_def_id.to_def_id()) } - cache_on_disk_if { true } - } - /// Given an `impl_id`, return the trait it implements along with some header information. /// Return `None` if this is an inherent impl. query impl_trait_header(impl_id: DefId) -> Option<ty::ImplTraitHeader<'tcx>> { diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index bda8dcadbce..730c1147684 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -380,11 +380,11 @@ pub enum ExprKind<'tcx> { }, /// A `#[loop_match] loop { state = 'blk: { match state { ... } } }` expression. LoopMatch { - /// The state variable that is updated, and also the scrutinee of the match. + /// The state variable that is updated. + /// The `match_data.scrutinee` is the same variable, but with a different span. state: ExprId, region_scope: region::Scope, - arms: Box<[ArmId]>, - match_span: Span, + match_data: Box<LoopMatchMatchData>, }, /// Special expression representing the `let` part of an `if let` or similar construct /// (including `if let` guards in match arms, and let-chains formed by `&&`). @@ -599,6 +599,14 @@ pub struct Arm<'tcx> { pub span: Span, } +/// The `match` part of a `#[loop_match]` +#[derive(Clone, Debug, HashStable)] +pub struct LoopMatchMatchData { + pub scrutinee: ExprId, + pub arms: Box<[ArmId]>, + pub span: Span, +} + #[derive(Copy, Clone, Debug, HashStable)] pub enum LogicalOp { /// The `&&` operator. diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index c9ef723aea4..dcfa6c4db32 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -2,6 +2,7 @@ use super::{ AdtExpr, AdtExprBase, Arm, Block, ClosureExpr, Expr, ExprKind, InlineAsmExpr, InlineAsmOperand, Pat, PatKind, Stmt, StmtKind, Thir, }; +use crate::thir::LoopMatchMatchData; /// Every `walk_*` method uses deconstruction to access fields of structs and /// enums. This will result in a compile error if a field is added, which makes @@ -83,7 +84,8 @@ pub fn walk_expr<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>( visitor.visit_pat(pat); } Loop { body } => visitor.visit_expr(&visitor.thir()[body]), - LoopMatch { state: scrutinee, ref arms, .. } | Match { scrutinee, ref arms, .. } => { + LoopMatch { match_data: box LoopMatchMatchData { scrutinee, ref arms, .. }, .. } + | Match { scrutinee, ref arms, .. } => { visitor.visit_expr(&visitor.thir()[scrutinee]); for &arm in &**arms { visitor.visit_arm(&visitor.thir()[arm]); diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index f5c55f96875..efa47b57cf3 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2287,7 +2287,7 @@ impl<'tcx> TyCtxt<'tcx> { } /// All traits in the crate graph, including those not visible to the user. - pub fn all_traits(self) -> impl Iterator<Item = DefId> { + pub fn all_traits_including_private(self) -> impl Iterator<Item = DefId> { iter::once(LOCAL_CRATE) .chain(self.crates(()).iter().copied()) .flat_map(move |cnum| self.traits(cnum).iter().copied()) diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 68adfb3cdb3..21b7500e46f 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -71,7 +71,7 @@ pub enum InstanceKind<'tcx> { /// - coroutines Item(DefId), - /// An intrinsic `fn` item (with`#[rustc_instrinsic]`). + /// An intrinsic `fn` item (with`#[rustc_intrinsic]`). /// /// Alongside `Virtual`, this is the only `InstanceKind` that does not have its own callable MIR. /// Instead, codegen and const eval "magically" evaluate calls to intrinsics purely in the @@ -445,10 +445,10 @@ impl<'tcx> fmt::Display for Instance<'tcx> { } } -// async_drop_in_place<T>::coroutine.poll, when T is a standart coroutine, +// async_drop_in_place<T>::coroutine.poll, when T is a standard coroutine, // should be resolved to this coroutine's future_drop_poll (through FutureDropPollShim proxy). // async_drop_in_place<async_drop_in_place<T>::coroutine>::coroutine.poll, -// when T is a standart coroutine, should be resolved to this coroutine's future_drop_poll. +// when T is a standard coroutine, should be resolved to this coroutine's future_drop_poll. // async_drop_in_place<async_drop_in_place<T>::coroutine>::coroutine.poll, // when T is not a coroutine, should be resolved to the innermost // async_drop_in_place<T>::coroutine's poll function (through FutureDropPollShim proxy) diff --git a/compiler/rustc_middle/src/ty/significant_drop_order.rs b/compiler/rustc_middle/src/ty/significant_drop_order.rs index 561f84192b4..5ada9ecc80c 100644 --- a/compiler/rustc_middle/src/ty/significant_drop_order.rs +++ b/compiler/rustc_middle/src/ty/significant_drop_order.rs @@ -70,7 +70,7 @@ fn true_significant_drop_ty<'tcx>( } } -/// Returns the list of types with a "potentially sigificant" that may be dropped +/// Returns the list of types with a "potentially significant" that may be dropped /// by dropping a value of type `ty`. #[instrument(level = "trace", skip(tcx, typing_env))] pub fn extract_component_raw<'tcx>( diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 399a6d6ebc5..7a1890226c9 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1676,7 +1676,7 @@ impl<'tcx> Ty<'tcx> { /// This is particularly useful for getting the type of the result of /// [`UnOp::PtrMetadata`](crate::mir::UnOp::PtrMetadata). /// - /// Panics if `self` is not dereferencable. + /// Panics if `self` is not dereferenceable. #[track_caller] pub fn pointee_metadata_ty_or_projection(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { let Some(pointee_ty) = self.builtin_deref(true) else { diff --git a/compiler/rustc_mir_build/src/builder/expr/into.rs b/compiler/rustc_mir_build/src/builder/expr/into.rs index fe3d072fa88..82b883a99a1 100644 --- a/compiler/rustc_mir_build/src/builder/expr/into.rs +++ b/compiler/rustc_mir_build/src/builder/expr/into.rs @@ -245,7 +245,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { None }) } - ExprKind::LoopMatch { state, region_scope, match_span, ref arms } => { + ExprKind::LoopMatch { + state, + region_scope, + match_data: box LoopMatchMatchData { box ref arms, span: match_span, scrutinee }, + } => { // Intuitively, this is a combination of a loop containing a labeled block // containing a match. // @@ -292,8 +296,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Logic for `match`. let scrutinee_place_builder = - unpack!(body_block = this.as_place_builder(body_block, state)); - let scrutinee_span = this.thir.exprs[state].span; + unpack!(body_block = this.as_place_builder(body_block, scrutinee)); + let scrutinee_span = this.thir.exprs[scrutinee].span; let match_start_span = match_span.shrink_to_lo().to(scrutinee_span); let mut patterns = Vec::with_capacity(arms.len()); @@ -335,7 +339,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { move |this| { this.in_breakable_scope(None, state_place, expr_span, |this| { Some(this.in_const_continuable_scope( - arms.clone(), + Box::from(arms), built_tree.clone(), state_place, expr_span, diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs index 9600067a85f..2c29b862841 100644 --- a/compiler/rustc_mir_build/src/builder/matches/mod.rs +++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs @@ -2970,6 +2970,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } Constructor::Wildcard => true, + // Opaque patterns must not be matched on structurally. + Constructor::Opaque(_) => false, + // These we may eventually support: Constructor::Struct | Constructor::Ref @@ -2980,8 +2983,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | Constructor::Str(_) => bug!("unsupported pattern constructor {:?}", pat.ctor()), // These should never occur here: - Constructor::Opaque(_) - | Constructor::Never + Constructor::Never | Constructor::NonExhaustive | Constructor::Hidden | Constructor::Missing diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 20e836f6bf2..16b49bf384c 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -1230,7 +1230,6 @@ pub(crate) struct ConstContinueMissingValue { #[derive(Diagnostic)] #[diag(mir_build_const_continue_unknown_jump_target)] -#[note] pub(crate) struct ConstContinueUnknownJumpTarget { #[primary_span] pub span: Span, diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 5197e93fda7..b694409f327 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -983,8 +983,11 @@ impl<'tcx> ThirBuildCx<'tcx> { data: region::ScopeData::Node, }, - arms: arms.iter().map(|a| self.convert_arm(a)).collect(), - match_span: block_body_expr.span, + match_data: Box::new(LoopMatchMatchData { + scrutinee: self.mirror_expr(scrutinee), + arms: arms.iter().map(|a| self.convert_arm(a)).collect(), + span: block_body_expr.span, + }), } } else { let block_ty = self.typeck_results.node_type(body.hir_id); 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 41fbabc2539..b7b160c738d 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -6,7 +6,7 @@ use rustc_errors::codes::*; use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, struct_span_code_err}; use rustc_hir::def::*; use rustc_hir::def_id::LocalDefId; -use rustc_hir::{self as hir, BindingMode, ByRef, HirId}; +use rustc_hir::{self as hir, BindingMode, ByRef, HirId, MatchSource}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::Level; use rustc_middle::bug; @@ -154,6 +154,12 @@ impl<'p, 'tcx> Visitor<'p, 'tcx> for MatchVisitor<'p, 'tcx> { ExprKind::Match { scrutinee, box ref arms, match_source } => { self.check_match(scrutinee, arms, match_source, ex.span); } + ExprKind::LoopMatch { + match_data: box LoopMatchMatchData { scrutinee, box ref arms, span }, + .. + } => { + self.check_match(scrutinee, arms, MatchSource::Normal, span); + } ExprKind::Let { box ref pat, expr } => { self.check_let(pat, Some(expr), ex.span); } 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 003ad170861..6d617d43c2a 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 @@ -365,11 +365,11 @@ fn extend_type_not_partial_eq<'tcx>( struct UsedParamsNeedInstantiationVisitor<'tcx> { tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, - /// The user has written `impl PartialEq for Ty` which means it's non-structual. + /// The user has written `impl PartialEq for Ty` which means it's non-structural. adts_with_manual_partialeq: FxHashSet<Span>, /// The type has no `PartialEq` implementation, neither manual or derived. adts_without_partialeq: FxHashSet<Span>, - /// The user has written `impl PartialEq for Ty` which means it's non-structual, + /// The user has written `impl PartialEq for Ty` which means it's non-structural, /// but we don't have a span to point at, so we'll just add them as a `note`. manual: FxHashSet<Ty<'tcx>>, /// The type has no `PartialEq` implementation, neither manual or derived, but diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs index 1507b6b8c06..5efc4be2de2 100644 --- a/compiler/rustc_mir_build/src/thir/print.rs +++ b/compiler/rustc_mir_build/src/thir/print.rs @@ -318,18 +318,23 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { self.print_expr(*body, depth_lvl + 2); print_indented!(self, ")", depth_lvl); } - LoopMatch { state, region_scope, match_span, arms } => { + LoopMatch { state, region_scope, match_data } => { print_indented!(self, "LoopMatch {", depth_lvl); print_indented!(self, "state:", depth_lvl + 1); self.print_expr(*state, depth_lvl + 2); print_indented!(self, format!("region_scope: {:?}", region_scope), depth_lvl + 1); - print_indented!(self, format!("match_span: {:?}", match_span), depth_lvl + 1); - - print_indented!(self, "arms: [", depth_lvl + 1); - for arm_id in arms.iter() { - self.print_arm(*arm_id, depth_lvl + 2); + print_indented!(self, "match_data:", depth_lvl + 1); + print_indented!(self, "LoopMatchMatchData {", depth_lvl + 2); + print_indented!(self, format!("span: {:?}", match_data.span), depth_lvl + 3); + print_indented!(self, "scrutinee:", depth_lvl + 3); + self.print_expr(match_data.scrutinee, depth_lvl + 4); + + print_indented!(self, "arms: [", depth_lvl + 3); + for arm_id in match_data.arms.iter() { + self.print_arm(*arm_id, depth_lvl + 4); } - print_indented!(self, "]", depth_lvl + 1); + print_indented!(self, "]", depth_lvl + 3); + print_indented!(self, "}", depth_lvl + 2); print_indented!(self, "}", depth_lvl); } Let { expr, pat } => { diff --git a/compiler/rustc_mir_transform/src/check_enums.rs b/compiler/rustc_mir_transform/src/check_enums.rs index 240da87ab27..33a87cb9873 100644 --- a/compiler/rustc_mir_transform/src/check_enums.rs +++ b/compiler/rustc_mir_transform/src/check_enums.rs @@ -120,6 +120,7 @@ enum EnumCheckType<'tcx> { }, } +#[derive(Debug, Copy, Clone)] struct TyAndSize<'tcx> { pub ty: Ty<'tcx>, pub size: Size, @@ -310,7 +311,7 @@ fn insert_discr_cast_to_u128<'tcx>( StatementKind::Assign(Box::new((discr_in_discr_ty, rvalue))), )); - // Cast the discriminant to a u128 (base for comparisions of enum discriminants). + // Cast the discriminant to a u128 (base for comparisons of enum discriminants). let const_u128 = Ty::new_uint(tcx, ty::UintTy::U128); let rvalue = Rvalue::Cast(CastKind::IntToInt, Operand::Copy(discr_in_discr_ty), const_u128); let discr = local_decls.push(LocalDecl::with_source_info(const_u128, source_info)).into(); @@ -337,7 +338,7 @@ fn insert_direct_enum_check<'tcx>( let invalid_discr_block_data = BasicBlockData::new(None, false); let invalid_discr_block = basic_blocks.push(invalid_discr_block_data); let block_data = &mut basic_blocks[current_block]; - let discr = insert_discr_cast_to_u128( + let discr_place = insert_discr_cast_to_u128( tcx, local_decls, block_data, @@ -348,13 +349,34 @@ fn insert_direct_enum_check<'tcx>( source_info, ); + // Mask out the bits of the discriminant type. + let mask = discr.size.unsigned_int_max(); + let discr_masked = + local_decls.push(LocalDecl::with_source_info(tcx.types.u128, source_info)).into(); + let rvalue = Rvalue::BinaryOp( + BinOp::BitAnd, + Box::new(( + Operand::Copy(discr_place), + Operand::Constant(Box::new(ConstOperand { + span: source_info.span, + user_ty: None, + const_: Const::Val(ConstValue::from_u128(mask), tcx.types.u128), + })), + )), + ); + block_data + .statements + .push(Statement::new(source_info, StatementKind::Assign(Box::new((discr_masked, rvalue))))); + // Branch based on the discriminant value. block_data.terminator = Some(Terminator { source_info, kind: TerminatorKind::SwitchInt { - discr: Operand::Copy(discr), + discr: Operand::Copy(discr_masked), targets: SwitchTargets::new( - discriminants.into_iter().map(|discr| (discr, new_block)), + discriminants + .into_iter() + .map(|discr_val| (discr.size.truncate(discr_val), new_block)), invalid_discr_block, ), }, @@ -371,7 +393,7 @@ fn insert_direct_enum_check<'tcx>( })), expected: true, target: new_block, - msg: Box::new(AssertKind::InvalidEnumConstruction(Operand::Copy(discr))), + msg: Box::new(AssertKind::InvalidEnumConstruction(Operand::Copy(discr_masked))), // This calls panic_invalid_enum_construction, which is #[rustc_nounwind]. // We never want to insert an unwind into unsafe code, because unwinding could // make a failing UB check turn into much worse UB when we start unwinding. @@ -445,7 +467,7 @@ fn insert_niche_check<'tcx>( source_info, ); - // Compare the discriminant agains the valid_range. + // Compare the discriminant against the valid_range. let start_const = Operand::Constant(Box::new(ConstOperand { span: source_info.span, user_ty: None, 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 0a839d91404..81d7b7ba02c 100644 --- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs +++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs @@ -239,7 +239,7 @@ pub(crate) fn coroutine_by_move_body_def_id<'tcx>( body_def.explicit_predicates_of(tcx.explicit_predicates_of(coroutine_def_id)); body_def.generics_of(tcx.generics_of(coroutine_def_id).clone()); body_def.param_env(tcx.param_env(coroutine_def_id)); - body_def.predicates_of(tcx.predicates_of(coroutine_def_id)); + body_def.explicit_predicates_of(tcx.explicit_predicates_of(coroutine_def_id)); // The type of the coroutine is the `by_move_coroutine_ty`. body_def.type_of(ty::EarlyBinder::bind(by_move_coroutine_ty)); diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 335354c23b6..6b11706d2b5 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -29,7 +29,7 @@ //! _b = some other value // also has VnIndex i //! ``` //! -//! We consider it to be replacable by: +//! We consider it to be replaceable by: //! ```ignore (MIR) //! _a = some value // has VnIndex i //! // some MIR diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 7852bb7ae2f..1c0fc774867 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -982,14 +982,16 @@ fn inline_call<'tcx, I: 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.append(&mut callee_body.source_scopes); + + // only "full" debug promises any variable-level information if tcx .sess .opts .unstable_opts .inline_mir_preserve_debug - .unwrap_or(tcx.sess.opts.debuginfo != DebugInfo::None) + .unwrap_or(tcx.sess.opts.debuginfo == DebugInfo::Full) { - // Note that we need to preserve these in the standard library so that + // -Zinline-mir-preserve-debug is enabled when building the standard library, so that // people working on rust can build with or without debuginfo while // still getting consistent results from the mir-opt tests. caller_body.var_debug_info.append(&mut callee_body.var_debug_info); diff --git a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs index 1bd770a8526..2f0edf31162 100644 --- a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs +++ b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs @@ -516,7 +516,7 @@ struct LocalLabel<'a> { /// A custom `Subdiagnostic` implementation so that the notes are delivered in a specific order impl Subdiagnostic for LocalLabel<'_> { fn add_to_diag<G: rustc_errors::EmissionGuarantee>(self, diag: &mut rustc_errors::Diag<'_, G>) { - // Becuase parent uses this field , we need to remove it delay before adding it. + // Because parent uses this field , we need to remove it delay before adding it. diag.remove_arg("name"); diag.arg("name", self.name); diag.remove_arg("is_generated_name"); diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs index 368d5340ac3..d1c2d6b508f 100644 --- a/compiler/rustc_mir_transform/src/ref_prop.rs +++ b/compiler/rustc_mir_transform/src/ref_prop.rs @@ -138,7 +138,7 @@ fn compute_replacement<'tcx>( // reborrowed references. let mut storage_to_remove = DenseBitSet::new_empty(body.local_decls.len()); - let fully_replacable_locals = fully_replacable_locals(ssa); + let fully_replaceable_locals = fully_replaceable_locals(ssa); // Returns true iff we can use `place` as a pointee. // @@ -204,7 +204,7 @@ fn compute_replacement<'tcx>( let needs_unique = ty.is_mutable_ptr(); // If this a mutable reference that we cannot fully replace, mark it as unknown. - if needs_unique && !fully_replacable_locals.contains(local) { + if needs_unique && !fully_replaceable_locals.contains(local) { debug!("not fully replaceable"); continue; } @@ -303,7 +303,7 @@ fn compute_replacement<'tcx>( // This a reborrow chain, recursively allow the replacement. // - // This also allows to detect cases where `target.local` is not replacable, + // This also allows to detect cases where `target.local` is not replaceable, // and mark it as such. if let &[PlaceElem::Deref] = &target.projection[..] { assert!(perform_opt); @@ -313,7 +313,7 @@ fn compute_replacement<'tcx>( } else if perform_opt { self.allowed_replacements.insert((target.local, loc)); } else if needs_unique { - // This mutable reference is not fully replacable, so drop it. + // This mutable reference is not fully replaceable, so drop it. self.targets[place.local] = Value::Unknown; } } @@ -326,22 +326,22 @@ fn compute_replacement<'tcx>( /// Compute the set of locals that can be fully replaced. /// -/// We consider a local to be replacable iff it's only used in a `Deref` projection `*_local` or +/// We consider a local to be replaceable iff it's only used in a `Deref` projection `*_local` or /// non-use position (like storage statements and debuginfo). -fn fully_replacable_locals(ssa: &SsaLocals) -> DenseBitSet<Local> { - let mut replacable = DenseBitSet::new_empty(ssa.num_locals()); +fn fully_replaceable_locals(ssa: &SsaLocals) -> DenseBitSet<Local> { + let mut replaceable = DenseBitSet::new_empty(ssa.num_locals()); // First pass: for each local, whether its uses can be fully replaced. for local in ssa.locals() { if ssa.num_direct_uses(local) == 0 { - replacable.insert(local); + replaceable.insert(local); } } // Second pass: a local can only be fully replaced if all its copies can. - ssa.meet_copy_equivalence(&mut replacable); + ssa.meet_copy_equivalence(&mut replaceable); - replacable + replaceable } /// Utility to help performing substitution of `*pattern` by `target`. diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 4083038cbb6..cdbc74cdfa8 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -31,7 +31,7 @@ pub(super) fn provide(providers: &mut Providers) { providers.mir_shims = make_shim; } -// Replace Pin<&mut ImplCoroutine> accesses (_1.0) into Pin<&mut ProxyCoroutine> acceses +// Replace Pin<&mut ImplCoroutine> accesses (_1.0) into Pin<&mut ProxyCoroutine> accesses struct FixProxyFutureDropVisitor<'tcx> { tcx: TyCtxt<'tcx>, replace_to: Local, diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 91e371d697d..131064f9832 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -532,7 +532,7 @@ fn collect_items_rec<'tcx>( }); } // Only updating `usage_map` for used items as otherwise we may be inserting the same item - // multiple times (if it is first 'mentioned' and then later actuall used), and the usage map + // multiple times (if it is first 'mentioned' and then later actually used), and the usage map // logic does not like that. // This is part of the output of collection and hence only relevant for "used" items. // ("Mentioned" items are only considered internally during collection.) diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 49025673bbd..69851511fb1 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -893,7 +893,7 @@ fn mono_item_visibility<'tcx>( // * First is weak lang items. These are basically mechanisms for // libcore to forward-reference symbols defined later in crates like // the standard library or `#[panic_handler]` definitions. The - // definition of these weak lang items needs to be referencable by + // definition of these weak lang items needs to be referenceable by // libcore, so we're no longer a candidate for internalization. // Removal of these functions can't be done by LLVM but rather must be // done by the linker as it's a non-local decision. diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs index 42264f58bcd..61f3f9367f0 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -73,7 +73,7 @@ where /// Register additional assumptions for aliases corresponding to `[const]` item bounds. /// /// Unlike item bounds, they are not simply implied by the well-formedness of the alias. - /// Instead, they only hold if the const conditons on the alias also hold. This is why + /// Instead, they only hold if the const conditions on the alias also hold. This is why /// we also register the const conditions of the alias after matching the goal against /// the assumption. fn consider_additional_alias_assumptions( diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs index cb7c498b94e..5ed316aa6b1 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs @@ -88,7 +88,7 @@ where /// This takes the `shallow_certainty` which represents whether we're confident /// that the final result of the current goal only depends on the nested goals. /// - /// In case this is `Certainy::Maybe`, there may still be additional nested goals + /// In case this is `Certainty::Maybe`, there may still be additional nested goals /// or inference constraints required for this candidate to be hold. The candidate /// always requires all already added constraints and nested goals. #[instrument(level = "trace", skip(self), ret)] diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs index 26443c54e18..2bb1ac8f742 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs @@ -42,7 +42,7 @@ where // Right now this includes both the impl and the assoc item where bounds, // and I don't think the assoc item where-bounds are allowed to be coinductive. // - // Projecting to the IAT also "steps out the impl contructor", so we would have + // Projecting to the IAT also "steps out the impl constructor", so we would have // to be very careful when changing the impl where-clauses to be productive. self.add_goals( GoalSource::Misc, 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 6c9fb63b579..098dc9dbaf0 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -1301,7 +1301,7 @@ where D: SolverDelegate<Interner = I>, I: Interner, { - /// FIXME(#57893): For backwards compatability with the old trait solver implementation, + /// FIXME(#57893): For backwards compatibility with the old trait solver implementation, /// we need to handle overlap between builtin and user-written impls for trait objects. /// /// This overlap is unsound in general and something which we intend to fix separately. diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index f6e0b08b140..af9f8735549 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -512,6 +512,8 @@ parse_leading_underscore_unicode_escape_label = invalid start of unicode escape parse_left_arrow_operator = unexpected token: `<-` .suggestion = if you meant to write a comparison against a negative value, add a space in between `<` and `-` +parse_let_chain_pre_2024 = let chains are only allowed in Rust 2024 or later + parse_lifetime_after_mut = lifetime must precede `mut` .suggestion = place the lifetime before `mut` diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 0f0c5434800..7f1b0991f0c 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1779,6 +1779,13 @@ pub(crate) struct AsyncBoundModifierIn2015 { } #[derive(Diagnostic)] +#[diag(parse_let_chain_pre_2024)] +pub(crate) struct LetChainPre2024 { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] #[diag(parse_self_argument_pointer)] pub(crate) struct SelfArgumentPointer { #[primary_span] diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 3cedc86dc0d..3d89530f914 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -4117,7 +4117,7 @@ impl MutVisitor for CondChecker<'_> { LetChainsPolicy::AlwaysAllowed => (), LetChainsPolicy::EditionDependent { current_edition } => { if !current_edition.at_least_rust_2024() || !span.at_least_rust_2024() { - self.parser.psess.gated_spans.gate(sym::let_chains, span); + self.parser.dcx().emit_err(errors::LetChainPre2024 { span }); } } } diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 8221c709027..0c57a8cc5e1 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -305,8 +305,13 @@ impl<'a> Parser<'a> { let removal_span = kw.span.with_hi(self.token.span.lo()); let path = self.parse_path(PathStyle::Type)?; let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus(); - let kind = - self.parse_remaining_bounds_path(lifetime_defs, path, lo, parse_plus)?; + let kind = self.parse_remaining_bounds_path( + lifetime_defs, + path, + lo, + parse_plus, + ast::Parens::No, + )?; let err = self.dcx().create_err(errors::TransposeDynOrImpl { span: kw.span, kw: kw.name.as_str(), @@ -333,7 +338,13 @@ impl<'a> Parser<'a> { } else { let path = self.parse_path(PathStyle::Type)?; let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus(); - self.parse_remaining_bounds_path(lifetime_defs, path, lo, parse_plus)? + self.parse_remaining_bounds_path( + lifetime_defs, + path, + lo, + parse_plus, + ast::Parens::No, + )? } } } else if self.eat_keyword(exp!(Impl)) { @@ -413,9 +424,13 @@ impl<'a> Parser<'a> { let maybe_bounds = allow_plus == AllowPlus::Yes && self.token.is_like_plus(); match ty.kind { // `(TY_BOUND_NOPAREN) + BOUND + ...`. - TyKind::Path(None, path) if maybe_bounds => { - self.parse_remaining_bounds_path(ThinVec::new(), path, lo, true) - } + TyKind::Path(None, path) if maybe_bounds => self.parse_remaining_bounds_path( + ThinVec::new(), + path, + lo, + true, + ast::Parens::Yes, + ), // For `('a) + …`, we know that `'a` in type position already lead to an error being // emitted. To reduce output, let's indirectly suppress E0178 (bad `+` in type) and // other irrelevant consequential errors. @@ -495,12 +510,14 @@ impl<'a> Parser<'a> { path: ast::Path, lo: Span, parse_plus: bool, + parens: ast::Parens, ) -> PResult<'a, TyKind> { let poly_trait_ref = PolyTraitRef::new( generic_params, path, TraitBoundModifiers::NONE, lo.to(self.prev_token.span), + parens, ); let bounds = vec![GenericBound::Trait(poly_trait_ref)]; self.parse_remaining_bounds(bounds, parse_plus) @@ -826,7 +843,7 @@ impl<'a> Parser<'a> { Ok(TyKind::MacCall(P(MacCall { path, args: self.parse_delim_args()? }))) } else if allow_plus == AllowPlus::Yes && self.check_plus() { // `Trait1 + Trait2 + 'a` - self.parse_remaining_bounds_path(ThinVec::new(), path, lo, true) + self.parse_remaining_bounds_path(ThinVec::new(), path, lo, true, ast::Parens::No) } else { // Just a type path. Ok(TyKind::Path(None, path)) @@ -892,10 +909,10 @@ impl<'a> Parser<'a> { fn parse_generic_bound(&mut self) -> PResult<'a, GenericBound> { let lo = self.token.span; let leading_token = self.prev_token; - let has_parens = self.eat(exp!(OpenParen)); + let parens = if self.eat(exp!(OpenParen)) { ast::Parens::Yes } else { ast::Parens::No }; let bound = if self.token.is_lifetime() { - self.parse_generic_lt_bound(lo, has_parens)? + self.parse_generic_lt_bound(lo, parens)? } else if self.eat_keyword(exp!(Use)) { // parse precise captures, if any. This is `use<'lt, 'lt, P, P>`; a list of // lifetimes and ident params (including SelfUpper). These are validated later @@ -904,7 +921,7 @@ impl<'a> Parser<'a> { let (args, args_span) = self.parse_precise_capturing_args()?; GenericBound::Use(args, use_span.to(args_span)) } else { - self.parse_generic_ty_bound(lo, has_parens, &leading_token)? + self.parse_generic_ty_bound(lo, parens, &leading_token)? }; Ok(bound) @@ -914,10 +931,14 @@ impl<'a> Parser<'a> { /// ```ebnf /// LT_BOUND = LIFETIME /// ``` - fn parse_generic_lt_bound(&mut self, lo: Span, has_parens: bool) -> PResult<'a, GenericBound> { + fn parse_generic_lt_bound( + &mut self, + lo: Span, + parens: ast::Parens, + ) -> PResult<'a, GenericBound> { let lt = self.expect_lifetime(); let bound = GenericBound::Outlives(lt); - if has_parens { + if let ast::Parens::Yes = parens { // FIXME(Centril): Consider not erroring here and accepting `('lt)` instead, // possibly introducing `GenericBound::Paren(P<GenericBound>)`? self.recover_paren_lifetime(lo)?; @@ -1090,7 +1111,7 @@ impl<'a> Parser<'a> { fn parse_generic_ty_bound( &mut self, lo: Span, - has_parens: bool, + parens: ast::Parens, leading_token: &Token, ) -> PResult<'a, GenericBound> { let (mut lifetime_defs, binder_span) = self.parse_late_bound_lifetime_defs()?; @@ -1116,7 +1137,7 @@ impl<'a> Parser<'a> { // e.g. `T: for<'a> 'a` or `T: [const] 'a`. if self.token.is_lifetime() { let _: ErrorGuaranteed = self.error_lt_bound_with_modifiers(modifiers, binder_span); - return self.parse_generic_lt_bound(lo, has_parens); + return self.parse_generic_lt_bound(lo, parens); } if let (more_lifetime_defs, Some(binder_span)) = self.parse_late_bound_lifetime_defs()? { @@ -1183,7 +1204,7 @@ impl<'a> Parser<'a> { self.recover_fn_trait_with_lifetime_params(&mut path, &mut lifetime_defs)?; } - if has_parens { + if let ast::Parens::Yes = parens { // Someone has written something like `&dyn (Trait + Other)`. The correct code // would be `&(dyn Trait + Other)` if self.token.is_like_plus() && leading_token.is_keyword(kw::Dyn) { @@ -1203,7 +1224,7 @@ impl<'a> Parser<'a> { } let poly_trait = - PolyTraitRef::new(lifetime_defs, path, modifiers, lo.to(self.prev_token.span)); + PolyTraitRef::new(lifetime_defs, path, modifiers, lo.to(self.prev_token.span), parens); Ok(GenericBound::Trait(poly_trait)) } diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index 6c2c571d240..4d64cdeb69a 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -298,6 +298,8 @@ fn emit_malformed_attribute( | sym::deprecated | sym::optimize | sym::cold + | sym::target_feature + | sym::rustc_allow_const_fn_unstable | sym::naked | sym::no_mangle | sym::must_use diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 9a60c151034..5a94d01e088 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -537,7 +537,7 @@ passes_no_sanitize = `#[no_sanitize({$attr_str})]` should be applied to {$accepted_kind} .label = not {$accepted_kind} -passes_non_exaustive_with_default_field_values = +passes_non_exhaustive_with_default_field_values = `#[non_exhaustive]` can't be used to annotate items with default field values .label = this struct has default field values diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 1b965b9545c..87d46e3e506 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -146,20 +146,18 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Attribute::Parsed(AttributeKind::ConstContinue(attr_span)) => { self.check_const_continue(hir_id, *attr_span, target) } - Attribute::Parsed(AttributeKind::AllowInternalUnstable(syms)) => self - .check_allow_internal_unstable( - hir_id, - syms.first().unwrap().1, - span, - target, - attrs, - ), - Attribute::Parsed(AttributeKind::AllowConstFnUnstable { .. }) => { - self.check_rustc_allow_const_fn_unstable(hir_id, attr, span, target) + Attribute::Parsed(AttributeKind::AllowInternalUnstable(_, first_span)) => { + self.check_allow_internal_unstable(hir_id, *first_span, span, target, attrs) + } + Attribute::Parsed(AttributeKind::AllowConstFnUnstable(_, first_span)) => { + self.check_rustc_allow_const_fn_unstable(hir_id, *first_span, span, target) } Attribute::Parsed(AttributeKind::Deprecation { .. }) => { self.check_deprecated(hir_id, attr, span, target) } + Attribute::Parsed(AttributeKind::TargetFeature(_, attr_span)) => { + self.check_target_feature(hir_id, *attr_span, span, target, attrs) + } Attribute::Parsed(AttributeKind::DocComment { .. }) => { /* `#[doc]` is actually a lot more than just doc comments, so is checked below*/ } Attribute::Parsed(AttributeKind::Repr(_)) => { /* handled below this loop and elsewhere */ @@ -230,9 +228,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } [sym::non_exhaustive, ..] => self.check_non_exhaustive(hir_id, attr, span, target, item), [sym::marker, ..] => self.check_marker(hir_id, attr, span, target), - [sym::target_feature, ..] => { - self.check_target_feature(hir_id, attr, span, target, attrs) - } [sym::thread_local, ..] => self.check_thread_local(attr, span, target), [sym::doc, ..] => self.check_doc_attrs( attr, @@ -816,7 +811,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { fn check_target_feature( &self, hir_id: HirId, - attr: &Attribute, + attr_span: Span, span: Span, target: Target, attrs: &[Attribute], @@ -834,7 +829,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { let sig = self.tcx.hir_node(hir_id).fn_sig().unwrap(); self.dcx().emit_err(errors::LangItemWithTargetFeature { - attr_span: attr.span(), + attr_span, name: lang_item, sig_span: sig.span, }); @@ -846,7 +841,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.tcx.emit_node_span_lint( UNUSED_ATTRIBUTES, hir_id, - attr.span(), + attr_span, errors::TargetFeatureOnStatement, ); } @@ -855,11 +850,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> { // erroneously allowed it and some crates used it accidentally, to be compatible // with crates depending on them, we can't throw an error here. Target::Field | Target::Arm | Target::MacroDef => { - self.inline_attr_str_error_with_macro_def(hir_id, attr.span(), "target_feature"); + self.inline_attr_str_error_with_macro_def(hir_id, attr_span, "target_feature"); } _ => { self.dcx().emit_err(errors::AttrShouldBeAppliedToFn { - attr_span: attr.span(), + attr_span, defn_span: span, on_crate: hir_id == CRATE_HIR_ID, }); @@ -2169,7 +2164,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { fn check_rustc_allow_const_fn_unstable( &self, hir_id: HirId, - attr: &Attribute, + attr_span: Span, span: Span, target: Target, ) { @@ -2181,15 +2176,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { // erroneously allowed it and some crates used it accidentally, to be compatible // with crates depending on them, we can't throw an error here. Target::Field | Target::Arm | Target::MacroDef => self - .inline_attr_str_error_with_macro_def( - hir_id, - attr.span(), - "allow_internal_unstable", - ), + .inline_attr_str_error_with_macro_def(hir_id, attr_span, "allow_internal_unstable"), _ => { - self.tcx - .dcx() - .emit_err(errors::RustcAllowConstFnUnstable { attr_span: attr.span(), span }); + self.tcx.dcx().emit_err(errors::RustcAllowConstFnUnstable { attr_span, span }); } } } @@ -2323,8 +2312,20 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } return; } + AttributeKind::TargetFeature(features, span) if features.len() == 0 => { + self.tcx.emit_node_span_lint( + UNUSED_ATTRIBUTES, + hir_id, + *span, + errors::Unused { + attr_span: *span, + note: errors::UnusedNote::EmptyList { name: sym::target_feature }, + }, + ); + return; + } _ => {} - } + }; } // Warn on useless empty attributes. @@ -2336,7 +2337,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { sym::deny, sym::forbid, sym::feature, - sym::target_feature, ]) && attr.meta_item_list().is_some_and(|list| list.is_empty()) { errors::UnusedNote::EmptyList { name: attr.name().unwrap() } diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index ce43b2c281d..cdfd1a2b07e 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -1199,7 +1199,7 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) { let def_kind = tcx.def_kind(item.owner_id); let mut dead_codes = Vec::new(); - // Only diagnose unused assoc items in inherient impl and used trait, + // Only diagnose unused assoc items in inherent impl and used trait, // for unused assoc items in impls of trait, // we have diagnosed them in the trait if they are unused, // for unused assoc items in unused trait, diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index d4988277073..3ede3c889c8 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -157,7 +157,7 @@ pub(crate) struct NonExhaustiveWrongLocation { } #[derive(Diagnostic)] -#[diag(passes_non_exaustive_with_default_field_values)] +#[diag(passes_non_exhaustive_with_default_field_values)] pub(crate) struct NonExhaustiveWithDefaultFieldValues { #[primary_span] pub attr_span: Span, diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index 53638f2a57d..c348cd508f9 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -70,7 +70,7 @@ //! # Constructors and fields //! //! In the value `Pair(Some(0), true)`, `Pair` is called the constructor of the value, and `Some(0)` -//! and `true` are its fields. Every matcheable value can be decomposed in this way. Examples of +//! and `true` are its fields. Every matchable value can be decomposed in this way. Examples of //! constructors are: `Some`, `None`, `(,)` (the 2-tuple constructor), `Foo {..}` (the constructor //! for a struct `Foo`), and `2` (the constructor for the number `2`). //! @@ -102,7 +102,7 @@ //! [`Constructor::is_covered_by`]. //! //! Note 1: variable bindings (like the `x` in `Some(x)`) match anything, so we treat them as wildcards. -//! Note 2: this only applies to matcheable values. For example a value of type `Rc<u64>` can't be +//! Note 2: this only applies to matchable values. For example a value of type `Rc<u64>` can't be //! deconstructed that way. //! //! diff --git a/compiler/rustc_query_impl/src/profiling_support.rs b/compiler/rustc_query_impl/src/profiling_support.rs index 7d80e54bf87..7be75ea88ac 100644 --- a/compiler/rustc_query_impl/src/profiling_support.rs +++ b/compiler/rustc_query_impl/src/profiling_support.rs @@ -259,4 +259,5 @@ pub fn alloc_self_profile_query_strings(tcx: TyCtxt<'_>) { for alloc in super::ALLOC_SELF_PROFILE_QUERY_STRINGS.iter() { alloc(tcx, &mut string_cache) } + tcx.sess.prof.store_query_cache_hits(); } diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index d4217e0aa54..04fc32a9b50 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -1342,7 +1342,7 @@ impl DepNodeColorMap { /// This tries to atomically mark a node green and assign `index` as the new /// index. This returns `Ok` if `index` gets assigned, otherwise it returns - /// the alreadly allocated index in `Err`. + /// the already allocated index in `Err`. #[inline] pub(super) fn try_mark_green( &self, diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index 58942474e32..aa818cc9c46 100644 --- a/compiler/rustc_resolve/messages.ftl +++ b/compiler/rustc_resolve/messages.ftl @@ -432,6 +432,7 @@ resolve_undeclared_label = resolve_underscore_lifetime_is_reserved = `'_` cannot be used here .label = `'_` is a reserved lifetime name + .help = use another lifetime specifier resolve_unexpected_res_change_ty_to_const_param_sugg = you might have meant to write a const parameter here diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 6d3752c0c83..b34bcb38f84 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -878,12 +878,12 @@ pub(crate) struct MacroExpandedExternCrateCannotShadowExternArguments { #[derive(Diagnostic)] #[diag(resolve_elided_anonymous_lifetime_report_error, code = E0637)] -pub(crate) struct ElidedAnonymousLivetimeReportError { +pub(crate) struct ElidedAnonymousLifetimeReportError { #[primary_span] #[label] pub(crate) span: Span, #[subdiagnostic] - pub(crate) suggestion: Option<ElidedAnonymousLivetimeReportErrorSuggestion>, + pub(crate) suggestion: Option<ElidedAnonymousLifetimeReportErrorSuggestion>, } #[derive(Diagnostic)] @@ -897,7 +897,7 @@ pub(crate) struct LendingIteratorReportError { #[derive(Diagnostic)] #[diag(resolve_anonymous_lifetime_non_gat_report_error)] -pub(crate) struct AnonymousLivetimeNonGatReportError { +pub(crate) struct AnonymousLifetimeNonGatReportError { #[primary_span] #[label] pub(crate) lifetime: Span, @@ -908,7 +908,7 @@ pub(crate) struct AnonymousLivetimeNonGatReportError { resolve_elided_anonymous_lifetime_report_error_suggestion, applicability = "machine-applicable" )] -pub(crate) struct ElidedAnonymousLivetimeReportErrorSuggestion { +pub(crate) struct ElidedAnonymousLifetimeReportErrorSuggestion { #[suggestion_part(code = "for<'a> ")] pub(crate) lo: Span, #[suggestion_part(code = "'a ")] @@ -917,7 +917,7 @@ pub(crate) struct ElidedAnonymousLivetimeReportErrorSuggestion { #[derive(Diagnostic)] #[diag(resolve_explicit_anonymous_lifetime_report_error, code = E0637)] -pub(crate) struct ExplicitAnonymousLivetimeReportError { +pub(crate) struct ExplicitAnonymousLifetimeReportError { #[primary_span] #[label] pub(crate) span: Span, @@ -934,6 +934,7 @@ pub(crate) struct ImplicitElidedLifetimeNotAllowedHere { #[derive(Diagnostic)] #[diag(resolve_underscore_lifetime_is_reserved, code = E0637)] +#[help] pub(crate) struct UnderscoreLifetimeIsReserved { #[primary_span] #[label] diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index ac7bdda4195..c2bea4e0fdc 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1892,7 +1892,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { .. } = rib.kind { - Some(errors::ElidedAnonymousLivetimeReportErrorSuggestion { + Some(errors::ElidedAnonymousLifetimeReportErrorSuggestion { lo: span.shrink_to_lo(), hi: lifetime.ident.span.shrink_to_hi(), }) @@ -1918,18 +1918,18 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ty: ty.span, }); } else { - self.r.dcx().emit_err(errors::AnonymousLivetimeNonGatReportError { + self.r.dcx().emit_err(errors::AnonymousLifetimeNonGatReportError { lifetime: lifetime.ident.span, }); } } else { - self.r.dcx().emit_err(errors::ElidedAnonymousLivetimeReportError { + self.r.dcx().emit_err(errors::ElidedAnonymousLifetimeReportError { span: lifetime.ident.span, suggestion, }); } } else { - self.r.dcx().emit_err(errors::ExplicitAnonymousLivetimeReportError { + self.r.dcx().emit_err(errors::ExplicitAnonymousLifetimeReportError { span: lifetime.ident.span, }); }; diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index e7b8c988cd4..6230b8cfbec 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -3832,6 +3832,7 @@ fn mk_where_bound_predicate( ref_id: DUMMY_NODE_ID, }, span: DUMMY_SP, + parens: ast::Parens::No, })], }; diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs index 3fe5db8ca54..f61cd1f0adf 100644 --- a/compiler/rustc_resolve/src/rustdoc.rs +++ b/compiler/rustc_resolve/src/rustdoc.rs @@ -627,7 +627,7 @@ pub fn source_span_for_markdown_range_inner( let fragment = &fragments[i]; let sp = fragment.span; // we need to calculate the span start, - // then use that in our calulations for the span end + // then use that in our calculations for the span end let lo = sp.lo() + BytePos(match_start as u32); return Some(( sp.with_lo(lo).with_hi(lo + BytePos((md_range.end - md_range.start) as u32)), diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs index 6ea70600626..1cb09e8a1ee 100644 --- a/compiler/rustc_serialize/src/serialize.rs +++ b/compiler/rustc_serialize/src/serialize.rs @@ -21,7 +21,7 @@ use thin_vec::ThinVec; /// [utf8]: https://en.wikipedia.org/w/index.php?title=UTF-8&oldid=1058865525#Codepage_layout const STR_SENTINEL: u8 = 0xC1; -/// For byte strings there are no bytes that canot occur. Just use this value +/// For byte strings there are no bytes that cannot occur. Just use this value /// as a best-effort sentinel. There is no validation skipped so the potential /// for badness is lower than in the `STR_SENTINEL` case. const BYTE_STR_SENTINEL: u8 = 0xC2; diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 73bb0471c22..74e766a1e95 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -190,7 +190,7 @@ pub struct CoverageOptions { /// to keep supporting this flag, remove it. pub no_mir_spans: bool, - /// `-Zcoverage-options=discard-all-spans-in-codegen`: During codgen, + /// `-Zcoverage-options=discard-all-spans-in-codegen`: During codegen, /// discard all coverage spans as though they were invalid. Needed by /// regression tests for #133606, because we don't have an easy way to /// reproduce it from actual source code. diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index bad2581ae31..8386fe8dab0 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1545,7 +1545,7 @@ impl RemapFileNameExt for rustc_span::FileName { "one and only one scope should be passed to for_scope" ); if sess.opts.unstable_opts.remap_path_scope.contains(scope) { - self.prefer_remapped_unconditionaly() + self.prefer_remapped_unconditionally() } else { self.prefer_local() } diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index baa4c0681e8..3fa83cfc6a0 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -130,7 +130,11 @@ impl<'tcx> SmirCtxt<'tcx> { pub fn all_trait_decls(&self) -> stable_mir::TraitDecls { let mut tables = self.0.borrow_mut(); - tables.tcx.all_traits().map(|trait_def_id| tables.trait_def(trait_def_id)).collect() + tables + .tcx + .all_traits_including_private() + .map(|trait_def_id| tables.trait_def(trait_def_id)) + .collect() } pub fn trait_decls(&self, crate_num: CrateNum) -> stable_mir::TraitDecls { diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index 4ea2bb04c5d..398738d1c38 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -1600,7 +1600,7 @@ pub struct VariantIdx(usize); index_impl!(VariantIdx); crate_def! { - /// Hold infomation about an Opaque definition, particularly useful in `RPITIT`. + /// Hold information about an Opaque definition, particularly useful in `RPITIT`. #[derive(Serialize)] pub OpaqueDef; } diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index c18ff285c4e..9b0e009b2cd 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -418,7 +418,7 @@ impl FileName { } } - pub fn prefer_remapped_unconditionaly(&self) -> FileNameDisplay<'_> { + pub fn prefer_remapped_unconditionally(&self) -> FileNameDisplay<'_> { FileNameDisplay { inner: self, display_pref: FileNameDisplayPreference::Remapped } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 34869a38bb4..d6537d49be7 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1775,7 +1775,6 @@ symbols! { resume, return_position_impl_trait_in_trait, return_type_notation, - rhs, riscv_target_feature, rlib, ropi, @@ -2398,7 +2397,7 @@ pub const STDLIB_STABLE_CRATES: &[Symbol] = &[sym::std, sym::core, sym::alloc, s #[derive(Copy, Clone, Eq, HashStable_Generic, Encodable, Decodable)] pub struct Ident { // `name` should never be the empty symbol. If you are considering that, - // you are probably conflating "empty identifer with "no identifier" and + // you are probably conflating "empty identifier with "no identifier" and // you should use `Option<Ident>` instead. pub name: Symbol, pub span: Span, diff --git a/compiler/rustc_target/src/callconv/s390x.rs b/compiler/rustc_target/src/callconv/s390x.rs index 1ba792c5acc..d2ae404b23b 100644 --- a/compiler/rustc_target/src/callconv/s390x.rs +++ b/compiler/rustc_target/src/callconv/s390x.rs @@ -46,7 +46,7 @@ where } if arg.layout.is_single_vector_element(cx, size) { - // pass non-transparant wrappers around a vector as `PassMode::Cast` + // pass non-transparent wrappers around a vector as `PassMode::Cast` arg.cast_to(Reg { kind: RegKind::Vector, size }); return; } diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs index 66733d5d4b8..b01ca989282 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs @@ -10,6 +10,7 @@ pub(crate) fn target() -> Target { base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.max_atomic_width = Some(64); base.stack_probes = StackProbeType::Inline; + base.abi = "elfv2".into(); base.llvm_abiname = "elfv2".into(); Target { diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_gnu.rs index ecf68ddff8c..bc7e445f3f8 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_gnu.rs @@ -10,6 +10,7 @@ pub(crate) fn target() -> Target { base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.max_atomic_width = Some(64); base.stack_probes = StackProbeType::Inline; + base.abi = "elfv1".into(); base.llvm_abiname = "elfv1".into(); Target { diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs index e205aef8285..4dc76f0936c 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs @@ -12,6 +12,7 @@ pub(crate) fn target() -> Target { base.stack_probes = StackProbeType::Inline; // FIXME(compiler-team#422): musl targets should be dynamically linked by default. base.crt_static_default = true; + base.abi = "elfv2".into(); base.llvm_abiname = "elfv2".into(); Target { diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_openbsd.rs index bcb328020ee..9dc44aa05cc 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_openbsd.rs @@ -10,6 +10,7 @@ pub(crate) fn target() -> Target { base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.max_atomic_width = Some(64); base.stack_probes = StackProbeType::Inline; + base.abi = "elfv2".into(); base.llvm_abiname = "elfv2".into(); Target { diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/powerpc64_wrs_vxworks.rs index 37c888ba514..10072f8092d 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc64_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc64_wrs_vxworks.rs @@ -10,6 +10,7 @@ pub(crate) fn target() -> Target { base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.max_atomic_width = Some(64); base.stack_probes = StackProbeType::Inline; + base.abi = "elfv1".into(); base.llvm_abiname = "elfv1".into(); Target { diff --git a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_freebsd.rs index 3096c4d14ad..a7f4e0eabb0 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_freebsd.rs @@ -8,6 +8,7 @@ pub(crate) fn target() -> Target { base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.max_atomic_width = Some(64); base.stack_probes = StackProbeType::Inline; + base.abi = "elfv2".into(); base.llvm_abiname = "elfv2".into(); Target { diff --git a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_gnu.rs index 9e406af53b5..af5704b51ba 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_gnu.rs @@ -8,6 +8,7 @@ pub(crate) fn target() -> Target { base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.max_atomic_width = Some(64); base.stack_probes = StackProbeType::Inline; + base.abi = "elfv2".into(); base.llvm_abiname = "elfv2".into(); Target { diff --git a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs index f145c5b8c14..26ee6a68c6a 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs @@ -10,6 +10,7 @@ pub(crate) fn target() -> Target { base.stack_probes = StackProbeType::Inline; // FIXME(compiler-team#422): musl targets should be dynamically linked by default. base.crt_static_default = true; + base.abi = "elfv2".into(); base.llvm_abiname = "elfv2".into(); Target { diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml index 1071105522d..62f1d908601 100644 --- a/compiler/rustc_trait_selection/Cargo.toml +++ b/compiler/rustc_trait_selection/Cargo.toml @@ -8,6 +8,7 @@ edition = "2024" itertools = "0.12" rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } +rustc_attr_data_structures = {path = "../rustc_attr_data_structures"} rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_fluent_macro = { path = "../rustc_fluent_macro" } 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 aea42df4dfd..bff5e9128cb 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 @@ -1,3 +1,4 @@ +use rustc_attr_data_structures::{AttributeKind, find_attr}; use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect}; use rustc_errors::{Diag, MultiSpan, pluralize}; use rustc_hir as hir; @@ -8,7 +9,7 @@ use rustc_middle::ty::fast_reject::DeepRejectCtxt; use rustc_middle::ty::print::{FmtPrinter, Printer}; use rustc_middle::ty::{self, Ty, suggest_constraining_type_param}; use rustc_span::def_id::DefId; -use rustc_span::{BytePos, Span, Symbol, sym}; +use rustc_span::{BytePos, Span, Symbol}; use tracing::debug; use crate::error_reporting::TypeErrCtxt; @@ -535,8 +536,7 @@ impl<T> Trait<T> for X { } } TypeError::TargetFeatureCast(def_id) => { - let target_spans = - tcx.get_attrs(def_id, sym::target_feature).map(|attr| attr.span()); + let target_spans = find_attr!(tcx.get_all_attrs(def_id), AttributeKind::TargetFeature(.., span) => *span); diag.note( "functions with `#[target_feature]` can only be coerced to `unsafe` function pointers" ); 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 c72eff1d231..28d572b303a 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 @@ -1855,7 +1855,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let trait_def_id = trait_pred.def_id(); let trait_name = self.tcx.item_name(trait_def_id); let crate_name = self.tcx.crate_name(trait_def_id.krate); - if let Some(other_trait_def_id) = self.tcx.all_traits().find(|def_id| { + if let Some(other_trait_def_id) = self.tcx.all_traits_including_private().find(|def_id| { trait_name == self.tcx.item_name(trait_def_id) && trait_def_id.krate != def_id.krate && crate_name == self.tcx.crate_name(def_id.krate) 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 2bbf90ed3ed..362052e9fdb 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -4432,7 +4432,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { candidate_impls: &[ImplCandidate<'tcx>], span: Span, ) { - // We can only suggest the slice coersion for function and binary operation arguments, + // We can only suggest the slice coercion for function and binary operation arguments, // since the suggestion would make no sense in turbofish or call let (ObligationCauseCode::BinOp { .. } | ObligationCauseCode::FunctionArg { .. }) = obligation.cause.code() diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 7bf49056e29..90cdf75265d 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -643,7 +643,7 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> { // Do not suggest constraining the `&self` param, but rather the return type. // If that is wrong (because it is not sufficient), a follow up error will tell the // user to fix it. This way we lower the chances of *over* constraining, but still - // get the cake of "correctly" contrained in two steps. + // get the cake of "correctly" constrained in two steps. visitor.visit_ty_unambig(self.ty_sup); } visitor.visit_ty_unambig(self.ty_sub); diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index 8d049fedf23..9a4f3887bbb 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -31,7 +31,7 @@ use crate::traits::{ /// /// Currently that is `Self` in supertraits. This is needed /// because `dyn_compatibility_violations` can't be used during -/// type collection, as type collection is needed for `dyn_compatiblity_violations` itself. +/// type collection, as type collection is needed for `dyn_compatibility_violations` itself. #[instrument(level = "debug", skip(tcx), ret)] pub fn hir_ty_lowering_dyn_compatibility_violations( tcx: TyCtxt<'_>, diff --git a/compiler/rustc_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs index fc95e42d67f..176d308de91 100644 --- a/compiler/rustc_trait_selection/src/traits/effects.rs +++ b/compiler/rustc_trait_selection/src/traits/effects.rs @@ -44,6 +44,12 @@ pub fn evaluate_host_effect_obligation<'tcx>( Err(EvaluationFailure::NoSolution) => {} } + match evaluate_host_effect_from_conditionally_const_item_bounds(selcx, obligation) { + Ok(result) => return Ok(result), + Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous), + Err(EvaluationFailure::NoSolution) => {} + } + match evaluate_host_effect_from_item_bounds(selcx, obligation) { Ok(result) => return Ok(result), Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous), @@ -56,7 +62,7 @@ pub fn evaluate_host_effect_obligation<'tcx>( Err(EvaluationFailure::NoSolution) => {} } - match evaluate_host_effect_from_selection_candiate(selcx, obligation) { + match evaluate_host_effect_from_selection_candidate(selcx, obligation) { Ok(result) => return Ok(result), Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous), Err(EvaluationFailure::NoSolution) => {} @@ -153,7 +159,9 @@ fn evaluate_host_effect_from_bounds<'tcx>( } } -fn evaluate_host_effect_from_item_bounds<'tcx>( +/// Assembles constness bounds from `~const` item bounds on alias types, which only +/// hold if the `~const` where bounds also hold and the parent trait is `~const`. +fn evaluate_host_effect_from_conditionally_const_item_bounds<'tcx>( selcx: &mut SelectionContext<'_, 'tcx>, obligation: &HostEffectObligation<'tcx>, ) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> { @@ -232,6 +240,63 @@ fn evaluate_host_effect_from_item_bounds<'tcx>( } } +/// Assembles constness bounds "normal" item bounds on aliases, which may include +/// unconditionally `const` bounds that are *not* conditional and thus always hold. +fn evaluate_host_effect_from_item_bounds<'tcx>( + selcx: &mut SelectionContext<'_, 'tcx>, + obligation: &HostEffectObligation<'tcx>, +) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> { + let infcx = selcx.infcx; + let tcx = infcx.tcx; + let drcx = DeepRejectCtxt::relate_rigid_rigid(selcx.tcx()); + let mut candidate = None; + + let mut consider_ty = obligation.predicate.self_ty(); + while let ty::Alias(kind @ (ty::Projection | ty::Opaque), alias_ty) = *consider_ty.kind() { + for clause in tcx.item_bounds(alias_ty.def_id).iter_instantiated(tcx, alias_ty.args) { + let bound_clause = clause.kind(); + let ty::ClauseKind::HostEffect(data) = bound_clause.skip_binder() else { + continue; + }; + let data = bound_clause.rebind(data); + if data.skip_binder().trait_ref.def_id != obligation.predicate.trait_ref.def_id { + continue; + } + + if !drcx.args_may_unify( + obligation.predicate.trait_ref.args, + data.skip_binder().trait_ref.args, + ) { + continue; + } + + let is_match = + infcx.probe(|_| match_candidate(selcx, obligation, data, true, |_, _| {}).is_ok()); + + if is_match { + if candidate.is_some() { + return Err(EvaluationFailure::Ambiguous); + } else { + candidate = Some(data); + } + } + } + + if kind != ty::Projection { + break; + } + + consider_ty = alias_ty.self_ty(); + } + + if let Some(data) = candidate { + Ok(match_candidate(selcx, obligation, data, true, |_, _| {}) + .expect("candidate matched before, so it should match again")) + } else { + Err(EvaluationFailure::NoSolution) + } +} + fn evaluate_host_effect_from_builtin_impls<'tcx>( selcx: &mut SelectionContext<'_, 'tcx>, obligation: &HostEffectObligation<'tcx>, @@ -333,7 +398,7 @@ fn evaluate_host_effect_for_destruct_goal<'tcx>( .collect()) } -fn evaluate_host_effect_from_selection_candiate<'tcx>( +fn evaluate_host_effect_from_selection_candidate<'tcx>( selcx: &mut SelectionContext<'_, 'tcx>, obligation: &HostEffectObligation<'tcx>, ) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> { diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 43806d3977b..91c41544f78 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -481,7 +481,7 @@ pub enum EvaluateConstErr { /// some unevaluated constant with either generic parameters or inference variables in its /// generic arguments. HasGenericsOrInfers, - /// The type this constant evalauted to is not valid for use in const generics. This should + /// The type this constant evaluated to is not valid for use in const generics. This should /// always result in an error when checking the constant is correctly typed for the parameter /// it is an argument to, so a bug is delayed when encountering this. InvalidConstParamTy(ErrorGuaranteed), 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 18971c47831..22eeb285b37 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 @@ -21,19 +21,9 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> { if let ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) = key.value.predicate.kind().skip_binder() + && term.is_trivially_wf(tcx) { - match term.as_type()?.kind() { - ty::Param(_) - | ty::Bool - | ty::Char - | ty::Int(_) - | ty::Float(_) - | ty::Str - | ty::Uint(_) => { - return Some(()); - } - _ => {} - } + return Some(()); } None diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 3eca77b43a8..3a369f13e79 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -904,7 +904,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let goal_kind = self.tcx().async_fn_trait_kind_from_def_id(obligation.predicate.def_id()).unwrap(); - // If we have not yet determiend the `ClosureKind` of the closure or coroutine-closure, + // If we have not yet determined the `ClosureKind` of the closure or coroutine-closure, // then additionally register an `AsyncFnKindHelper` goal which will fail if the kind // is constrained to an insufficient type later on. if let Some(closure_kind) = self.infcx.shallow_resolve(kind_ty).to_opt_closure_kind() { diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index a05bae53566..141454bfe37 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -368,16 +368,17 @@ pub fn sizedness_fast_path<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc // Proving `Sized`/`MetaSized`, very often on "obviously sized" types like // `&T`, accounts for about 60% percentage of the predicates we have to prove. No need to // canonicalize and all that for such cases. - if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_ref)) = + if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) = predicate.kind().skip_binder() + && trait_pred.polarity == ty::PredicatePolarity::Positive { - let sizedness = match tcx.as_lang_item(trait_ref.def_id()) { + let sizedness = match tcx.as_lang_item(trait_pred.def_id()) { Some(LangItem::Sized) => SizedTraitKind::Sized, Some(LangItem::MetaSized) => SizedTraitKind::MetaSized, _ => return false, }; - if trait_ref.self_ty().has_trivial_sizedness(tcx, sizedness) { + if trait_pred.self_ty().has_trivial_sizedness(tcx, sizedness) { debug!("fast path -- trivial sizedness"); return true; } diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs index 9d144010561..7dd3c59edd0 100644 --- a/compiler/rustc_traits/src/codegen.rs +++ b/compiler/rustc_traits/src/codegen.rs @@ -6,11 +6,11 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::bug; use rustc_middle::traits::CodegenObligationError; -use rustc_middle::ty::{self, PseudoCanonicalInput, TyCtxt, TypeVisitableExt, Upcast}; +use rustc_middle::ty::{self, PseudoCanonicalInput, TyCtxt, TypeVisitableExt}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::traits::{ ImplSource, Obligation, ObligationCause, ObligationCtxt, ScrubbedTraitError, SelectionContext, - SelectionError, sizedness_fast_path, + SelectionError, }; use tracing::debug; @@ -34,13 +34,6 @@ pub(crate) fn codegen_select_candidate<'tcx>( let (infcx, param_env) = tcx.infer_ctxt().ignoring_regions().build_with_typing_env(typing_env); let mut selcx = SelectionContext::new(&infcx); - if sizedness_fast_path(tcx, trait_ref.upcast(tcx)) { - return Ok(&*tcx.arena.alloc(ImplSource::Builtin( - ty::solve::BuiltinImplSource::Trivial, - Default::default(), - ))); - } - let obligation_cause = ObligationCause::dummy(); let obligation = Obligation::new(tcx, obligation_cause, param_env, trait_ref); diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index f14a45aa1e3..a65f9b347dc 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -1,9 +1,8 @@ -use rustc_data_structures::fx::FxIndexSet; +use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_hir::definitions::{DefPathData, DisambiguatorState}; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{self as hir, AmbigArg}; use rustc_middle::query::Providers; use rustc_middle::ty::{self, ImplTraitInTraitData, TyCtxt}; use rustc_middle::{bug, span_bug}; @@ -14,7 +13,6 @@ pub(crate) fn provide(providers: &mut Providers) { associated_item_def_ids, associated_items, associated_types_for_impl_traits_in_associated_fn, - associated_type_for_impl_trait_in_trait, impl_item_implementor_ids, ..*providers }; @@ -160,20 +158,22 @@ fn associated_item_from_impl_item_ref(impl_item_ref: &hir::ImplItemRef) -> ty::A container: ty::AssocItemContainer::Impl, } } -struct RPITVisitor { - rpits: FxIndexSet<LocalDefId>, +struct RPITVisitor<'tcx> { + tcx: TyCtxt<'tcx>, + synthetics: Vec<LocalDefId>, + data: DefPathData, + disambiguator: DisambiguatorState, } -impl<'tcx> Visitor<'tcx> for RPITVisitor { - fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx, AmbigArg>) { - if let hir::TyKind::OpaqueDef(opaq) = ty.kind - && self.rpits.insert(opaq.def_id) - { - for bound in opaq.bounds { - intravisit::walk_param_bound(self, bound); - } - } - intravisit::walk_ty(self, ty) +impl<'tcx> Visitor<'tcx> for RPITVisitor<'tcx> { + fn visit_opaque_ty(&mut self, opaque: &'tcx hir::OpaqueTy<'tcx>) -> Self::Result { + self.synthetics.push(associated_type_for_impl_trait_in_trait( + self.tcx, + opaque.def_id, + self.data, + &mut self.disambiguator, + )); + intravisit::walk_opaque_ty(self, opaque) } } @@ -194,14 +194,18 @@ fn associated_types_for_impl_traits_in_associated_fn( match tcx.def_kind(parent_def_id) { DefKind::Trait => { - let mut visitor = RPITVisitor { rpits: FxIndexSet::default() }; - if let Some(output) = tcx.hir_get_fn_output(fn_def_id) { + let data = DefPathData::AnonAssocTy(tcx.item_name(fn_def_id.to_def_id())); + let mut visitor = RPITVisitor { + tcx, + synthetics: vec![], + data, + disambiguator: DisambiguatorState::with(parent_def_id, data, 0), + }; visitor.visit_fn_ret_ty(output); - - tcx.arena.alloc_from_iter(visitor.rpits.iter().map(|opaque_ty_def_id| { - tcx.associated_type_for_impl_trait_in_trait(opaque_ty_def_id).to_def_id() - })) + tcx.arena.alloc_from_iter( + visitor.synthetics.into_iter().map(|def_id| def_id.to_def_id()), + ) } else { &[] } @@ -211,7 +215,6 @@ fn associated_types_for_impl_traits_in_associated_fn( let Some(trait_fn_def_id) = tcx.associated_item(fn_def_id).trait_item_def_id else { return &[]; }; - tcx.arena.alloc_from_iter( tcx.associated_types_for_impl_traits_in_associated_fn(trait_fn_def_id).iter().map( move |&trait_assoc_def_id| { @@ -236,6 +239,8 @@ fn associated_types_for_impl_traits_in_associated_fn( fn associated_type_for_impl_trait_in_trait( tcx: TyCtxt<'_>, opaque_ty_def_id: LocalDefId, + data: DefPathData, + disambiguator: &mut DisambiguatorState, ) -> LocalDefId { let (hir::OpaqueTyOrigin::FnReturn { parent: fn_def_id, .. } | hir::OpaqueTyOrigin::AsyncFn { parent: fn_def_id, .. }) = @@ -246,22 +251,15 @@ fn associated_type_for_impl_trait_in_trait( let trait_def_id = tcx.local_parent(fn_def_id); assert_eq!(tcx.def_kind(trait_def_id), DefKind::Trait); - // Collect all opaque types in return position for the method and use - // the index as the disambiguator to make an unique def path. - let mut visitor = RPITVisitor { rpits: FxIndexSet::default() }; - visitor.visit_fn_ret_ty(tcx.hir_get_fn_output(fn_def_id).unwrap()); - let disambiguator = visitor.rpits.get_index_of(&opaque_ty_def_id).unwrap().try_into().unwrap(); - let span = tcx.def_span(opaque_ty_def_id); // Also use the method name to create an unique def path. - let data = DefPathData::AnonAssocTy(tcx.item_name(fn_def_id.to_def_id())); let trait_assoc_ty = tcx.at(span).create_def( trait_def_id, // No name because this is an anonymous associated type. None, DefKind::AssocTy, Some(data), - &mut DisambiguatorState::with(trait_def_id, data, disambiguator), + disambiguator, ); let local_def_id = trait_assoc_ty.def_id(); diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index 3b4482146d4..3b313edea6f 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -179,7 +179,7 @@ impl<'tcx> OpaqueTypeCollector<'tcx> { } } - /// Checks the `#[define_opaque]` attributes on items and collectes opaques to define + /// Checks the `#[define_opaque]` attributes on items and collects opaques to define /// from the referenced types. #[instrument(level = "trace", skip(self))] fn collect_taits_from_defines_attr(&mut self) { diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index 8ba9e7105d6..6c77a90250a 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -13,7 +13,7 @@ use crate::{self as ty, Interner}; /// slightly different typing rules depending on the current context. See the /// doc comment for each variant for how and why they are used. /// -/// In most cases you can get the correct typing mode automically via: +/// In most cases you can get the correct typing mode automatically via: /// - `mir::Body::typing_mode` /// - `rustc_lint::LateContext::typing_mode` /// diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs index 8941360d2d0..7433c215e6f 100644 --- a/compiler/rustc_type_ir/src/search_graph/mod.rs +++ b/compiler/rustc_type_ir/src/search_graph/mod.rs @@ -390,8 +390,8 @@ impl PathsToNested { /// /// They are used when checking whether reevaluating a global cache /// would encounter a cycle or use a provisional cache entry given the -/// currentl search graph state. We need to disable the global cache -/// in this case as it could otherwise result in behaviorial differences. +/// current search graph state. We need to disable the global cache +/// in this case as it could otherwise result in behavioral differences. /// Cycles can impact behavior. The cycle ABA may have different final /// results from a the cycle BAB depending on the cycle root. /// @@ -513,7 +513,7 @@ pub struct SearchGraph<D: Delegate<Cx = X>, X: Cx = <D as Delegate>::Cx> { /// /// `nested_goals` are only used when checking whether global cache entries /// are applicable. This only cares about whether a goal is actually accessed. -/// Given that the usage of the provisional cache is fully determinstic, we +/// Given that the usage of the provisional cache is fully deterministic, we /// don't need to track the nested goals used while computing a provisional /// cache entry. enum UpdateParentGoalCtxt<'a, X: Cx> { diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 4536f555443..4e3f76de49e 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -1098,115 +1098,6 @@ impl<T: ?Sized> Box<T> { pub unsafe fn from_non_null(ptr: NonNull<T>) -> Self { unsafe { Self::from_raw(ptr.as_ptr()) } } -} - -impl<T: ?Sized, A: Allocator> Box<T, A> { - /// Constructs a box from a raw pointer in the given allocator. - /// - /// After calling this function, the raw pointer is owned by the - /// resulting `Box`. Specifically, the `Box` destructor will call - /// the destructor of `T` and free the allocated memory. For this - /// to be safe, the memory must have been allocated in accordance - /// with the [memory layout] used by `Box` . - /// - /// # Safety - /// - /// This function is unsafe because improper use may lead to - /// memory problems. For example, a double-free may occur if the - /// function is called twice on the same raw pointer. - /// - /// The raw pointer must point to a block of memory allocated by `alloc`. - /// - /// # Examples - /// - /// Recreate a `Box` which was previously converted to a raw pointer - /// using [`Box::into_raw_with_allocator`]: - /// ``` - /// #![feature(allocator_api)] - /// - /// use std::alloc::System; - /// - /// let x = Box::new_in(5, System); - /// let (ptr, alloc) = Box::into_raw_with_allocator(x); - /// let x = unsafe { Box::from_raw_in(ptr, alloc) }; - /// ``` - /// Manually create a `Box` from scratch by using the system allocator: - /// ``` - /// #![feature(allocator_api, slice_ptr_get)] - /// - /// use std::alloc::{Allocator, Layout, System}; - /// - /// unsafe { - /// let ptr = System.allocate(Layout::new::<i32>())?.as_mut_ptr() as *mut i32; - /// // In general .write is required to avoid attempting to destruct - /// // the (uninitialized) previous contents of `ptr`, though for this - /// // simple example `*ptr = 5` would have worked as well. - /// ptr.write(5); - /// let x = Box::from_raw_in(ptr, System); - /// } - /// # Ok::<(), std::alloc::AllocError>(()) - /// ``` - /// - /// [memory layout]: self#memory-layout - #[unstable(feature = "allocator_api", issue = "32838")] - #[inline] - pub unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Self { - Box(unsafe { Unique::new_unchecked(raw) }, alloc) - } - - /// Constructs a box from a `NonNull` pointer in the given allocator. - /// - /// After calling this function, the `NonNull` pointer is owned by - /// the resulting `Box`. Specifically, the `Box` destructor will call - /// the destructor of `T` and free the allocated memory. For this - /// to be safe, the memory must have been allocated in accordance - /// with the [memory layout] used by `Box` . - /// - /// # Safety - /// - /// This function is unsafe because improper use may lead to - /// memory problems. For example, a double-free may occur if the - /// function is called twice on the same raw pointer. - /// - /// The non-null pointer must point to a block of memory allocated by `alloc`. - /// - /// # Examples - /// - /// Recreate a `Box` which was previously converted to a `NonNull` pointer - /// using [`Box::into_non_null_with_allocator`]: - /// ``` - /// #![feature(allocator_api, box_vec_non_null)] - /// - /// use std::alloc::System; - /// - /// let x = Box::new_in(5, System); - /// let (non_null, alloc) = Box::into_non_null_with_allocator(x); - /// let x = unsafe { Box::from_non_null_in(non_null, alloc) }; - /// ``` - /// Manually create a `Box` from scratch by using the system allocator: - /// ``` - /// #![feature(allocator_api, box_vec_non_null, slice_ptr_get)] - /// - /// use std::alloc::{Allocator, Layout, System}; - /// - /// unsafe { - /// let non_null = System.allocate(Layout::new::<i32>())?.cast::<i32>(); - /// // In general .write is required to avoid attempting to destruct - /// // the (uninitialized) previous contents of `non_null`. - /// non_null.write(5); - /// let x = Box::from_non_null_in(non_null, System); - /// } - /// # Ok::<(), std::alloc::AllocError>(()) - /// ``` - /// - /// [memory layout]: self#memory-layout - #[unstable(feature = "allocator_api", issue = "32838")] - // #[unstable(feature = "box_vec_non_null", reason = "new API", issue = "130364")] - #[inline] - pub unsafe fn from_non_null_in(raw: NonNull<T>, alloc: A) -> Self { - // SAFETY: guaranteed by the caller. - unsafe { Box::from_raw_in(raw.as_ptr(), alloc) } - } /// Consumes the `Box`, returning a wrapped raw pointer. /// @@ -1259,8 +1150,11 @@ impl<T: ?Sized, A: Allocator> Box<T, A> { #[stable(feature = "box_raw", since = "1.4.0")] #[inline] pub fn into_raw(b: Self) -> *mut T { - // Make sure Miri realizes that we transition from a noalias pointer to a raw pointer here. - unsafe { &raw mut *&mut *Self::into_raw_with_allocator(b).0 } + // Avoid `into_raw_with_allocator` as that interacts poorly with Miri's Stacked Borrows. + let mut b = mem::ManuallyDrop::new(b); + // We go through the built-in deref for `Box`, which is crucial for Miri to recognize this + // operation for it's alias tracking. + &raw mut **b } /// Consumes the `Box`, returning a wrapped `NonNull` pointer. @@ -1322,6 +1216,115 @@ impl<T: ?Sized, A: Allocator> Box<T, A> { // SAFETY: `Box` is guaranteed to be non-null. unsafe { NonNull::new_unchecked(Self::into_raw(b)) } } +} + +impl<T: ?Sized, A: Allocator> Box<T, A> { + /// Constructs a box from a raw pointer in the given allocator. + /// + /// After calling this function, the raw pointer is owned by the + /// resulting `Box`. Specifically, the `Box` destructor will call + /// the destructor of `T` and free the allocated memory. For this + /// to be safe, the memory must have been allocated in accordance + /// with the [memory layout] used by `Box` . + /// + /// # Safety + /// + /// This function is unsafe because improper use may lead to + /// memory problems. For example, a double-free may occur if the + /// function is called twice on the same raw pointer. + /// + /// The raw pointer must point to a block of memory allocated by `alloc`. + /// + /// # Examples + /// + /// Recreate a `Box` which was previously converted to a raw pointer + /// using [`Box::into_raw_with_allocator`]: + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// let x = Box::new_in(5, System); + /// let (ptr, alloc) = Box::into_raw_with_allocator(x); + /// let x = unsafe { Box::from_raw_in(ptr, alloc) }; + /// ``` + /// Manually create a `Box` from scratch by using the system allocator: + /// ``` + /// #![feature(allocator_api, slice_ptr_get)] + /// + /// use std::alloc::{Allocator, Layout, System}; + /// + /// unsafe { + /// let ptr = System.allocate(Layout::new::<i32>())?.as_mut_ptr() as *mut i32; + /// // In general .write is required to avoid attempting to destruct + /// // the (uninitialized) previous contents of `ptr`, though for this + /// // simple example `*ptr = 5` would have worked as well. + /// ptr.write(5); + /// let x = Box::from_raw_in(ptr, System); + /// } + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + /// + /// [memory layout]: self#memory-layout + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Self { + Box(unsafe { Unique::new_unchecked(raw) }, alloc) + } + + /// Constructs a box from a `NonNull` pointer in the given allocator. + /// + /// After calling this function, the `NonNull` pointer is owned by + /// the resulting `Box`. Specifically, the `Box` destructor will call + /// the destructor of `T` and free the allocated memory. For this + /// to be safe, the memory must have been allocated in accordance + /// with the [memory layout] used by `Box` . + /// + /// # Safety + /// + /// This function is unsafe because improper use may lead to + /// memory problems. For example, a double-free may occur if the + /// function is called twice on the same raw pointer. + /// + /// The non-null pointer must point to a block of memory allocated by `alloc`. + /// + /// # Examples + /// + /// Recreate a `Box` which was previously converted to a `NonNull` pointer + /// using [`Box::into_non_null_with_allocator`]: + /// ``` + /// #![feature(allocator_api, box_vec_non_null)] + /// + /// use std::alloc::System; + /// + /// let x = Box::new_in(5, System); + /// let (non_null, alloc) = Box::into_non_null_with_allocator(x); + /// let x = unsafe { Box::from_non_null_in(non_null, alloc) }; + /// ``` + /// Manually create a `Box` from scratch by using the system allocator: + /// ``` + /// #![feature(allocator_api, box_vec_non_null, slice_ptr_get)] + /// + /// use std::alloc::{Allocator, Layout, System}; + /// + /// unsafe { + /// let non_null = System.allocate(Layout::new::<i32>())?.cast::<i32>(); + /// // In general .write is required to avoid attempting to destruct + /// // the (uninitialized) previous contents of `non_null`. + /// non_null.write(5); + /// let x = Box::from_non_null_in(non_null, System); + /// } + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + /// + /// [memory layout]: self#memory-layout + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "box_vec_non_null", reason = "new API", issue = "130364")] + #[inline] + pub unsafe fn from_non_null_in(raw: NonNull<T>, alloc: A) -> Self { + // SAFETY: guaranteed by the caller. + unsafe { Box::from_raw_in(raw.as_ptr(), alloc) } + } /// Consumes the `Box`, returning a wrapped raw pointer and the allocator. /// @@ -1602,7 +1605,9 @@ impl<T: ?Sized, A: Allocator> Box<T, A> { where A: 'a, { - unsafe { &mut *Box::into_raw(b) } + let (ptr, alloc) = Box::into_raw_with_allocator(b); + mem::forget(alloc); + unsafe { &mut *ptr } } /// Converts a `Box<T>` into a `Pin<Box<T>>`. If `T` does not implement [`Unpin`], then diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 010d17f7476..5018ff4ad71 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1322,6 +1322,30 @@ impl<T: ?Sized> Rc<T> { unsafe { Self::from_raw_in(ptr, Global) } } + /// Consumes the `Rc`, returning the wrapped pointer. + /// + /// To avoid a memory leak the pointer must be converted back to an `Rc` using + /// [`Rc::from_raw`]. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let x = Rc::new("hello".to_owned()); + /// let x_ptr = Rc::into_raw(x); + /// assert_eq!(unsafe { &*x_ptr }, "hello"); + /// # // Prevent leaks for Miri. + /// # drop(unsafe { Rc::from_raw(x_ptr) }); + /// ``` + #[must_use = "losing the pointer will leak memory"] + #[stable(feature = "rc_raw", since = "1.17.0")] + #[rustc_never_returns_null_ptr] + pub fn into_raw(this: Self) -> *const T { + let this = ManuallyDrop::new(this); + Self::as_ptr(&*this) + } + /// Increments the strong reference count on the `Rc<T>` associated with the /// provided pointer by one. /// @@ -1408,30 +1432,6 @@ impl<T: ?Sized, A: Allocator> Rc<T, A> { &this.alloc } - /// Consumes the `Rc`, returning the wrapped pointer. - /// - /// To avoid a memory leak the pointer must be converted back to an `Rc` using - /// [`Rc::from_raw`]. - /// - /// # Examples - /// - /// ``` - /// use std::rc::Rc; - /// - /// let x = Rc::new("hello".to_owned()); - /// let x_ptr = Rc::into_raw(x); - /// assert_eq!(unsafe { &*x_ptr }, "hello"); - /// # // Prevent leaks for Miri. - /// # drop(unsafe { Rc::from_raw(x_ptr) }); - /// ``` - #[must_use = "losing the pointer will leak memory"] - #[stable(feature = "rc_raw", since = "1.17.0")] - #[rustc_never_returns_null_ptr] - pub fn into_raw(this: Self) -> *const T { - let this = ManuallyDrop::new(this); - Self::as_ptr(&*this) - } - /// Consumes the `Rc`, returning the wrapped pointer and allocator. /// /// To avoid a memory leak the pointer must be converted back to an `Rc` using @@ -1525,7 +1525,7 @@ impl<T: ?Sized, A: Allocator> Rc<T, A> { /// use std::alloc::System; /// /// let x = Rc::new_in("hello".to_owned(), System); - /// let x_ptr = Rc::into_raw(x); + /// let (x_ptr, _alloc) = Rc::into_raw_with_allocator(x); /// /// unsafe { /// // Convert back to an `Rc` to prevent leak. @@ -1547,7 +1547,7 @@ impl<T: ?Sized, A: Allocator> Rc<T, A> { /// use std::alloc::System; /// /// let x: Rc<[u32], _> = Rc::new_in([1, 2, 3], System); - /// let x_ptr: *const [u32] = Rc::into_raw(x); + /// let x_ptr: *const [u32] = Rc::into_raw_with_allocator(x).0; /// /// unsafe { /// let x: Rc<[u32; 3], _> = Rc::from_raw_in(x_ptr.cast::<[u32; 3]>(), System); @@ -1648,7 +1648,7 @@ impl<T: ?Sized, A: Allocator> Rc<T, A> { /// let five = Rc::new_in(5, System); /// /// unsafe { - /// let ptr = Rc::into_raw(five); + /// let (ptr, _alloc) = Rc::into_raw_with_allocator(five); /// Rc::increment_strong_count_in(ptr, System); /// /// let five = Rc::from_raw_in(ptr, System); @@ -1694,7 +1694,7 @@ impl<T: ?Sized, A: Allocator> Rc<T, A> { /// let five = Rc::new_in(5, System); /// /// unsafe { - /// let ptr = Rc::into_raw(five); + /// let (ptr, _alloc) = Rc::into_raw_with_allocator(five); /// Rc::increment_strong_count_in(ptr, System); /// /// let five = Rc::from_raw_in(ptr, System); @@ -3123,6 +3123,39 @@ impl<T: ?Sized> Weak<T> { pub unsafe fn from_raw(ptr: *const T) -> Self { unsafe { Self::from_raw_in(ptr, Global) } } + + /// Consumes the `Weak<T>` and turns it into a raw pointer. + /// + /// This converts the weak pointer into a raw pointer, while still preserving the ownership of + /// one weak reference (the weak count is not modified by this operation). It can be turned + /// back into the `Weak<T>` with [`from_raw`]. + /// + /// The same restrictions of accessing the target of the pointer as with + /// [`as_ptr`] apply. + /// + /// # Examples + /// + /// ``` + /// use std::rc::{Rc, Weak}; + /// + /// let strong = Rc::new("hello".to_owned()); + /// let weak = Rc::downgrade(&strong); + /// let raw = weak.into_raw(); + /// + /// assert_eq!(1, Rc::weak_count(&strong)); + /// assert_eq!("hello", unsafe { &*raw }); + /// + /// drop(unsafe { Weak::from_raw(raw) }); + /// assert_eq!(0, Rc::weak_count(&strong)); + /// ``` + /// + /// [`from_raw`]: Weak::from_raw + /// [`as_ptr`]: Weak::as_ptr + #[must_use = "losing the pointer will leak memory"] + #[stable(feature = "weak_into_raw", since = "1.45.0")] + pub fn into_raw(self) -> *const T { + mem::ManuallyDrop::new(self).as_ptr() + } } impl<T: ?Sized, A: Allocator> Weak<T, A> { @@ -3175,39 +3208,6 @@ impl<T: ?Sized, A: Allocator> Weak<T, A> { } } - /// Consumes the `Weak<T>` and turns it into a raw pointer. - /// - /// This converts the weak pointer into a raw pointer, while still preserving the ownership of - /// one weak reference (the weak count is not modified by this operation). It can be turned - /// back into the `Weak<T>` with [`from_raw`]. - /// - /// The same restrictions of accessing the target of the pointer as with - /// [`as_ptr`] apply. - /// - /// # Examples - /// - /// ``` - /// use std::rc::{Rc, Weak}; - /// - /// let strong = Rc::new("hello".to_owned()); - /// let weak = Rc::downgrade(&strong); - /// let raw = weak.into_raw(); - /// - /// assert_eq!(1, Rc::weak_count(&strong)); - /// assert_eq!("hello", unsafe { &*raw }); - /// - /// drop(unsafe { Weak::from_raw(raw) }); - /// assert_eq!(0, Rc::weak_count(&strong)); - /// ``` - /// - /// [`from_raw`]: Weak::from_raw - /// [`as_ptr`]: Weak::as_ptr - #[must_use = "losing the pointer will leak memory"] - #[stable(feature = "weak_into_raw", since = "1.45.0")] - pub fn into_raw(self) -> *const T { - mem::ManuallyDrop::new(self).as_ptr() - } - /// Consumes the `Weak<T>`, returning the wrapped pointer and allocator. /// /// This converts the weak pointer into a raw pointer, while still preserving the ownership of diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 1e3c03977bd..b8925f4544f 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1467,6 +1467,30 @@ impl<T: ?Sized> Arc<T> { unsafe { Arc::from_raw_in(ptr, Global) } } + /// Consumes the `Arc`, returning the wrapped pointer. + /// + /// To avoid a memory leak the pointer must be converted back to an `Arc` using + /// [`Arc::from_raw`]. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let x = Arc::new("hello".to_owned()); + /// let x_ptr = Arc::into_raw(x); + /// assert_eq!(unsafe { &*x_ptr }, "hello"); + /// # // Prevent leaks for Miri. + /// # drop(unsafe { Arc::from_raw(x_ptr) }); + /// ``` + #[must_use = "losing the pointer will leak memory"] + #[stable(feature = "rc_raw", since = "1.17.0")] + #[rustc_never_returns_null_ptr] + pub fn into_raw(this: Self) -> *const T { + let this = ManuallyDrop::new(this); + Self::as_ptr(&*this) + } + /// Increments the strong reference count on the `Arc<T>` associated with the /// provided pointer by one. /// @@ -1558,30 +1582,6 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> { &this.alloc } - /// Consumes the `Arc`, returning the wrapped pointer. - /// - /// To avoid a memory leak the pointer must be converted back to an `Arc` using - /// [`Arc::from_raw`]. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let x = Arc::new("hello".to_owned()); - /// let x_ptr = Arc::into_raw(x); - /// assert_eq!(unsafe { &*x_ptr }, "hello"); - /// # // Prevent leaks for Miri. - /// # drop(unsafe { Arc::from_raw(x_ptr) }); - /// ``` - #[must_use = "losing the pointer will leak memory"] - #[stable(feature = "rc_raw", since = "1.17.0")] - #[rustc_never_returns_null_ptr] - pub fn into_raw(this: Self) -> *const T { - let this = ManuallyDrop::new(this); - Self::as_ptr(&*this) - } - /// Consumes the `Arc`, returning the wrapped pointer and allocator. /// /// To avoid a memory leak the pointer must be converted back to an `Arc` using @@ -1676,7 +1676,7 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> { /// use std::alloc::System; /// /// let x = Arc::new_in("hello".to_owned(), System); - /// let x_ptr = Arc::into_raw(x); + /// let (x_ptr, alloc) = Arc::into_raw_with_allocator(x); /// /// unsafe { /// // Convert back to an `Arc` to prevent leak. @@ -1698,7 +1698,7 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> { /// use std::alloc::System; /// /// let x: Arc<[u32], _> = Arc::new_in([1, 2, 3], System); - /// let x_ptr: *const [u32] = Arc::into_raw(x); + /// let x_ptr: *const [u32] = Arc::into_raw_with_allocator(x).0; /// /// unsafe { /// let x: Arc<[u32; 3], _> = Arc::from_raw_in(x_ptr.cast::<[u32; 3]>(), System); @@ -1850,7 +1850,7 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> { /// let five = Arc::new_in(5, System); /// /// unsafe { - /// let ptr = Arc::into_raw(five); + /// let (ptr, _alloc) = Arc::into_raw_with_allocator(five); /// Arc::increment_strong_count_in(ptr, System); /// /// // This assertion is deterministic because we haven't shared @@ -1899,7 +1899,7 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> { /// let five = Arc::new_in(5, System); /// /// unsafe { - /// let ptr = Arc::into_raw(five); + /// let (ptr, _alloc) = Arc::into_raw_with_allocator(five); /// Arc::increment_strong_count_in(ptr, System); /// /// // Those assertions are deterministic because we haven't shared @@ -2863,6 +2863,39 @@ impl<T: ?Sized> Weak<T> { pub unsafe fn from_raw(ptr: *const T) -> Self { unsafe { Weak::from_raw_in(ptr, Global) } } + + /// Consumes the `Weak<T>` and turns it into a raw pointer. + /// + /// This converts the weak pointer into a raw pointer, while still preserving the ownership of + /// one weak reference (the weak count is not modified by this operation). It can be turned + /// back into the `Weak<T>` with [`from_raw`]. + /// + /// The same restrictions of accessing the target of the pointer as with + /// [`as_ptr`] apply. + /// + /// # Examples + /// + /// ``` + /// use std::sync::{Arc, Weak}; + /// + /// let strong = Arc::new("hello".to_owned()); + /// let weak = Arc::downgrade(&strong); + /// let raw = weak.into_raw(); + /// + /// assert_eq!(1, Arc::weak_count(&strong)); + /// assert_eq!("hello", unsafe { &*raw }); + /// + /// drop(unsafe { Weak::from_raw(raw) }); + /// assert_eq!(0, Arc::weak_count(&strong)); + /// ``` + /// + /// [`from_raw`]: Weak::from_raw + /// [`as_ptr`]: Weak::as_ptr + #[must_use = "losing the pointer will leak memory"] + #[stable(feature = "weak_into_raw", since = "1.45.0")] + pub fn into_raw(self) -> *const T { + ManuallyDrop::new(self).as_ptr() + } } impl<T: ?Sized, A: Allocator> Weak<T, A> { @@ -2915,39 +2948,6 @@ impl<T: ?Sized, A: Allocator> Weak<T, A> { } } - /// Consumes the `Weak<T>` and turns it into a raw pointer. - /// - /// This converts the weak pointer into a raw pointer, while still preserving the ownership of - /// one weak reference (the weak count is not modified by this operation). It can be turned - /// back into the `Weak<T>` with [`from_raw`]. - /// - /// The same restrictions of accessing the target of the pointer as with - /// [`as_ptr`] apply. - /// - /// # Examples - /// - /// ``` - /// use std::sync::{Arc, Weak}; - /// - /// let strong = Arc::new("hello".to_owned()); - /// let weak = Arc::downgrade(&strong); - /// let raw = weak.into_raw(); - /// - /// assert_eq!(1, Arc::weak_count(&strong)); - /// assert_eq!("hello", unsafe { &*raw }); - /// - /// drop(unsafe { Weak::from_raw(raw) }); - /// assert_eq!(0, Arc::weak_count(&strong)); - /// ``` - /// - /// [`from_raw`]: Weak::from_raw - /// [`as_ptr`]: Weak::as_ptr - #[must_use = "losing the pointer will leak memory"] - #[stable(feature = "weak_into_raw", since = "1.45.0")] - pub fn into_raw(self) -> *const T { - ManuallyDrop::new(self).as_ptr() - } - /// Consumes the `Weak<T>`, returning the wrapped pointer and allocator. /// /// This converts the weak pointer into a raw pointer, while still preserving the ownership of diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 5bd82560da7..c8341750f4d 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -761,6 +761,88 @@ impl<T> Vec<T> { pub fn peek_mut(&mut self) -> Option<PeekMut<'_, T>> { PeekMut::new(self) } + + /// Decomposes a `Vec<T>` into its raw components: `(pointer, length, capacity)`. + /// + /// Returns the raw pointer to the underlying data, the length of + /// the vector (in elements), and the allocated capacity of the + /// data (in elements). These are the same arguments in the same + /// order as the arguments to [`from_raw_parts`]. + /// + /// After calling this function, the caller is responsible for the + /// memory previously managed by the `Vec`. The only way to do + /// this is to convert the raw pointer, length, and capacity back + /// into a `Vec` with the [`from_raw_parts`] function, allowing + /// the destructor to perform the cleanup. + /// + /// [`from_raw_parts`]: Vec::from_raw_parts + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_into_raw_parts)] + /// let v: Vec<i32> = vec![-1, 0, 1]; + /// + /// let (ptr, len, cap) = v.into_raw_parts(); + /// + /// let rebuilt = unsafe { + /// // We can now make changes to the components, such as + /// // transmuting the raw pointer to a compatible type. + /// let ptr = ptr as *mut u32; + /// + /// Vec::from_raw_parts(ptr, len, cap) + /// }; + /// assert_eq!(rebuilt, [4294967295, 0, 1]); + /// ``` + #[must_use = "losing the pointer will leak memory"] + #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] + pub fn into_raw_parts(self) -> (*mut T, usize, usize) { + let mut me = ManuallyDrop::new(self); + (me.as_mut_ptr(), me.len(), me.capacity()) + } + + #[doc(alias = "into_non_null_parts")] + /// Decomposes a `Vec<T>` into its raw components: `(NonNull pointer, length, capacity)`. + /// + /// Returns the `NonNull` pointer to the underlying data, the length of + /// the vector (in elements), and the allocated capacity of the + /// data (in elements). These are the same arguments in the same + /// order as the arguments to [`from_parts`]. + /// + /// After calling this function, the caller is responsible for the + /// memory previously managed by the `Vec`. The only way to do + /// this is to convert the `NonNull` pointer, length, and capacity back + /// into a `Vec` with the [`from_parts`] function, allowing + /// the destructor to perform the cleanup. + /// + /// [`from_parts`]: Vec::from_parts + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_into_raw_parts, box_vec_non_null)] + /// + /// let v: Vec<i32> = vec![-1, 0, 1]; + /// + /// let (ptr, len, cap) = v.into_parts(); + /// + /// let rebuilt = unsafe { + /// // We can now make changes to the components, such as + /// // transmuting the raw pointer to a compatible type. + /// let ptr = ptr.cast::<u32>(); + /// + /// Vec::from_parts(ptr, len, cap) + /// }; + /// assert_eq!(rebuilt, [4294967295, 0, 1]); + /// ``` + #[must_use = "losing the pointer will leak memory"] + #[unstable(feature = "box_vec_non_null", reason = "new API", issue = "130364")] + // #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] + pub fn into_parts(self) -> (NonNull<T>, usize, usize) { + let (ptr, len, capacity) = self.into_raw_parts(); + // SAFETY: A `Vec` always has a non-null pointer. + (unsafe { NonNull::new_unchecked(ptr) }, len, capacity) + } } impl<T, A: Allocator> Vec<T, A> { @@ -1095,88 +1177,6 @@ impl<T, A: Allocator> Vec<T, A> { unsafe { Vec { buf: RawVec::from_nonnull_in(ptr, capacity, alloc), len: length } } } - /// Decomposes a `Vec<T>` into its raw components: `(pointer, length, capacity)`. - /// - /// Returns the raw pointer to the underlying data, the length of - /// the vector (in elements), and the allocated capacity of the - /// data (in elements). These are the same arguments in the same - /// order as the arguments to [`from_raw_parts`]. - /// - /// After calling this function, the caller is responsible for the - /// memory previously managed by the `Vec`. The only way to do - /// this is to convert the raw pointer, length, and capacity back - /// into a `Vec` with the [`from_raw_parts`] function, allowing - /// the destructor to perform the cleanup. - /// - /// [`from_raw_parts`]: Vec::from_raw_parts - /// - /// # Examples - /// - /// ``` - /// #![feature(vec_into_raw_parts)] - /// let v: Vec<i32> = vec![-1, 0, 1]; - /// - /// let (ptr, len, cap) = v.into_raw_parts(); - /// - /// let rebuilt = unsafe { - /// // We can now make changes to the components, such as - /// // transmuting the raw pointer to a compatible type. - /// let ptr = ptr as *mut u32; - /// - /// Vec::from_raw_parts(ptr, len, cap) - /// }; - /// assert_eq!(rebuilt, [4294967295, 0, 1]); - /// ``` - #[must_use = "losing the pointer will leak memory"] - #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] - pub fn into_raw_parts(self) -> (*mut T, usize, usize) { - let mut me = ManuallyDrop::new(self); - (me.as_mut_ptr(), me.len(), me.capacity()) - } - - #[doc(alias = "into_non_null_parts")] - /// Decomposes a `Vec<T>` into its raw components: `(NonNull pointer, length, capacity)`. - /// - /// Returns the `NonNull` pointer to the underlying data, the length of - /// the vector (in elements), and the allocated capacity of the - /// data (in elements). These are the same arguments in the same - /// order as the arguments to [`from_parts`]. - /// - /// After calling this function, the caller is responsible for the - /// memory previously managed by the `Vec`. The only way to do - /// this is to convert the `NonNull` pointer, length, and capacity back - /// into a `Vec` with the [`from_parts`] function, allowing - /// the destructor to perform the cleanup. - /// - /// [`from_parts`]: Vec::from_parts - /// - /// # Examples - /// - /// ``` - /// #![feature(vec_into_raw_parts, box_vec_non_null)] - /// - /// let v: Vec<i32> = vec![-1, 0, 1]; - /// - /// let (ptr, len, cap) = v.into_parts(); - /// - /// let rebuilt = unsafe { - /// // We can now make changes to the components, such as - /// // transmuting the raw pointer to a compatible type. - /// let ptr = ptr.cast::<u32>(); - /// - /// Vec::from_parts(ptr, len, cap) - /// }; - /// assert_eq!(rebuilt, [4294967295, 0, 1]); - /// ``` - #[must_use = "losing the pointer will leak memory"] - #[unstable(feature = "box_vec_non_null", reason = "new API", issue = "130364")] - // #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] - pub fn into_parts(self) -> (NonNull<T>, usize, usize) { - let (ptr, len, capacity) = self.into_raw_parts(); - // SAFETY: A `Vec` always has a non-null pointer. - (unsafe { NonNull::new_unchecked(ptr) }, len, capacity) - } - /// Decomposes a `Vec<T>` into its raw components: `(pointer, length, capacity, allocator)`. /// /// Returns the raw pointer to the underlying data, the length of the vector (in elements), @@ -3031,6 +3031,61 @@ impl<T, A: Allocator> Vec<T, A> { (initialized, spare, &mut self.len) } } + + /// Groups every `N` elements in the `Vec<T>` into chunks to produce a `Vec<[T; N]>`, dropping + /// elements in the remainder. `N` must be greater than zero. + /// + /// If the capacity is not a multiple of the chunk size, the buffer will shrink down to the + /// nearest multiple with a reallocation or deallocation. + /// + /// This function can be used to reverse [`Vec::into_flattened`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_into_chunks)] + /// + /// let vec = vec![0, 1, 2, 3, 4, 5, 6, 7]; + /// assert_eq!(vec.into_chunks::<3>(), [[0, 1, 2], [3, 4, 5]]); + /// + /// let vec = vec![0, 1, 2, 3]; + /// let chunks: Vec<[u8; 10]> = vec.into_chunks(); + /// assert!(chunks.is_empty()); + /// + /// let flat = vec![0; 8 * 8 * 8]; + /// let reshaped: Vec<[[[u8; 8]; 8]; 8]> = flat.into_chunks().into_chunks().into_chunks(); + /// assert_eq!(reshaped.len(), 1); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "vec_into_chunks", issue = "142137")] + pub fn into_chunks<const N: usize>(mut self) -> Vec<[T; N], A> { + const { + assert!(N != 0, "chunk size must be greater than zero"); + } + + let (len, cap) = (self.len(), self.capacity()); + + let len_remainder = len % N; + if len_remainder != 0 { + self.truncate(len - len_remainder); + } + + let cap_remainder = cap % N; + if !T::IS_ZST && cap_remainder != 0 { + self.buf.shrink_to_fit(cap - cap_remainder); + } + + let (ptr, _, _, alloc) = self.into_raw_parts_with_alloc(); + + // SAFETY: + // - `ptr` and `alloc` were just returned from `self.into_raw_parts_with_alloc()` + // - `[T; N]` has the same alignment as `T` + // - `size_of::<[T; N]>() * cap / N == size_of::<T>() * cap` + // - `len / N <= cap / N` because `len <= cap` + // - the allocated memory consists of `len / N` valid values of type `[T; N]` + // - `cap / N` fits the size of the allocated memory after shrinking + unsafe { Vec::from_raw_parts_in(ptr.cast(), len / N, cap / N, alloc) } + } } impl<T: Clone, A: Allocator> Vec<T, A> { diff --git a/library/core/src/bool.rs b/library/core/src/bool.rs index 2016ece007e..99268d6182f 100644 --- a/library/core/src/bool.rs +++ b/library/core/src/bool.rs @@ -61,4 +61,71 @@ impl bool { pub fn then<T, F: FnOnce() -> T>(self, f: F) -> Option<T> { if self { Some(f()) } else { None } } + + /// Returns `Ok(())` if the `bool` is [`true`](../std/keyword.true.html), + /// or `Err(err)` otherwise. + /// + /// Arguments passed to `ok_or` are eagerly evaluated; if you are + /// passing the result of a function call, it is recommended to use + /// [`ok_or_else`], which is lazily evaluated. + /// + /// [`ok_or_else`]: bool::ok_or_else + /// + /// # Examples + /// + /// ``` + /// #![feature(bool_to_result)] + /// + /// assert_eq!(false.ok_or(0), Err(0)); + /// assert_eq!(true.ok_or(0), Ok(())); + /// ``` + /// + /// ``` + /// #![feature(bool_to_result)] + /// + /// let mut a = 0; + /// let mut function_with_side_effects = || { a += 1; }; + /// + /// assert!(true.ok_or(function_with_side_effects()).is_ok()); + /// assert!(false.ok_or(function_with_side_effects()).is_err()); + /// + /// // `a` is incremented twice because the value passed to `ok_or` is + /// // evaluated eagerly. + /// assert_eq!(a, 2); + /// ``` + #[unstable(feature = "bool_to_result", issue = "142748")] + #[inline] + pub fn ok_or<E>(self, err: E) -> Result<(), E> { + if self { Ok(()) } else { Err(err) } + } + + /// Returns `Ok(())` if the `bool` is [`true`](../std/keyword.true.html), + /// or `Err(f())` otherwise. + /// + /// # Examples + /// + /// ``` + /// #![feature(bool_to_result)] + /// + /// assert_eq!(false.ok_or_else(|| 0), Err(0)); + /// assert_eq!(true.ok_or_else(|| 0), Ok(())); + /// ``` + /// + /// ``` + /// #![feature(bool_to_result)] + /// + /// let mut a = 0; + /// + /// assert!(true.ok_or_else(|| { a += 1; }).is_ok()); + /// assert!(false.ok_or_else(|| { a += 1; }).is_err()); + /// + /// // `a` is incremented once because the closure is evaluated lazily by + /// // `ok_or_else`. + /// assert_eq!(a, 1); + /// ``` + #[unstable(feature = "bool_to_result", issue = "142748")] + #[inline] + pub fn ok_or_else<E, F: FnOnce() -> E>(self, f: F) -> Result<(), E> { + if self { Ok(()) } else { Err(f()) } + } } diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index 0aa8f47462d..b1ca3701fa5 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -1449,7 +1449,6 @@ pub trait PartialOrd<Rhs: PointeeSized = Self>: PartialEq<Rhs> + PointeeSized { /// check `==` and `<` separately to do rather than needing to calculate /// (then optimize out) the three-way `Ordering` result. #[inline] - #[must_use] // Added to improve the behaviour of tuples; not necessarily stabilization-track. #[unstable(feature = "partial_ord_chaining_methods", issue = "none")] #[doc(hidden)] @@ -1459,7 +1458,6 @@ pub trait PartialOrd<Rhs: PointeeSized = Self>: PartialEq<Rhs> + PointeeSized { /// Same as `__chaining_lt`, but for `<=` instead of `<`. #[inline] - #[must_use] #[unstable(feature = "partial_ord_chaining_methods", issue = "none")] #[doc(hidden)] fn __chaining_le(&self, other: &Rhs) -> ControlFlow<bool> { @@ -1468,7 +1466,6 @@ pub trait PartialOrd<Rhs: PointeeSized = Self>: PartialEq<Rhs> + PointeeSized { /// Same as `__chaining_lt`, but for `>` instead of `<`. #[inline] - #[must_use] #[unstable(feature = "partial_ord_chaining_methods", issue = "none")] #[doc(hidden)] fn __chaining_gt(&self, other: &Rhs) -> ControlFlow<bool> { @@ -1477,7 +1474,6 @@ pub trait PartialOrd<Rhs: PointeeSized = Self>: PartialEq<Rhs> + PointeeSized { /// Same as `__chaining_lt`, but for `>=` instead of `<`. #[inline] - #[must_use] #[unstable(feature = "partial_ord_chaining_methods", issue = "none")] #[doc(hidden)] fn __chaining_ge(&self, other: &Rhs) -> ControlFlow<bool> { diff --git a/library/core/src/error.rs b/library/core/src/error.rs index bfa392003b9..7f5c6ac42bc 100644 --- a/library/core/src/error.rs +++ b/library/core/src/error.rs @@ -347,7 +347,7 @@ impl dyn Error { /// let b = B(Some(Box::new(A))); /// /// // let err : Box<Error> = b.into(); // or - /// let err = &b as &(dyn Error); + /// let err = &b as &dyn Error; /// /// let mut iter = err.sources(); /// diff --git a/library/core/src/ffi/c_char.md b/library/core/src/ffi/c_char.md index b262a3663b3..119b739a39e 100644 --- a/library/core/src/ffi/c_char.md +++ b/library/core/src/ffi/c_char.md @@ -1,6 +1,6 @@ Equivalent to C's `char` type. -[C's `char` type] is completely unlike [Rust's `char` type]; while Rust's type represents a unicode scalar value, C's `char` type is just an ordinary integer. On modern architectures this type will always be either [`i8`] or [`u8`], as they use byte-addresses memory with 8-bit bytes. +[C's `char` type] is completely unlike [Rust's `char` type]; while Rust's type represents a unicode scalar value, C's `char` type is just an ordinary integer. On modern architectures this type will always be either [`i8`] or [`u8`], as they use byte-addressed memory with 8-bit bytes. C chars are most commonly used to make C strings. Unlike Rust, where the length of a string is included alongside the string, C strings mark the end of a string with the character `'\0'`. See `CStr` for more information. diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 2be8d37bbee..c593737af8a 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -2867,7 +2867,7 @@ macro_rules! tuple { maybe_tuple_doc! { $($name)+ @ #[stable(feature = "rust1", since = "1.0.0")] - impl<$($name:Debug),+> Debug for ($($name,)+) where last_type!($($name,)+): ?Sized { + impl<$($name:Debug),+> Debug for ($($name,)+) { #[allow(non_snake_case, unused_assignments)] fn fmt(&self, f: &mut Formatter<'_>) -> Result { let mut builder = f.debug_tuple(""); @@ -2898,11 +2898,6 @@ macro_rules! maybe_tuple_doc { }; } -macro_rules! last_type { - ($a:ident,) => { $a }; - ($a:ident, $($rest_a:ident,)+) => { last_type!($($rest_a,)+) }; -} - tuple! { E, D, C, B, A, Z, Y, X, W, V, U, T, } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs index 42af595ae41..80f462263a5 100644 --- a/library/core/src/fmt/num.rs +++ b/library/core/src/fmt/num.rs @@ -589,7 +589,7 @@ impl fmt::Display for i128 { } impl u128 { - /// Format optimized for u128. Computation of 128 bits is limited by proccessing + /// Format optimized for u128. Computation of 128 bits is limited by processing /// in batches of 16 decimals at a time. #[doc(hidden)] #[unstable( diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs index efda64791d4..a10c85640bb 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -886,7 +886,7 @@ mod impls { maybe_tuple_doc! { $($name)+ @ #[stable(feature = "rust1", since = "1.0.0")] - impl<$($name: Hash),+> Hash for ($($name,)+) where last_type!($($name,)+): ?Sized { + impl<$($name: Hash),+> Hash for ($($name,)+) { #[allow(non_snake_case)] #[inline] fn hash<S: Hasher>(&self, state: &mut S) { @@ -912,11 +912,6 @@ mod impls { }; } - macro_rules! last_type { - ($a:ident,) => { $a }; - ($a:ident, $($rest_a:ident,)+) => { last_type!($($rest_a,)+) }; - } - impl_hash_tuple! {} impl_hash_tuple! { T } impl_hash_tuple! { T B } diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 4250de9fb2b..ab99492638e 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -459,7 +459,7 @@ pub const fn unlikely(b: bool) -> bool { /// Therefore, implementations must not require the user to uphold /// any safety invariants. /// -/// The public form of this instrinsic is [`core::hint::select_unpredictable`]. +/// The public form of this intrinsic is [`core::hint::select_unpredictable`]. /// However unlike the public form, the intrinsic will not drop the value that /// is not selected. #[unstable(feature = "core_intrinsics", issue = "none")] @@ -472,7 +472,8 @@ pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T { } /// A guard for unsafe functions that cannot ever be executed if `T` is uninhabited: -/// This will statically either panic, or do nothing. +/// This will statically either panic, or do nothing. It does not *guarantee* to ever panic, +/// and should only be called if an assertion failure will imply language UB in the following code. /// /// This intrinsic does not have a stable counterpart. #[rustc_intrinsic_const_stable_indirect] @@ -481,7 +482,9 @@ pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T { pub const fn assert_inhabited<T>(); /// A guard for unsafe functions that cannot ever be executed if `T` does not permit -/// zero-initialization: This will statically either panic, or do nothing. +/// zero-initialization: This will statically either panic, or do nothing. It does not *guarantee* +/// to ever panic, and should only be called if an assertion failure will imply language UB in the +/// following code. /// /// This intrinsic does not have a stable counterpart. #[rustc_intrinsic_const_stable_indirect] @@ -489,7 +492,9 @@ pub const fn assert_inhabited<T>(); #[rustc_intrinsic] pub const fn assert_zero_valid<T>(); -/// A guard for `std::mem::uninitialized`. This will statically either panic, or do nothing. +/// A guard for `std::mem::uninitialized`. This will statically either panic, or do nothing. It does +/// not *guarantee* to ever panic, and should only be called if an assertion failure will imply +/// language UB in the following code. /// /// This intrinsic does not have a stable counterpart. #[rustc_intrinsic_const_stable_indirect] @@ -2290,7 +2295,7 @@ where /// used inside the `if const`. /// Note that the two arms of this `if` really each become their own function, which is why the /// macro supports setting attributes for those functions. The runtime function is always -/// markes as `#[inline]`. +/// marked as `#[inline]`. /// /// See [`const_eval_select()`] for the rules and requirements around that intrinsic. pub(crate) macro const_eval_select { @@ -2530,7 +2535,7 @@ pub const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) /// Returns whether we should perform contract-checking at runtime. /// /// This is meant to be similar to the ub_checks intrinsic, in terms -/// of not prematurely commiting at compile-time to whether contract +/// of not prematurely committing at compile-time to whether contract /// checking is turned on, so that we can specify contracts in libstd /// and let an end user opt into turning them on. #[rustc_const_unstable(feature = "contracts_internals", issue = "128044" /* compiler-team#759 */)] diff --git a/library/core/src/intrinsics/simd.rs b/library/core/src/intrinsics/simd.rs index 11533ab6aa4..19488082cc3 100644 --- a/library/core/src/intrinsics/simd.rs +++ b/library/core/src/intrinsics/simd.rs @@ -160,7 +160,7 @@ pub unsafe fn simd_funnel_shl<T>(a: T, b: T, shift: T) -> T; #[rustc_nounwind] pub unsafe fn simd_funnel_shr<T>(a: T, b: T, shift: T) -> T; -/// "Ands" vectors elementwise. +/// "And"s vectors elementwise. /// /// `T` must be a vector of integers. #[rustc_intrinsic] @@ -522,7 +522,7 @@ pub unsafe fn simd_reduce_max<T, U>(x: T) -> U; #[rustc_nounwind] pub unsafe fn simd_reduce_min<T, U>(x: T) -> U; -/// Logical "ands" all elements together. +/// Logical "and"s all elements together. /// /// `T` must be a vector of integers or floats. /// diff --git a/library/core/src/io/borrowed_buf.rs b/library/core/src/io/borrowed_buf.rs index 6bd9c18e00b..854e03cf182 100644 --- a/library/core/src/io/borrowed_buf.rs +++ b/library/core/src/io/borrowed_buf.rs @@ -281,7 +281,7 @@ impl<'a> BorrowedCursor<'a> { /// Panics if there are less than `n` bytes initialized. #[inline] pub fn advance(&mut self, n: usize) -> &mut Self { - // The substraction cannot underflow by invariant of this type. + // The subtraction cannot underflow by invariant of this type. assert!(n <= self.buf.init - self.buf.filled); self.buf.filled += n; diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 6e160eddecb..2f701171505 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -89,7 +89,7 @@ #![allow(internal_features)] #![deny(ffi_unwind_calls)] #![warn(unreachable_pub)] -// Do not check link redundancy on bootstraping phase +// Do not check link redundancy on bootstrapping phase #![allow(rustdoc::redundant_explicit_links)] #![warn(rustdoc::unescaped_backticks)] // diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 0cc5640941a..67f95a02af3 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -19,6 +19,9 @@ use crate::fmt::Debug; use crate::hash::{Hash, Hasher}; use crate::pin::UnsafePinned; +// NOTE: for consistent error messages between `core` and `minicore`, all `diagnostic` attributes +// should be replicated exactly in `minicore` (if `minicore` defines the item). + /// Implements a given marker trait for multiple types at the same time. /// /// The basic syntax looks like this: diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 63a479ed8dd..fc35e54bb0d 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -616,7 +616,9 @@ impl<T> MaybeUninit<T> { // This also means that `self` must be a `value` variant. unsafe { intrinsics::assert_inhabited::<T>(); - ManuallyDrop::into_inner(self.value) + // We do this via a raw ptr read instead of `ManuallyDrop::into_inner` so that there's + // no trace of `ManuallyDrop` in Miri's error messages here. + (&raw const self.value).cast::<T>().read() } } diff --git a/library/core/src/num/dec2flt/float.rs b/library/core/src/num/dec2flt/float.rs index 5bf0faf0bc9..21aabdc8add 100644 --- a/library/core/src/num/dec2flt/float.rs +++ b/library/core/src/num/dec2flt/float.rs @@ -109,7 +109,7 @@ pub trait RawFloat: /// Round-to-even only happens for negative values of q /// when q ≥ −4 in the 64-bit case and when q ≥ −17 in - /// the 32-bitcase. + /// the 32-bit case. /// /// When q ≥ 0,we have that 5^q ≤ 2m+1. In the 64-bit case,we /// have 5^q ≤ 2m+1 ≤ 2^54 or q ≤ 23. In the 32-bit case,we have @@ -119,7 +119,7 @@ pub trait RawFloat: /// so (2m+1)×5^−q < 2^64. We have that 2m+1 > 2^53 (64-bit case) /// or 2m+1 > 2^24 (32-bit case). Hence,we must have 2^53×5^−q < 2^64 /// (64-bit) and 2^24×5^−q < 2^64 (32-bit). Hence we have 5^−q < 2^11 - /// or q ≥ −4 (64-bit case) and 5^−q < 2^40 or q ≥ −17 (32-bitcase). + /// or q ≥ −4 (64-bit case) and 5^−q < 2^40 or q ≥ −17 (32-bit case). /// /// Thus we have that we only need to round ties to even when /// we have that q ∈ [−4,23](in the 64-bit case) or q∈[−17,10] @@ -143,7 +143,7 @@ pub trait RawFloat: /// smaller than `10^SMALLEST_POWER_OF_TEN`, which will round to zero. /// /// The smallest power of ten is represented by `⌊log10(2^-n / (2^64 - 1))⌋`, where `n` is - /// the smallest power of two. The `2^64 - 1)` denomenator comes from the number of values + /// the smallest power of two. The `2^64 - 1)` denominator comes from the number of values /// that are representable by the intermediate storage format. I don't actually know _why_ /// the storage format is relevant here. /// diff --git a/library/core/src/num/error.rs b/library/core/src/num/error.rs index 6ef2fdd14c1..a5242d60bf1 100644 --- a/library/core/src/num/error.rs +++ b/library/core/src/num/error.rs @@ -79,7 +79,7 @@ pub struct ParseIntError { /// # } /// ``` #[stable(feature = "int_error_matching", since = "1.55.0")] -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash)] #[non_exhaustive] pub enum IntErrorKind { /// Value being parsed is empty. diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 079032f2f96..9cadbd47ab6 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -2572,7 +2572,7 @@ macro_rules! uint_impl { if size_of::<Self>() == 1 { // Trick LLVM into generating the psadbw instruction when SSE2 // is available and this function is autovectorized for u8's. - (self as i32).wrapping_sub(other as i32).abs() as Self + (self as i32).wrapping_sub(other as i32).unsigned_abs() as Self } else { if self < other { other - self diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs index 1935268cda8..ad3b6439a61 100644 --- a/library/core/src/ops/range.rs +++ b/library/core/src/ops/range.rs @@ -1211,7 +1211,7 @@ pub enum OneSidedRangeBound { /// Types that implement `OneSidedRange<T>` must return `Bound::Unbounded` /// from one of `RangeBounds::start_bound` or `RangeBounds::end_bound`. #[unstable(feature = "one_sided_range", issue = "69780")] -pub trait OneSidedRange<T: ?Sized>: RangeBounds<T> { +pub trait OneSidedRange<T>: RangeBounds<T> { /// An internal-only helper function for `split_off` and /// `split_off_mut` that returns the bound of the one-sided range. fn bound(self) -> (OneSidedRangeBound, T); diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index b6d5f848ef0..3ca6feb679b 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -792,7 +792,7 @@ //! //! 1. *Structural [`Unpin`].* A struct can be [`Unpin`] only if all of its //! structurally-pinned fields are, too. This is [`Unpin`]'s behavior by default. -//! However, as a libray author, it is your responsibility not to write something like +//! However, as a library author, it is your responsibility not to write something like //! <code>impl\<T> [Unpin] for Struct\<T> {}</code> and then offer a method that provides //! structural pinning to an inner field of `T`, which may not be [`Unpin`]! (Adding *any* //! projection operation requires unsafe code, so the fact that [`Unpin`] is a safe trait does diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 800eb74babb..27b0c6830db 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -29,7 +29,7 @@ impl<T: PointeeSized> *const T { if const #[rustc_allow_const_fn_unstable(const_raw_ptr_comparison)] { match (ptr).guaranteed_eq(null_mut()) { Some(res) => res, - // To remain maximally convervative, we stop execution when we don't + // To remain maximally conservative, we stop execution when we don't // know whether the pointer is null or not. // We can *not* return `false` here, that would be unsound in `NonNull::new`! None => panic!("null-ness of this pointer cannot be determined in const context"), @@ -49,7 +49,7 @@ impl<T: PointeeSized> *const T { self as _ } - /// Try to cast to a pointer of another type by checking aligment. + /// Try to cast to a pointer of another type by checking alignment. /// /// If the pointer is properly aligned to the target type, it will be /// cast to the target type. Otherwise, `None` is returned. diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 6b436184f20..73efdf04454 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -32,7 +32,7 @@ impl<T: PointeeSized> *mut T { self as _ } - /// Try to cast to a pointer of another type by checking aligment. + /// Try to cast to a pointer of another type by checking alignment. /// /// If the pointer is properly aligned to the target type, it will be /// cast to the target type. Otherwise, `None` is returned. diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index ea650b810b7..c26c3a32ef3 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -497,7 +497,7 @@ impl<T: PointeeSized> NonNull<T> { unsafe { NonNull { pointer: self.as_ptr() as *mut U } } } - /// Try to cast to a pointer of another type by checking aligment. + /// Try to cast to a pointer of another type by checking alignment. /// /// If the pointer is properly aligned to the target type, it will be /// cast to the target type. Otherwise, `None` is returned. diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs index 6327c41f052..9cf08e74ff6 100644 --- a/library/core/src/tuple.rs +++ b/library/core/src/tuple.rs @@ -1,7 +1,7 @@ // See core/src/primitive_docs.rs for documentation. use crate::cmp::Ordering::{self, *}; -use crate::marker::{ConstParamTy_, PointeeSized, StructuralPartialEq, UnsizedConstParamTy}; +use crate::marker::{ConstParamTy_, StructuralPartialEq, UnsizedConstParamTy}; use crate::ops::ControlFlow::{self, Break, Continue}; use crate::random::{Random, RandomSource}; @@ -24,10 +24,7 @@ macro_rules! tuple_impls { maybe_tuple_doc! { $($T)+ @ #[stable(feature = "rust1", since = "1.0.0")] - impl<$($T: PartialEq),+> PartialEq for ($($T,)+) - where - last_type!($($T,)+): PointeeSized - { + impl<$($T: PartialEq),+> PartialEq for ($($T,)+) { #[inline] fn eq(&self, other: &($($T,)+)) -> bool { $( ${ignore($T)} self.${index()} == other.${index()} )&&+ @@ -43,8 +40,6 @@ macro_rules! tuple_impls { $($T)+ @ #[stable(feature = "rust1", since = "1.0.0")] impl<$($T: Eq),+> Eq for ($($T,)+) - where - last_type!($($T,)+): PointeeSized {} } @@ -73,8 +68,6 @@ macro_rules! tuple_impls { $($T)+ @ #[stable(feature = "rust1", since = "1.0.0")] impl<$($T: PartialOrd),+> PartialOrd for ($($T,)+) - where - last_type!($($T,)+): PointeeSized { #[inline] fn partial_cmp(&self, other: &($($T,)+)) -> Option<Ordering> { @@ -119,8 +112,6 @@ macro_rules! tuple_impls { $($T)+ @ #[stable(feature = "rust1", since = "1.0.0")] impl<$($T: Ord),+> Ord for ($($T,)+) - where - last_type!($($T,)+): PointeeSized { #[inline] fn cmp(&self, other: &($($T,)+)) -> Ordering { @@ -245,9 +236,4 @@ macro_rules! lexical_cmp { ($a:expr, $b:expr) => { ($a).cmp(&$b) }; } -macro_rules! last_type { - ($a:ident,) => { $a }; - ($a:ident, $($rest_a:ident,)+) => { last_type!($($rest_a,)+) }; -} - tuple_impls!(E D C B A Z Y X W V U T); diff --git a/library/coretests/tests/bool.rs b/library/coretests/tests/bool.rs index bcd6dc2abac..eb5f0f50663 100644 --- a/library/coretests/tests/bool.rs +++ b/library/coretests/tests/bool.rs @@ -105,3 +105,11 @@ fn test_bool_to_option() { assert_eq!(D, Some(0)); */ } + +#[test] +fn test_bool_to_result() { + assert_eq!(false.ok_or(0), Err(0)); + assert_eq!(true.ok_or(0), Ok(())); + assert_eq!(false.ok_or_else(|| 0), Err(0)); + assert_eq!(true.ok_or_else(|| 0), Ok(())); +} diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 0c54609260f..fdef736c0c0 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -11,6 +11,7 @@ #![feature(async_iter_from_iter)] #![feature(async_iterator)] #![feature(bigint_helper_methods)] +#![feature(bool_to_result)] #![feature(bstr)] #![feature(cfg_target_has_reliable_f16_f128)] #![feature(char_max_len)] diff --git a/library/coretests/tests/num/dec2flt/float.rs b/library/coretests/tests/num/dec2flt/float.rs index 2407ba50ca3..193d5887749 100644 --- a/library/coretests/tests/num/dec2flt/float.rs +++ b/library/coretests/tests/num/dec2flt/float.rs @@ -23,7 +23,7 @@ fn test_f16_integer_decode() { fn test_f32_integer_decode() { assert_eq!(3.14159265359f32.integer_decode(), (13176795, -22, 1)); assert_eq!((-8573.5918555f32).integer_decode(), (8779358, -10, -1)); - // Set 2^100 directly instead of using powf, because it doesn't guarentee precision + // Set 2^100 directly instead of using powf, because it doesn't guarantee precision assert_eq!(1.2676506e30_f32.integer_decode(), (8388608, 77, 1)); assert_eq!(0f32.integer_decode(), (0, -150, 1)); assert_eq!((-0f32).integer_decode(), (0, -150, -1)); @@ -40,7 +40,7 @@ fn test_f32_integer_decode() { fn test_f64_integer_decode() { assert_eq!(3.14159265359f64.integer_decode(), (7074237752028906, -51, 1)); assert_eq!((-8573.5918555f64).integer_decode(), (4713381968463931, -39, -1)); - // Set 2^100 directly instead of using powf, because it doesn't guarentee precision + // Set 2^100 directly instead of using powf, because it doesn't guarantee precision assert_eq!(1.2676506002282294e30_f64.integer_decode(), (4503599627370496, 48, 1)); assert_eq!(0f64.integer_decode(), (0, -1075, 1)); assert_eq!((-0f64).integer_decode(), (0, -1075, -1)); diff --git a/library/rustc-std-workspace-core/Cargo.toml b/library/rustc-std-workspace-core/Cargo.toml index bd318fc2f9e..1ddc112380f 100644 --- a/library/rustc-std-workspace-core/Cargo.toml +++ b/library/rustc-std-workspace-core/Cargo.toml @@ -1,3 +1,5 @@ +cargo-features = ["public-dependency"] + [package] name = "rustc-std-workspace-core" version = "1.99.0" @@ -11,5 +13,7 @@ edition = "2024" path = "lib.rs" [dependencies] -core = { path = "../core" } -compiler_builtins = { path = "../compiler-builtins/compiler-builtins", features = ["compiler-builtins"] } +core = { path = "../core", public = true } +compiler_builtins = { path = "../compiler-builtins/compiler-builtins", features = [ + "compiler-builtins", +] } diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index d9902d41928..72ad7c244ee 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -4,6 +4,27 @@ //! filesystem. All methods in this module represent cross-platform filesystem //! operations. Extra platform-specific functionality can be found in the //! extension traits of `std::os::$platform`. +//! +//! # Time of Check to Time of Use (TOCTOU) +//! +//! Many filesystem operations are subject to a race condition known as "Time of Check to Time of Use" +//! (TOCTOU). This occurs when a program checks a condition (like file existence or permissions) +//! and then uses the result of that check to make a decision, but the condition may have changed +//! between the check and the use. +//! +//! For example, checking if a file exists and then creating it if it doesn't is vulnerable to +//! TOCTOU - another process could create the file between your check and creation attempt. +//! +//! Another example is with symbolic links: when removing a directory, if another process replaces +//! the directory with a symbolic link between the check and the removal operation, the removal +//! might affect the wrong location. This is why operations like [`remove_dir_all`] need to use +//! atomic operations to prevent such race conditions. +//! +//! To avoid TOCTOU issues: +//! - Be aware that metadata operations (like [`metadata`] or [`symlink_metadata`]) may be affected by +//! changes made by other processes. +//! - Use atomic operations when possible (like [`File::create_new`] instead of checking existence then creating). +//! - Keep file open for the duration of operations. #![stable(feature = "rust1", since = "1.0.0")] #![deny(unsafe_op_in_unsafe_fn)] @@ -548,13 +569,14 @@ impl File { /// non-exhaustive list of likely errors. /// /// This option is useful because it is atomic. Otherwise between checking whether a file - /// exists and creating a new one, the file may have been created by another process (a TOCTOU + /// exists and creating a new one, the file may have been created by another process (a [TOCTOU] /// race condition / attack). /// /// This can also be written using /// `File::options().read(true).write(true).create_new(true).open(...)`. /// /// [`AlreadyExists`]: crate::io::ErrorKind::AlreadyExists + /// [TOCTOU]: self#time-of-check-to-time-of-use-toctou /// /// # Examples /// @@ -1610,7 +1632,7 @@ impl OpenOptions { /// /// This option is useful because it is atomic. Otherwise between checking /// whether a file exists and creating a new one, the file may have been - /// created by another process (a TOCTOU race condition / attack). + /// created by another process (a [TOCTOU] race condition / attack). /// /// If `.create_new(true)` is set, [`.create()`] and [`.truncate()`] are /// ignored. @@ -1621,6 +1643,7 @@ impl OpenOptions { /// [`.create()`]: OpenOptions::create /// [`.truncate()`]: OpenOptions::truncate /// [`AlreadyExists`]: io::ErrorKind::AlreadyExists + /// [TOCTOU]: self#time-of-check-to-time-of-use-toctou /// /// # Examples /// @@ -2954,17 +2977,17 @@ pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> { /// `GetFileInformationByHandleEx`, `SetFileInformationByHandle`, and `NtCreateFile`. /// /// ## Time-of-check to time-of-use (TOCTOU) race conditions -/// On a few platforms there is no way to remove a directory's contents without following symlinks -/// unless you perform a check and then operate on paths based on that directory. -/// This allows concurrently-running code to replace the directory with a symlink after the check, -/// causing a removal to instead operate on a path based on the symlink. This is a TOCTOU race. -/// By default, `fs::remove_dir_all` protects against a symlink TOCTOU race on all platforms -/// except the following. It should not be used in security-sensitive contexts on these platforms: -/// - Miri: Even when emulating targets where the underlying implementation will protect against -/// TOCTOU races, Miri will not do so. -/// - Redox OS: This function does not protect against TOCTOU races, as Redox does not implement -/// the required platform support to do so. +/// See the [module-level TOCTOU explanation](self#time-of-check-to-time-of-use-toctou). +/// +/// On most platforms, `fs::remove_dir_all` protects against symlink TOCTOU races by default. +/// However, on the following platforms, this protection is not provided and the function should +/// not be used in security-sensitive contexts: +/// - **Miri**: Even when emulating targets where the underlying implementation will protect against +/// TOCTOU races, Miri will not do so. +/// - **Redox OS**: This function does not protect against TOCTOU races, as Redox does not implement +/// the required platform support to do so. /// +/// [TOCTOU]: self#time-of-check-to-time-of-use-toctou /// [changes]: io#platform-specific-behavior /// /// # Errors @@ -3091,7 +3114,7 @@ pub fn read_dir<P: AsRef<Path>>(path: P) -> io::Result<ReadDir> { /// On UNIX-like systems, this function will update the permission bits /// of the file pointed to by the symlink. /// -/// Note that this behavior can lead to privalage escalation vulnerabilites, +/// Note that this behavior can lead to privalage escalation vulnerabilities, /// where the ability to create a symlink in one directory allows you to /// cause the permissions of another file or directory to be modified. /// @@ -3238,7 +3261,7 @@ impl AsInnerMut<fs_imp::DirBuilder> for DirBuilder { /// permission is denied on one of the parent directories. /// /// Note that while this avoids some pitfalls of the `exists()` method, it still can not -/// prevent time-of-check to time-of-use (TOCTOU) bugs. You should only use it in scenarios +/// prevent time-of-check to time-of-use ([TOCTOU]) bugs. You should only use it in scenarios /// where those bugs are not an issue. /// /// # Examples @@ -3251,6 +3274,7 @@ impl AsInnerMut<fs_imp::DirBuilder> for DirBuilder { /// ``` /// /// [`Path::exists`]: crate::path::Path::exists +/// [TOCTOU]: self#time-of-check-to-time-of-use-toctou #[stable(feature = "fs_try_exists", since = "1.81.0")] #[inline] pub fn exists<P: AsRef<Path>>(path: P) -> io::Result<bool> { diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs index 3f4fe2e56ec..466b134d8fa 100644 --- a/library/std/src/os/unix/process.rs +++ b/library/std/src/os/unix/process.rs @@ -385,7 +385,7 @@ pub trait ChildExt: Sealed { /// # Errors /// /// This function will return an error if the signal is invalid. The integer values associated - /// with signals are implemenation-specific, so it's encouraged to use a crate that provides + /// with signals are implementation-specific, so it's encouraged to use a crate that provides /// posix bindings. /// /// # Examples diff --git a/library/std/src/path.rs b/library/std/src/path.rs index b734d2b324c..0ce20a143df 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -3127,7 +3127,7 @@ impl Path { /// Returns `true` if the path points at an existing entity. /// /// Warning: this method may be error-prone, consider using [`try_exists()`] instead! - /// It also has a risk of introducing time-of-check to time-of-use (TOCTOU) bugs. + /// It also has a risk of introducing time-of-check to time-of-use ([TOCTOU]) bugs. /// /// This function will traverse symbolic links to query information about the /// destination file. @@ -3148,6 +3148,7 @@ impl Path { /// check errors, call [`Path::try_exists`]. /// /// [`try_exists()`]: Self::try_exists + /// [TOCTOU]: fs#time-of-check-to-time-of-use-toctou #[stable(feature = "path_ext", since = "1.5.0")] #[must_use] #[inline] @@ -3167,7 +3168,7 @@ impl Path { /// permission is denied on one of the parent directories. /// /// Note that while this avoids some pitfalls of the `exists()` method, it still can not - /// prevent time-of-check to time-of-use (TOCTOU) bugs. You should only use it in scenarios + /// prevent time-of-check to time-of-use ([TOCTOU]) bugs. You should only use it in scenarios /// where those bugs are not an issue. /// /// This is an alias for [`std::fs::exists`](crate::fs::exists). @@ -3180,6 +3181,7 @@ impl Path { /// assert!(Path::new("/root/secret_file.txt").try_exists().is_err()); /// ``` /// + /// [TOCTOU]: fs#time-of-check-to-time-of-use-toctou /// [`exists()`]: Self::exists #[stable(feature = "path_try_exists", since = "1.63.0")] #[inline] diff --git a/library/std/src/sys/net/connection/socket/wasip2.rs b/library/std/src/sys/net/connection/socket/wasip2.rs index 73c25831872..c77c50fece1 100644 --- a/library/std/src/sys/net/connection/socket/wasip2.rs +++ b/library/std/src/sys/net/connection/socket/wasip2.rs @@ -140,7 +140,7 @@ impl Socket { 0 => {} _ => { // WASI poll does not return POLLHUP or POLLERR in revents. Check if the - // connnection actually succeeded and return ok only when the socket is + // connection actually succeeded and return ok only when the socket is // ready and no errors were found. if let Some(e) = self.take_error()? { return Err(e); diff --git a/library/std/src/sys/pal/uefi/helpers.rs b/library/std/src/sys/pal/uefi/helpers.rs index e47263348db..420481648a7 100644 --- a/library/std/src/sys/pal/uefi/helpers.rs +++ b/library/std/src/sys/pal/uefi/helpers.rs @@ -487,7 +487,7 @@ impl<T> OwnedProtocol<T> { let protocol: *mut T = Box::into_raw(Box::new(protocol)); let mut handle: r_efi::efi::Handle = crate::ptr::null_mut(); - // FIXME: Move into r-efi once extended_varargs_abi_support is stablized + // FIXME: Move into r-efi once extended_varargs_abi_support is stabilized let func: BootInstallMultipleProtocolInterfaces = unsafe { crate::mem::transmute((*bt.as_ptr()).install_multiple_protocol_interfaces) }; @@ -521,7 +521,7 @@ impl<T> Drop for OwnedProtocol<T> { // Do not deallocate a runtime protocol if let Some(bt) = boot_services() { let bt: NonNull<r_efi::efi::BootServices> = bt.cast(); - // FIXME: Move into r-efi once extended_varargs_abi_support is stablized + // FIXME: Move into r-efi once extended_varargs_abi_support is stabilized let func: BootUninstallMultipleProtocolInterfaces = unsafe { crate::mem::transmute((*bt.as_ptr()).uninstall_multiple_protocol_interfaces) }; @@ -645,7 +645,7 @@ pub(crate) fn get_device_path_from_map(map: &Path) -> io::Result<BorrowedDeviceP } /// Helper for UEFI Protocols which are created and destroyed using -/// [EFI_SERVICE_BINDING_PROTCOL](https://uefi.org/specs/UEFI/2.11/11_Protocols_UEFI_Driver_Model.html#efi-service-binding-protocol) +/// [EFI_SERVICE_BINDING_PROTOCOL](https://uefi.org/specs/UEFI/2.11/11_Protocols_UEFI_Driver_Model.html#efi-service-binding-protocol) pub(crate) struct ServiceProtocol { service_guid: r_efi::efi::Guid, handle: NonNull<crate::ffi::c_void>, diff --git a/library/std/src/sys/path/cygwin.rs b/library/std/src/sys/path/cygwin.rs index e90372805bb..da0982384b0 100644 --- a/library/std/src/sys/path/cygwin.rs +++ b/library/std/src/sys/path/cygwin.rs @@ -10,7 +10,7 @@ pub fn is_sep_byte(b: u8) -> bool { b == b'/' || b == b'\\' } -/// Cygwin allways prefers `/` over `\`, and it always converts all `/` to `\` +/// Cygwin always prefers `/` over `\`, and it always converts all `/` to `\` /// internally when calling Win32 APIs. Therefore, the server component of path /// `\\?\UNC\localhost/share` is `localhost/share` on Win32, but `localhost` /// on Cygwin. diff --git a/library/std/src/sys/random/linux.rs b/library/std/src/sys/random/linux.rs index 18196fae28b..53e2f1da675 100644 --- a/library/std/src/sys/random/linux.rs +++ b/library/std/src/sys/random/linux.rs @@ -15,7 +15,7 @@ //! bytes, while the non-blocking pool, once initialized using the blocking //! pool, uses a CPRNG to return an unlimited number of random bytes. With a //! strong enough CPRNG however, the entropy estimation didn't contribute that -//! much towards security while being an excellent vector for DoS attacs. Thus, +//! much towards security while being an excellent vector for DoS attacks. Thus, //! the blocking pool was removed in kernel version 5.6.[^2] That patch did not //! magically increase the quality of the non-blocking pool, however, so we can //! safely consider it strong enough even in older kernel versions and use it @@ -30,7 +30,7 @@ //! data the system has available at the time. //! //! So in conclusion, we always want the output of the non-blocking pool, but -//! may need to wait until it is initalized. The default behavior of `getrandom` +//! may need to wait until it is initialized. The default behavior of `getrandom` //! is to wait until the non-blocking pool is initialized and then draw from there, //! so if `getrandom` is available, we use its default to generate the bytes. For //! `HashMap`, however, we need to specify the `GRND_INSECURE` flags, but that diff --git a/library/std/src/sys/random/unsupported.rs b/library/std/src/sys/random/unsupported.rs index d68ce4a9e87..894409b395a 100644 --- a/library/std/src/sys/random/unsupported.rs +++ b/library/std/src/sys/random/unsupported.rs @@ -6,7 +6,7 @@ pub fn fill_bytes(_: &mut [u8]) { pub fn hashmap_random_keys() -> (u64, u64) { // Use allocation addresses for a bit of randomness. This isn't - // particularily secure, but there isn't really an alternative. + // particularly secure, but there isn't really an alternative. let stack = 0u8; let heap = Box::new(0u8); let k1 = ptr::from_ref(&stack).addr() as u64; diff --git a/library/std/src/thread/spawnhook.rs b/library/std/src/thread/spawnhook.rs index 98f471ad54b..c8a7bcf55c1 100644 --- a/library/std/src/thread/spawnhook.rs +++ b/library/std/src/thread/spawnhook.rs @@ -6,7 +6,7 @@ use crate::thread::Thread; crate::thread_local! { /// A thread local linked list of spawn hooks. /// - /// It is a linked list of Arcs, such that it can very cheaply be inhereted by spawned threads. + /// It is a linked list of Arcs, such that it can very cheaply be inherited by spawned threads. /// /// (That technically makes it a set of linked lists with shared tails, so a linked tree.) static SPAWN_HOOKS: Cell<SpawnHooks> = const { Cell::new(SpawnHooks { first: None }) }; diff --git a/library/std/src/time.rs b/library/std/src/time.rs index 03af35e809c..393426be087 100644 --- a/library/std/src/time.rs +++ b/library/std/src/time.rs @@ -95,10 +95,10 @@ use crate::sys_common::{FromInner, IntoInner}; /// let now = Instant::now(); /// let days_per_10_millennia = 365_2425; /// let solar_seconds_per_day = 60 * 60 * 24; -/// let millenium_in_solar_seconds = 31_556_952_000; -/// assert_eq!(millenium_in_solar_seconds, days_per_10_millennia * solar_seconds_per_day / 10); +/// let millennium_in_solar_seconds = 31_556_952_000; +/// assert_eq!(millennium_in_solar_seconds, days_per_10_millennia * solar_seconds_per_day / 10); /// -/// let duration = Duration::new(millenium_in_solar_seconds, 0); +/// let duration = Duration::new(millennium_in_solar_seconds, 0); /// println!("{:?}", now + duration); /// ``` /// diff --git a/library/std/tests/thread_local/tests.rs b/library/std/tests/thread_local/tests.rs index e8278361d93..5df1a0e25ee 100644 --- a/library/std/tests/thread_local/tests.rs +++ b/library/std/tests/thread_local/tests.rs @@ -348,7 +348,7 @@ fn join_orders_after_tls_destructors() { // // The test won't currently work without target_thread_local, aka with slow tls. // The runtime tries very hard to drop last the TLS variable that keeps the information about the -// current thread, by using several tricks like deffering the drop to a later round of TLS destruction. +// current thread, by using several tricks like deferring the drop to a later round of TLS destruction. // However, this only seems to work with fast tls. // // With slow TLS, it seems that multiple libc implementations will just set the value to null the first diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs index 567416d079b..6c5f70b2f43 100644 --- a/src/bootstrap/src/core/build_steps/check.rs +++ b/src/bootstrap/src/core/build_steps/check.rs @@ -5,7 +5,7 @@ use crate::core::build_steps::compile::{ }; use crate::core::build_steps::tool::{COMPILETEST_ALLOW_FEATURES, SourceType, prepare_tool_cargo}; use crate::core::builder::{ - self, Alias, Builder, Kind, RunConfig, ShouldRun, Step, crate_description, + self, Alias, Builder, Kind, RunConfig, ShouldRun, Step, StepMetadata, crate_description, }; use crate::core::config::TargetSelection; use crate::utils::build_stamp::{self, BuildStamp}; @@ -167,6 +167,10 @@ impl Step for Std { let _guard = builder.msg_check("library test/bench/example targets", target, Some(stage)); run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false); } + + fn metadata(&self) -> Option<StepMetadata> { + Some(StepMetadata::check("std", self.target)) + } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -258,6 +262,10 @@ impl Step for Rustc { let hostdir = builder.sysroot_target_libdir(compiler, compiler.host); add_to_sysroot(builder, &libdir, &hostdir, &stamp); } + + fn metadata(&self) -> Option<StepMetadata> { + Some(StepMetadata::check("rustc", self.target)) + } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -315,6 +323,10 @@ impl Step for CodegenBackend { run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false); } + + fn metadata(&self) -> Option<StepMetadata> { + Some(StepMetadata::check(self.backend, self.target)) + } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -373,6 +385,10 @@ impl Step for RustAnalyzer { let _guard = builder.msg_check("rust-analyzer artifacts", target, None); run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false); } + + fn metadata(&self) -> Option<StepMetadata> { + Some(StepMetadata::check("rust-analyzer", self.target)) + } } /// Compiletest is implicitly "checked" when it gets built in order to run tests, @@ -432,6 +448,10 @@ impl Step for Compiletest { let _guard = builder.msg_check("compiletest artifacts", self.target, None); run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false); } + + fn metadata(&self) -> Option<StepMetadata> { + Some(StepMetadata::check("compiletest", self.target)) + } } macro_rules! tool_check_step { @@ -467,6 +487,10 @@ macro_rules! tool_check_step { let Self { target } = self; run_tool_check_step(builder, target, stringify!($name), $path); } + + fn metadata(&self) -> Option<StepMetadata> { + Some(StepMetadata::check(stringify!($name), self.target)) + } } } } diff --git a/src/bootstrap/src/core/build_steps/clean.rs b/src/bootstrap/src/core/build_steps/clean.rs index 882fcd08780..f67569d1486 100644 --- a/src/bootstrap/src/core/build_steps/clean.rs +++ b/src/bootstrap/src/core/build_steps/clean.rs @@ -181,7 +181,7 @@ fn rm_rf(path: &Path) { panic!("failed to get metadata for file {}: {}", path.display(), e); } Ok(metadata) => { - if metadata.file_type().is_file() || metadata.file_type().is_symlink() { + if !metadata.file_type().is_dir() { do_op(path, "remove file", |p| match fs::remove_file(p) { #[cfg(windows)] Err(e) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 84064150738..c3a3eddd161 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -306,11 +306,7 @@ impl Step for Std { } fn metadata(&self) -> Option<StepMetadata> { - Some( - StepMetadata::build("std", self.target) - .built_by(self.compiler) - .stage(self.compiler.stage), - ) + Some(StepMetadata::build("std", self.target).built_by(self.compiler)) } } @@ -1186,11 +1182,7 @@ impl Step for Rustc { } fn metadata(&self) -> Option<StepMetadata> { - Some( - StepMetadata::build("rustc", self.target) - .built_by(self.build_compiler) - .stage(self.build_compiler.stage + 1), - ) + Some(StepMetadata::build("rustc", self.target).built_by(self.build_compiler)) } } diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index 61268df7336..d487995e98a 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -346,6 +346,6 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) { // since last merge. // // NOTE: Because of the exit above, this is only reachable if formatting / format checking - // succeeded. So we are not commiting the version if formatting was not good. + // succeeded. So we are not committing the version if formatting was not good. update_rustfmt_version(build); } diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 01b181f55de..2d4d9e53598 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1108,7 +1108,9 @@ impl Step for Tidy { if builder.config.cmd.bless() { cmd.arg("--bless"); } - if let Some(s) = builder.config.cmd.extra_checks() { + if let Some(s) = + builder.config.cmd.extra_checks().or(builder.config.tidy_extra_checks.as_deref()) + { cmd.arg(format!("--extra-checks={s}")); } let mut args = std::env::args_os(); diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index a7220515ca0..ad3f8d89767 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -1195,7 +1195,6 @@ macro_rules! tool_extended { Some( StepMetadata::build($tool_name, self.target) .built_by(self.compiler.with_stage(self.compiler.stage.saturating_sub(1))) - .stage(self.compiler.stage) ) } } diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index 8e9e8b496de..b96a988cde3 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -153,6 +153,10 @@ impl StepMetadata { Self::new(name, target, Kind::Build) } + pub fn check(name: &'static str, target: TargetSelection) -> Self { + Self::new(name, target, Kind::Check) + } + pub fn doc(name: &'static str, target: TargetSelection) -> Self { Self::new(name, target, Kind::Doc) } @@ -178,6 +182,14 @@ impl StepMetadata { self.stage = Some(stage); self } + + pub fn get_stage(&self) -> Option<u32> { + self.stage.or(self + .built_by + // For std, its stage corresponds to the stage of the compiler that builds it. + // For everything else, a stage N things gets built by a stage N-1 compiler. + .map(|compiler| if self.name == "std" { compiler.stage } else { compiler.stage + 1 })) + } } pub struct RunConfig<'a> { diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 8adf93ea528..1c5267cb75e 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -863,7 +863,7 @@ mod snapshot { insta::assert_snapshot!( ctx.config("build") .path("opt-dist") - .render_steps(), @"[build] rustc 0 <host> -> OptimizedDist <host>"); + .render_steps(), @"[build] rustc 0 <host> -> OptimizedDist 1 <host>"); } #[test] @@ -880,7 +880,7 @@ mod snapshot { ctx.config("build") .path("opt-dist") .stage(1) - .render_steps(), @"[build] rustc 0 <host> -> OptimizedDist <host>"); + .render_steps(), @"[build] rustc 0 <host> -> OptimizedDist 1 <host>"); } #[test] @@ -890,7 +890,7 @@ mod snapshot { ctx.config("build") .path("opt-dist") .stage(2) - .render_steps(), @"[build] rustc 0 <host> -> OptimizedDist <host>"); + .render_steps(), @"[build] rustc 0 <host> -> OptimizedDist 1 <host>"); } #[test] @@ -984,8 +984,8 @@ mod snapshot { ctx .config("dist") .render_steps(), @r" - [build] rustc 0 <host> -> UnstableBookGen <host> - [build] rustc 0 <host> -> Rustbook <host> + [build] rustc 0 <host> -> UnstableBookGen 1 <host> + [build] rustc 0 <host> -> Rustbook 1 <host> [build] llvm <host> [build] rustc 0 <host> -> rustc 1 <host> [build] rustc 1 <host> -> std 1 <host> @@ -993,14 +993,14 @@ mod snapshot { [build] rustdoc 1 <host> [doc] std 2 <host> [build] rustc 2 <host> -> std 2 <host> - [build] rustc 0 <host> -> LintDocs <host> - [build] rustc 0 <host> -> RustInstaller <host> + [build] rustc 0 <host> -> LintDocs 1 <host> + [build] rustc 0 <host> -> RustInstaller 1 <host> [dist] docs <host> [doc] std 2 <host> [dist] mingw <host> - [build] rustc 0 <host> -> GenerateCopyright <host> + [build] rustc 0 <host> -> GenerateCopyright 1 <host> [dist] rustc <host> - [dist] rustc 1 <host> -> std <host> + [dist] rustc 1 <host> -> std 1 <host> [dist] src <> " ); @@ -1014,25 +1014,25 @@ mod snapshot { .config("dist") .args(&["--set", "build.extended=true"]) .render_steps(), @r" - [build] rustc 0 <host> -> UnstableBookGen <host> - [build] rustc 0 <host> -> Rustbook <host> + [build] rustc 0 <host> -> UnstableBookGen 1 <host> + [build] rustc 0 <host> -> Rustbook 1 <host> [build] llvm <host> [build] rustc 0 <host> -> rustc 1 <host> - [build] rustc 0 <host> -> WasmComponentLd <host> + [build] rustc 0 <host> -> WasmComponentLd 1 <host> [build] rustc 1 <host> -> std 1 <host> [build] rustc 1 <host> -> rustc 2 <host> - [build] rustc 1 <host> -> WasmComponentLd <host> + [build] rustc 1 <host> -> WasmComponentLd 2 <host> [build] rustdoc 1 <host> [doc] std 2 <host> [build] rustc 2 <host> -> std 2 <host> - [build] rustc 0 <host> -> LintDocs <host> - [build] rustc 0 <host> -> RustInstaller <host> + [build] rustc 0 <host> -> LintDocs 1 <host> + [build] rustc 0 <host> -> RustInstaller 1 <host> [dist] docs <host> [doc] std 2 <host> [dist] mingw <host> - [build] rustc 0 <host> -> GenerateCopyright <host> + [build] rustc 0 <host> -> GenerateCopyright 1 <host> [dist] rustc <host> - [dist] rustc 1 <host> -> std <host> + [dist] rustc 1 <host> -> std 1 <host> [dist] src <> [build] rustc 0 <host> -> rustfmt 1 <host> [build] rustc 0 <host> -> cargo-fmt 1 <host> @@ -1052,8 +1052,8 @@ mod snapshot { .hosts(&[&host_target()]) .targets(&[&host_target(), TEST_TRIPLE_1]) .render_steps(), @r" - [build] rustc 0 <host> -> UnstableBookGen <host> - [build] rustc 0 <host> -> Rustbook <host> + [build] rustc 0 <host> -> UnstableBookGen 1 <host> + [build] rustc 0 <host> -> Rustbook 1 <host> [build] llvm <host> [build] rustc 0 <host> -> rustc 1 <host> [build] rustc 1 <host> -> std 1 <host> @@ -1062,19 +1062,19 @@ mod snapshot { [doc] std 2 <host> [doc] std 2 <target1> [build] rustc 2 <host> -> std 2 <host> - [build] rustc 0 <host> -> LintDocs <host> - [build] rustc 0 <host> -> RustInstaller <host> + [build] rustc 0 <host> -> LintDocs 1 <host> + [build] rustc 0 <host> -> RustInstaller 1 <host> [dist] docs <host> [dist] docs <target1> [doc] std 2 <host> [doc] std 2 <target1> [dist] mingw <host> [dist] mingw <target1> - [build] rustc 0 <host> -> GenerateCopyright <host> + [build] rustc 0 <host> -> GenerateCopyright 1 <host> [dist] rustc <host> - [dist] rustc 1 <host> -> std <host> + [dist] rustc 1 <host> -> std 1 <host> [build] rustc 2 <host> -> std 2 <target1> - [dist] rustc 2 <host> -> std <target1> + [dist] rustc 2 <host> -> std 2 <target1> [dist] src <> " ); @@ -1089,8 +1089,8 @@ mod snapshot { .hosts(&[&host_target(), TEST_TRIPLE_1]) .targets(&[&host_target()]) .render_steps(), @r" - [build] rustc 0 <host> -> UnstableBookGen <host> - [build] rustc 0 <host> -> Rustbook <host> + [build] rustc 0 <host> -> UnstableBookGen 1 <host> + [build] rustc 0 <host> -> Rustbook 1 <host> [build] llvm <host> [build] rustc 0 <host> -> rustc 1 <host> [build] rustc 1 <host> -> std 1 <host> @@ -1098,20 +1098,20 @@ mod snapshot { [build] rustdoc 1 <host> [doc] std 2 <host> [build] rustc 2 <host> -> std 2 <host> - [build] rustc 0 <host> -> LintDocs <host> + [build] rustc 0 <host> -> LintDocs 1 <host> [build] rustc 1 <host> -> std 1 <target1> [build] rustc 2 <host> -> std 2 <target1> - [build] rustc 0 <host> -> RustInstaller <host> + [build] rustc 0 <host> -> RustInstaller 1 <host> [dist] docs <host> [doc] std 2 <host> [dist] mingw <host> - [build] rustc 0 <host> -> GenerateCopyright <host> + [build] rustc 0 <host> -> GenerateCopyright 1 <host> [dist] rustc <host> [build] llvm <target1> [build] rustc 1 <host> -> rustc 2 <target1> [build] rustdoc 1 <target1> [dist] rustc <target1> - [dist] rustc 1 <host> -> std <host> + [dist] rustc 1 <host> -> std 1 <host> [dist] src <> " ); @@ -1126,8 +1126,8 @@ mod snapshot { .hosts(&[&host_target(), TEST_TRIPLE_1]) .targets(&[&host_target(), TEST_TRIPLE_1]) .render_steps(), @r" - [build] rustc 0 <host> -> UnstableBookGen <host> - [build] rustc 0 <host> -> Rustbook <host> + [build] rustc 0 <host> -> UnstableBookGen 1 <host> + [build] rustc 0 <host> -> Rustbook 1 <host> [build] llvm <host> [build] rustc 0 <host> -> rustc 1 <host> [build] rustc 1 <host> -> std 1 <host> @@ -1136,24 +1136,24 @@ mod snapshot { [doc] std 2 <host> [doc] std 2 <target1> [build] rustc 2 <host> -> std 2 <host> - [build] rustc 0 <host> -> LintDocs <host> + [build] rustc 0 <host> -> LintDocs 1 <host> [build] rustc 1 <host> -> std 1 <target1> [build] rustc 2 <host> -> std 2 <target1> - [build] rustc 0 <host> -> RustInstaller <host> + [build] rustc 0 <host> -> RustInstaller 1 <host> [dist] docs <host> [dist] docs <target1> [doc] std 2 <host> [doc] std 2 <target1> [dist] mingw <host> [dist] mingw <target1> - [build] rustc 0 <host> -> GenerateCopyright <host> + [build] rustc 0 <host> -> GenerateCopyright 1 <host> [dist] rustc <host> [build] llvm <target1> [build] rustc 1 <host> -> rustc 2 <target1> [build] rustdoc 1 <target1> [dist] rustc <target1> - [dist] rustc 1 <host> -> std <host> - [dist] rustc 1 <host> -> std <target1> + [dist] rustc 1 <host> -> std 1 <host> + [dist] rustc 1 <host> -> std 1 <target1> [dist] src <> " ); @@ -1168,8 +1168,8 @@ mod snapshot { .hosts(&[]) .targets(&[TEST_TRIPLE_1]) .render_steps(), @r" - [build] rustc 0 <host> -> UnstableBookGen <host> - [build] rustc 0 <host> -> Rustbook <host> + [build] rustc 0 <host> -> UnstableBookGen 1 <host> + [build] rustc 0 <host> -> Rustbook 1 <host> [build] llvm <host> [build] rustc 0 <host> -> rustc 1 <host> [build] rustc 1 <host> -> std 1 <host> @@ -1177,12 +1177,12 @@ mod snapshot { [build] rustdoc 1 <host> [doc] std 2 <target1> [build] rustc 2 <host> -> std 2 <host> - [build] rustc 0 <host> -> RustInstaller <host> + [build] rustc 0 <host> -> RustInstaller 1 <host> [dist] docs <target1> [doc] std 2 <target1> [dist] mingw <target1> [build] rustc 2 <host> -> std 2 <target1> - [dist] rustc 2 <host> -> std <target1> + [dist] rustc 2 <host> -> std 2 <target1> "); } @@ -1198,31 +1198,31 @@ mod snapshot { .targets(&[TEST_TRIPLE_1]) .args(&["--set", "rust.channel=nightly", "--set", "build.extended=true"]) .render_steps(), @r" - [build] rustc 0 <host> -> UnstableBookGen <host> - [build] rustc 0 <host> -> Rustbook <host> + [build] rustc 0 <host> -> UnstableBookGen 1 <host> + [build] rustc 0 <host> -> Rustbook 1 <host> [build] llvm <host> [build] rustc 0 <host> -> rustc 1 <host> - [build] rustc 0 <host> -> WasmComponentLd <host> + [build] rustc 0 <host> -> WasmComponentLd 1 <host> [build] rustc 1 <host> -> std 1 <host> [build] rustc 1 <host> -> rustc 2 <host> - [build] rustc 1 <host> -> WasmComponentLd <host> + [build] rustc 1 <host> -> WasmComponentLd 2 <host> [build] rustdoc 1 <host> [doc] std 2 <target1> [build] rustc 2 <host> -> std 2 <host> [build] rustc 1 <host> -> std 1 <target1> [build] rustc 2 <host> -> std 2 <target1> - [build] rustc 0 <host> -> LintDocs <host> - [build] rustc 0 <host> -> RustInstaller <host> + [build] rustc 0 <host> -> LintDocs 1 <host> + [build] rustc 0 <host> -> RustInstaller 1 <host> [dist] docs <target1> [doc] std 2 <target1> [dist] mingw <target1> [build] llvm <target1> [build] rustc 1 <host> -> rustc 2 <target1> - [build] rustc 1 <host> -> WasmComponentLd <target1> + [build] rustc 1 <host> -> WasmComponentLd 2 <target1> [build] rustdoc 1 <target1> - [build] rustc 0 <host> -> GenerateCopyright <host> + [build] rustc 0 <host> -> GenerateCopyright 1 <host> [dist] rustc <target1> - [dist] rustc 1 <host> -> std <target1> + [dist] rustc 1 <host> -> std 1 <target1> [dist] src <> [build] rustc 0 <host> -> rustfmt 1 <target1> [build] rustc 0 <host> -> cargo-fmt 1 <target1> @@ -1234,6 +1234,289 @@ mod snapshot { } #[test] + fn check_compiler_no_explicit_stage() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("check") + .path("compiler") + .render_steps(), @r" + [check] std <host> + [build] llvm <host> + [check] rustc <host> + [check] cranelift <host> + [check] gcc <host> + "); + + insta::assert_snapshot!( + ctx.config("check") + .path("rustc") + .render_steps(), @r" + [check] std <host> + [build] llvm <host> + [check] rustc <host> + "); + } + + #[test] + fn check_compiler_stage_0() { + let ctx = TestCtx::new(); + ctx.config("check").path("compiler").stage(0).run(); + } + + #[test] + fn check_compiler_stage_1() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("check") + .path("compiler") + .stage(1) + .render_steps(), @r" + [build] llvm <host> + [build] rustc 0 <host> -> rustc 1 <host> + [build] rustc 1 <host> -> std 1 <host> + [check] rustc <host> + [check] cranelift <host> + [check] gcc <host> + "); + } + + #[test] + fn check_compiler_stage_2() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("check") + .path("compiler") + .stage(2) + .render_steps(), @r" + [build] llvm <host> + [build] rustc 0 <host> -> rustc 1 <host> + [build] rustc 1 <host> -> std 1 <host> + [build] rustc 1 <host> -> rustc 2 <host> + [build] rustc 2 <host> -> std 2 <host> + [check] rustc <host> + [check] cranelift <host> + [check] gcc <host> + "); + } + + #[test] + fn check_cross_compile() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("check") + .stage(2) + .targets(&[TEST_TRIPLE_1]) + .hosts(&[TEST_TRIPLE_1]) + .render_steps(), @r" + [build] llvm <host> + [build] rustc 0 <host> -> rustc 1 <host> + [build] rustc 1 <host> -> std 1 <host> + [build] rustc 1 <host> -> rustc 2 <host> + [build] rustc 2 <host> -> std 2 <host> + [build] rustc 1 <host> -> std 1 <target1> + [build] rustc 2 <host> -> std 2 <target1> + [check] rustc <target1> + [check] Rustdoc <target1> + [check] cranelift <target1> + [check] gcc <target1> + [check] Clippy <target1> + [check] Miri <target1> + [check] CargoMiri <target1> + [check] MiroptTestTools <target1> + [check] Rustfmt <target1> + [check] rust-analyzer <target1> + [check] TestFloatParse <target1> + [check] FeaturesStatusDump <target1> + [check] std <target1> + "); + } + + #[test] + fn check_library_no_explicit_stage() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("check") + .path("library") + .render_steps(), @r" + [build] llvm <host> + [build] rustc 0 <host> -> rustc 1 <host> + [check] std <host> + "); + } + + #[test] + fn check_library_stage_0() { + let ctx = TestCtx::new(); + ctx.config("check").path("library").stage(0).run(); + } + + #[test] + fn check_library_stage_1() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("check") + .path("library") + .stage(1) + .render_steps(), @r" + [build] llvm <host> + [build] rustc 0 <host> -> rustc 1 <host> + [check] std <host> + "); + } + + #[test] + fn check_library_stage_2() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("check") + .path("library") + .stage(2) + .render_steps(), @r" + [build] llvm <host> + [build] rustc 0 <host> -> rustc 1 <host> + [build] rustc 1 <host> -> std 1 <host> + [build] rustc 1 <host> -> rustc 2 <host> + [check] std <host> + "); + } + + #[test] + fn check_library_cross_compile() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("check") + .paths(&["core", "alloc", "std"]) + .targets(&[TEST_TRIPLE_1, TEST_TRIPLE_2]) + .render_steps(), @r" + [build] llvm <host> + [build] rustc 0 <host> -> rustc 1 <host> + [check] std <target1> + [check] std <target2> + "); + } + + #[test] + fn check_miri_no_explicit_stage() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("check") + .path("miri") + .render_steps(), @r" + [check] std <host> + [build] llvm <host> + [check] rustc <host> + [check] Miri <host> + "); + } + + #[test] + fn check_miri_stage_0() { + let ctx = TestCtx::new(); + ctx.config("check").path("miri").stage(0).run(); + } + + #[test] + fn check_miri_stage_1() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("check") + .path("miri") + .stage(1) + .render_steps(), @r" + [build] llvm <host> + [build] rustc 0 <host> -> rustc 1 <host> + [build] rustc 1 <host> -> std 1 <host> + [check] rustc <host> + [check] Miri <host> + "); + } + + #[test] + fn check_miri_stage_2() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("check") + .path("miri") + .stage(2) + .render_steps(), @r" + [build] llvm <host> + [build] rustc 0 <host> -> rustc 1 <host> + [build] rustc 1 <host> -> std 1 <host> + [build] rustc 1 <host> -> rustc 2 <host> + [build] rustc 2 <host> -> std 2 <host> + [check] rustc <host> + [check] Miri <host> + "); + } + + #[test] + fn check_compiletest() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("check") + .path("compiletest") + .render_steps(), @"[check] compiletest <host>"); + } + + #[test] + fn check_compiletest_stage1_libtest() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("check") + .path("compiletest") + .args(&["--set", "build.compiletest-use-stage0-libtest=false"]) + .render_steps(), @r" + [check] std <host> + [build] llvm <host> + [check] rustc <host> + [check] compiletest <host> + "); + } + + #[test] + fn check_codegen() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("check") + .path("rustc_codegen_cranelift") + .render_steps(), @r" + [check] std <host> + [build] llvm <host> + [check] rustc <host> + [check] cranelift <host> + [check] gcc <host> + "); + } + + #[test] + fn check_rust_analyzer() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("check") + .path("rust-analyzer") + .render_steps(), @r" + [check] std <host> + [build] llvm <host> + [check] rustc <host> + [check] rust-analyzer <host> + "); + } + + #[test] + fn check_bootstrap_tool() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("check") + .path("run-make-support") + .render_steps(), @r" + [check] std <host> + [build] llvm <host> + [check] rustc <host> + [check] RunMakeSupport <host> + "); + } + + #[test] fn test_exclude() { let ctx = TestCtx::new(); let steps = ctx.config("test").args(&["--skip", "src/tools/tidy"]).get_steps(); @@ -1384,7 +1667,7 @@ fn render_metadata(metadata: &StepMetadata) -> String { if let Some(compiler) = metadata.built_by { write!(record, "{} -> ", render_compiler(compiler)); } - let stage = if let Some(stage) = metadata.stage { format!("{stage} ") } else { "".to_string() }; + let stage = metadata.get_stage().map(|stage| format!("{stage} ")).unwrap_or_default(); write!(record, "{} {stage}<{}>", metadata.name, normalize_target(metadata.target)); record } diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 0cdfbbdaf75..49b3fec4c35 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -297,7 +297,8 @@ pub struct Config { /// Whether to use the precompiled stage0 libtest with compiletest. pub compiletest_use_stage0_libtest: bool, - + /// Default value for `--extra-checks` + pub tidy_extra_checks: Option<String>, pub is_running_on_ci: bool, /// Cache for determining path modifications @@ -744,6 +745,7 @@ impl Config { jobs, compiletest_diff_tool, compiletest_use_stage0_libtest, + tidy_extra_checks, mut ccache, exclude, } = toml.build.unwrap_or_default(); @@ -1010,6 +1012,7 @@ impl Config { optimized_compiler_builtins.unwrap_or(config.channel != "dev"); config.compiletest_diff_tool = compiletest_diff_tool; config.compiletest_use_stage0_libtest = compiletest_use_stage0_libtest.unwrap_or(true); + config.tidy_extra_checks = tidy_extra_checks; let download_rustc = config.download_rustc_commit.is_some(); config.explicit_stage_from_cli = flags_stage.is_some(); diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs index bb21d033458..79275db6486 100644 --- a/src/bootstrap/src/core/config/flags.rs +++ b/src/bootstrap/src/core/config/flags.rs @@ -382,7 +382,7 @@ pub enum Subcommand { bless: bool, #[arg(long)] /// comma-separated list of other files types to check (accepts py, py:lint, - /// py:fmt, shell) + /// py:fmt, shell, shell:lint, cpp, cpp:fmt, spellcheck, spellcheck:fix) extra_checks: Option<String>, #[arg(long)] /// rerun tests even if the inputs are unchanged diff --git a/src/bootstrap/src/core/config/toml/build.rs b/src/bootstrap/src/core/config/toml/build.rs index 98e1194de72..4d29691f38b 100644 --- a/src/bootstrap/src/core/config/toml/build.rs +++ b/src/bootstrap/src/core/config/toml/build.rs @@ -69,6 +69,7 @@ define_config! { jobs: Option<u32> = "jobs", compiletest_diff_tool: Option<String> = "compiletest-diff-tool", compiletest_use_stage0_libtest: Option<bool> = "compiletest-use-stage0-libtest", + tidy_extra_checks: Option<String> = "tidy-extra-checks", ccache: Option<StringOrBool> = "ccache", exclude: Option<Vec<PathBuf>> = "exclude", } diff --git a/src/bootstrap/src/core/config/toml/rust.rs b/src/bootstrap/src/core/config/toml/rust.rs index 642f2f2271d..ac5eaea3bcb 100644 --- a/src/bootstrap/src/core/config/toml/rust.rs +++ b/src/bootstrap/src/core/config/toml/rust.rs @@ -393,6 +393,27 @@ pub fn check_incompatible_options_for_ci_rustc( Ok(()) } +pub(crate) const VALID_CODEGEN_BACKENDS: &[&str] = &["llvm", "cranelift", "gcc"]; + +pub(crate) fn validate_codegen_backends(backends: Vec<String>, section: &str) -> Vec<String> { + for backend in &backends { + if let Some(stripped) = backend.strip_prefix(CODEGEN_BACKEND_PREFIX) { + panic!( + "Invalid value '{backend}' for '{section}.codegen-backends'. \ + Codegen backends are defined without the '{CODEGEN_BACKEND_PREFIX}' prefix. \ + Please, use '{stripped}' instead." + ) + } + if !VALID_CODEGEN_BACKENDS.contains(&backend.as_str()) { + println!( + "HELP: '{backend}' for '{section}.codegen-backends' might fail. \ + List of known good values: {VALID_CODEGEN_BACKENDS:?}" + ); + } + } + backends +} + impl Config { pub fn apply_rust_config( &mut self, @@ -571,24 +592,10 @@ impl Config { set(&mut self.ehcont_guard, ehcont_guard); self.llvm_libunwind_default = llvm_libunwind.map(|v| v.parse().expect("failed to parse rust.llvm-libunwind")); - - if let Some(ref backends) = codegen_backends { - let available_backends = ["llvm", "cranelift", "gcc"]; - - self.rust_codegen_backends = backends.iter().map(|s| { - if let Some(backend) = s.strip_prefix(CODEGEN_BACKEND_PREFIX) { - if available_backends.contains(&backend) { - panic!("Invalid value '{s}' for 'rust.codegen-backends'. Instead, please use '{backend}'."); - } else { - println!("HELP: '{s}' for 'rust.codegen-backends' might fail. \ - Codegen backends are mostly defined without the '{CODEGEN_BACKEND_PREFIX}' prefix. \ - In this case, it would be referred to as '{backend}'."); - } - } - - s.clone() - }).collect(); - } + set( + &mut self.rust_codegen_backends, + codegen_backends.map(|backends| validate_codegen_backends(backends, "rust")), + ); self.rust_codegen_units = codegen_units.map(threads_from_config); self.rust_codegen_units_std = codegen_units_std.map(threads_from_config); diff --git a/src/bootstrap/src/core/config/toml/target.rs b/src/bootstrap/src/core/config/toml/target.rs index b9f6780ca3f..337276948b3 100644 --- a/src/bootstrap/src/core/config/toml/target.rs +++ b/src/bootstrap/src/core/config/toml/target.rs @@ -16,7 +16,7 @@ use std::collections::HashMap; use serde::{Deserialize, Deserializer}; -use crate::core::build_steps::compile::CODEGEN_BACKEND_PREFIX; +use crate::core::config::toml::rust::validate_codegen_backends; use crate::core::config::{LlvmLibunwind, Merge, ReplaceOpt, SplitDebuginfo, StringOrBool}; use crate::{Config, HashSet, PathBuf, TargetSelection, define_config, exit}; @@ -142,23 +142,9 @@ impl Config { target.rpath = cfg.rpath; target.optimized_compiler_builtins = cfg.optimized_compiler_builtins; target.jemalloc = cfg.jemalloc; - - if let Some(ref backends) = cfg.codegen_backends { - let available_backends = ["llvm", "cranelift", "gcc"]; - - target.codegen_backends = Some(backends.iter().map(|s| { - if let Some(backend) = s.strip_prefix(CODEGEN_BACKEND_PREFIX) { - if available_backends.contains(&backend) { - panic!("Invalid value '{s}' for 'target.{triple}.codegen-backends'. Instead, please use '{backend}'."); - } else { - println!("HELP: '{s}' for 'target.{triple}.codegen-backends' might fail. \ - Codegen backends are mostly defined without the '{CODEGEN_BACKEND_PREFIX}' prefix. \ - In this case, it would be referred to as '{backend}'."); - } - } - - s.clone() - }).collect()); + if let Some(backends) = cfg.codegen_backends { + target.codegen_backends = + Some(validate_codegen_backends(backends, &format!("target.{triple}"))) } target.split_debuginfo = cfg.split_debuginfo.as_ref().map(|v| { diff --git a/src/bootstrap/src/utils/cache/tests.rs b/src/bootstrap/src/utils/cache/tests.rs index 8562a35b3e0..fd0a7cccd60 100644 --- a/src/bootstrap/src/utils/cache/tests.rs +++ b/src/bootstrap/src/utils/cache/tests.rs @@ -1,12 +1,13 @@ use std::path::PathBuf; -use crate::utils::cache::{INTERNER, Internable, TyIntern}; +use crate::utils::cache::{INTERNER, Internable, Interner, TyIntern}; #[test] fn test_string_interning() { - let s1 = INTERNER.intern_str("Hello"); - let s2 = INTERNER.intern_str("Hello"); - let s3 = INTERNER.intern_str("world"); + let interner = Interner::default(); + let s1 = interner.intern_str("Hello"); + let s2 = interner.intern_str("Hello"); + let s3 = interner.intern_str("world"); assert_eq!(s1, s2, "Same strings should be interned to the same instance"); assert_ne!(s1, s3, "Different strings should have different interned values"); @@ -14,6 +15,8 @@ fn test_string_interning() { #[test] fn test_interned_equality() { + // Because we compare with &str, and the Deref impl accesses the global + // INTERNER variable, we cannot use a local Interner variable here. let s1 = INTERNER.intern_str("test"); let s2 = INTERNER.intern_str("test"); diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index f873c62588b..68312a503ee 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -149,7 +149,7 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ ChangeInfo { change_id: 121976, severity: ChangeSeverity::Info, - summary: "A new `boostrap-cache-path` option has been introduced which can be utilized to modify the cache path for bootstrap.", + summary: "A new `bootstrap-cache-path` option has been introduced which can be utilized to modify the cache path for bootstrap.", }, ChangeInfo { change_id: 122108, @@ -404,7 +404,7 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ ChangeInfo { change_id: 140438, severity: ChangeSeverity::Info, - summary: "Added a new option `rust.debug-assertions-tools` to control debug asssertions for tools.", + summary: "Added a new option `rust.debug-assertions-tools` to control debug assertions for tools.", }, ChangeInfo { change_id: 140732, @@ -441,4 +441,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Warning, summary: "`llvm.lld` is no longer enabled by default for the dist profile.", }, + ChangeInfo { + change_id: 143251, + severity: ChangeSeverity::Info, + summary: "Added new option `build.tidy-extra-checks` to specify a default value for the --extra-checks cli flag.", + }, ]; diff --git a/src/bootstrap/src/utils/proc_macro_deps.rs b/src/bootstrap/src/utils/proc_macro_deps.rs index b61fa3bb8d6..21c7fc89d7d 100644 --- a/src/bootstrap/src/utils/proc_macro_deps.rs +++ b/src/bootstrap/src/utils/proc_macro_deps.rs @@ -30,7 +30,6 @@ pub static CRATES: &[&str] = &[ "memchr", "minimal-lexical", "nom", - "once_cell", "pest", "pest_generator", "pest_meta", diff --git a/src/ci/citool/src/jobs.rs b/src/ci/citool/src/jobs.rs index 81e002edb15..410274227e4 100644 --- a/src/ci/citool/src/jobs.rs +++ b/src/ci/citool/src/jobs.rs @@ -13,7 +13,7 @@ use crate::utils::load_env_var; #[derive(serde::Deserialize, Debug, Clone)] #[serde(deny_unknown_fields)] pub struct Job { - /// Name of the job, e.g. mingw-check-1 + /// Name of the job, e.g. pr-check-1 pub name: String, /// GitHub runner on which the job should be executed pub os: String, @@ -66,6 +66,8 @@ pub struct JobDatabase { pub try_jobs: Vec<Job>, #[serde(rename = "auto")] pub auto_jobs: Vec<Job>, + #[serde(rename = "optional")] + pub optional_jobs: Vec<Job>, /// Shared environments for the individual run types. envs: JobEnvironments, @@ -75,9 +77,10 @@ impl JobDatabase { /// Find `auto` jobs that correspond to the passed `pattern`. /// Patterns are matched using the glob syntax. /// For example `dist-*` matches all jobs starting with `dist-`. - fn find_auto_jobs_by_pattern(&self, pattern: &str) -> Vec<Job> { + fn find_auto_or_optional_jobs_by_pattern(&self, pattern: &str) -> Vec<Job> { self.auto_jobs .iter() + .chain(self.optional_jobs.iter()) .filter(|j| glob_match::glob_match(pattern, &j.name)) .cloned() .collect() @@ -181,7 +184,7 @@ fn calculate_jobs( let mut jobs: Vec<Job> = vec![]; let mut unknown_patterns = vec![]; for pattern in patterns { - let matched_jobs = db.find_auto_jobs_by_pattern(pattern); + let matched_jobs = db.find_auto_or_optional_jobs_by_pattern(pattern); if matched_jobs.is_empty() { unknown_patterns.push(pattern.clone()); } else { diff --git a/src/ci/citool/src/jobs/tests.rs b/src/ci/citool/src/jobs/tests.rs index ed5444d4333..63ac508b632 100644 --- a/src/ci/citool/src/jobs/tests.rs +++ b/src/ci/citool/src/jobs/tests.rs @@ -46,6 +46,13 @@ auto: - name: test-msvc-i686-2 os: ubuntu env: {} +optional: + - name: optional-job-1 + os: ubuntu + env: {} + - name: optional-dist-x86_64 + os: ubuntu + env: {} "#, ) .unwrap(); @@ -57,12 +64,18 @@ auto: "*i686*", &["test-i686", "dist-i686", "test-msvc-i686-1", "test-msvc-i686-2"], ); + // Test that optional jobs are found + check_pattern(&db, "optional-*", &["optional-job-1", "optional-dist-x86_64"]); + check_pattern(&db, "*optional*", &["optional-job-1", "optional-dist-x86_64"]); } #[track_caller] fn check_pattern(db: &JobDatabase, pattern: &str, expected: &[&str]) { - let jobs = - db.find_auto_jobs_by_pattern(pattern).into_iter().map(|j| j.name).collect::<Vec<_>>(); + let jobs = db + .find_auto_or_optional_jobs_by_pattern(pattern) + .into_iter() + .map(|j| j.name) + .collect::<Vec<_>>(); assert_eq!(jobs, expected); } @@ -116,8 +129,13 @@ fn validate_jobs() { load_job_db(&db_str).expect("Failed to load job database") }; - let all_jobs = - db.pr_jobs.iter().chain(db.try_jobs.iter()).chain(db.auto_jobs.iter()).collect::<Vec<_>>(); + let all_jobs = db + .pr_jobs + .iter() + .chain(db.try_jobs.iter()) + .chain(db.auto_jobs.iter()) + .chain(db.optional_jobs.iter()) + .collect::<Vec<_>>(); let errors: Vec<anyhow::Error> = all_jobs.into_iter().filter_map(|job| validate_codebuild_image(job).err()).collect(); diff --git a/src/ci/citool/tests/jobs.rs b/src/ci/citool/tests/jobs.rs index 83f2fc0ed1f..dbaf13d4f42 100644 --- a/src/ci/citool/tests/jobs.rs +++ b/src/ci/citool/tests/jobs.rs @@ -40,7 +40,7 @@ try-job: dist-i686-msvc"#, fn pr_jobs() { let stdout = get_matrix("pull_request", "commit", "refs/heads/pr/1234"); insta::assert_snapshot!(stdout, @r#" - jobs=[{"name":"mingw-check-1","full_name":"PR - mingw-check-1","os":"ubuntu-24.04","env":{"PR_CI_JOB":1},"free_disk":true},{"name":"mingw-check-2","full_name":"PR - mingw-check-2","os":"ubuntu-24.04","env":{"PR_CI_JOB":1},"free_disk":true},{"name":"mingw-check-tidy","full_name":"PR - mingw-check-tidy","os":"ubuntu-24.04","env":{"PR_CI_JOB":1},"continue_on_error":true,"free_disk":true,"doc_url":"https://foo.bar"}] + jobs=[{"name":"pr-check-1","full_name":"PR - pr-check-1","os":"ubuntu-24.04","env":{"PR_CI_JOB":1},"free_disk":true},{"name":"pr-check-2","full_name":"PR - pr-check-2","os":"ubuntu-24.04","env":{"PR_CI_JOB":1},"free_disk":true},{"name":"tidy","full_name":"PR - tidy","os":"ubuntu-24.04","env":{"PR_CI_JOB":1},"continue_on_error":true,"free_disk":true,"doc_url":"https://foo.bar"}] run_type=pr "#); } diff --git a/src/ci/citool/tests/test-jobs.yml b/src/ci/citool/tests/test-jobs.yml index d262da11102..d82b3e7648e 100644 --- a/src/ci/citool/tests/test-jobs.yml +++ b/src/ci/citool/tests/test-jobs.yml @@ -64,11 +64,11 @@ envs: # These jobs automatically inherit envs.pr, to avoid repeating # it in each job definition. pr: - - name: mingw-check-1 + - name: pr-check-1 <<: *job-linux-4c - - name: mingw-check-2 + - name: pr-check-2 <<: *job-linux-4c - - name: mingw-check-tidy + - name: tidy continue_on_error: true doc_url: https://foo.bar <<: *job-linux-4c @@ -139,3 +139,8 @@ auto: DIST_REQUIRE_ALL_TOOLS: 1 CODEGEN_BACKENDS: llvm,cranelift <<: *job-windows + +# Jobs that only run when explicitly invoked via `@bors try`. +optional: + - name: test-optional-job + <<: *job-linux-4c diff --git a/src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile b/src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile index d5027589e0b..e6133fce83e 100644 --- a/src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile +++ b/src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile @@ -26,6 +26,5 @@ ENV RUST_CONFIGURE_ARGS \ --enable-sanitizers \ --enable-profiler \ --enable-compiler-docs -# FIXME: Skipping cargo panic_abort_doc_tests due to https://github.com/rust-lang/rust/issues/123733 ENV SCRIPT python3 ../x.py --stage 2 test && \ - python3 ../x.py --stage 2 test src/tools/cargo --test-args \"--skip panic_abort_doc_tests\" + python3 ../x.py --stage 2 test src/tools/cargo diff --git a/src/ci/docker/host-x86_64/mingw-check-1/Dockerfile b/src/ci/docker/host-x86_64/mingw-check-1/Dockerfile deleted file mode 100644 index c46a2471e75..00000000000 --- a/src/ci/docker/host-x86_64/mingw-check-1/Dockerfile +++ /dev/null @@ -1,58 +0,0 @@ -FROM ubuntu:22.04 - -ARG DEBIAN_FRONTEND=noninteractive -RUN apt-get update && apt-get install -y --no-install-recommends \ - g++ \ - make \ - ninja-build \ - file \ - curl \ - ca-certificates \ - python3 \ - python3-pip \ - python3-pkg-resources \ - git \ - cmake \ - sudo \ - gdb \ - xz-utils \ - libssl-dev \ - pkg-config \ - mingw-w64 \ - && rm -rf /var/lib/apt/lists/* - -ENV RUST_CONFIGURE_ARGS="--set rust.validate-mir-opts=3" - -COPY scripts/nodejs.sh /scripts/ -RUN sh /scripts/nodejs.sh /node -ENV PATH="/node/bin:${PATH}" - -# Install es-check -# Pin its version to prevent unrelated CI failures due to future es-check versions. -RUN npm install es-check@6.1.1 eslint@8.6.0 typescript@5.7.3 -g - -COPY scripts/sccache.sh /scripts/ -RUN sh /scripts/sccache.sh - -COPY host-x86_64/mingw-check-1/reuse-requirements.txt /tmp/ -RUN pip3 install --no-deps --no-cache-dir --require-hashes -r /tmp/reuse-requirements.txt - -COPY host-x86_64/mingw-check-1/check-default-config-profiles.sh /scripts/ -COPY host-x86_64/mingw-check-1/validate-toolstate.sh /scripts/ - -# Check library crates on all tier 1 targets. -# We disable optimized compiler built-ins because that requires a C toolchain for the target. -# We also skip the x86_64-unknown-linux-gnu target as it is well-tested by other jobs. -ENV SCRIPT \ - /scripts/check-default-config-profiles.sh && \ - python3 ../x.py build --stage 1 src/tools/build-manifest && \ - python3 ../x.py test --stage 0 src/tools/compiletest && \ - python3 ../x.py check compiletest --set build.compiletest-use-stage0-libtest=true && \ - python3 ../x.py check --stage 1 --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \ - python3 ../x.py check --stage 1 --set build.optimized-compiler-builtins=false core alloc std --target=aarch64-unknown-linux-gnu,i686-pc-windows-msvc,i686-unknown-linux-gnu,x86_64-apple-darwin,x86_64-pc-windows-gnu,x86_64-pc-windows-msvc && \ - /scripts/validate-toolstate.sh && \ - reuse --include-submodules lint && \ - python3 ../x.py test collect-license-metadata && \ - # Runs checks to ensure that there are no issues in our JS code. - es-check es2019 ../src/librustdoc/html/static/js/*.js && \ - tsc --project ../src/librustdoc/html/static/js/tsconfig.json diff --git a/src/ci/docker/host-x86_64/pr-check-1/Dockerfile b/src/ci/docker/host-x86_64/pr-check-1/Dockerfile new file mode 100644 index 00000000000..7a8056b70dc --- /dev/null +++ b/src/ci/docker/host-x86_64/pr-check-1/Dockerfile @@ -0,0 +1,58 @@ +FROM ubuntu:22.04 + +ARG DEBIAN_FRONTEND=noninteractive +RUN apt-get update && apt-get install -y --no-install-recommends \ + g++ \ + make \ + ninja-build \ + file \ + curl \ + ca-certificates \ + python3 \ + python3-pip \ + python3-pkg-resources \ + git \ + cmake \ + sudo \ + gdb \ + xz-utils \ + libssl-dev \ + pkg-config \ + mingw-w64 \ + && rm -rf /var/lib/apt/lists/* + +ENV RUST_CONFIGURE_ARGS="--set rust.validate-mir-opts=3" + +COPY scripts/nodejs.sh /scripts/ +RUN sh /scripts/nodejs.sh /node +ENV PATH="/node/bin:${PATH}" + +# Install es-check +# Pin its version to prevent unrelated CI failures due to future es-check versions. +RUN npm install es-check@6.1.1 eslint@8.6.0 typescript@5.7.3 -g + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + +COPY host-x86_64/pr-check-1/reuse-requirements.txt /tmp/ +RUN pip3 install --no-deps --no-cache-dir --require-hashes -r /tmp/reuse-requirements.txt + +COPY host-x86_64/pr-check-1/check-default-config-profiles.sh /scripts/ +COPY host-x86_64/pr-check-1/validate-toolstate.sh /scripts/ + +# Check library crates on all tier 1 targets. +# We disable optimized compiler built-ins because that requires a C toolchain for the target. +# We also skip the x86_64-unknown-linux-gnu target as it is well-tested by other jobs. +ENV SCRIPT \ + /scripts/check-default-config-profiles.sh && \ + python3 ../x.py build --stage 1 src/tools/build-manifest && \ + python3 ../x.py test --stage 0 src/tools/compiletest && \ + python3 ../x.py check compiletest --set build.compiletest-use-stage0-libtest=true && \ + python3 ../x.py check --stage 1 --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \ + python3 ../x.py check --stage 1 --set build.optimized-compiler-builtins=false core alloc std --target=aarch64-unknown-linux-gnu,i686-pc-windows-msvc,i686-unknown-linux-gnu,x86_64-apple-darwin,x86_64-pc-windows-gnu,x86_64-pc-windows-msvc && \ + /scripts/validate-toolstate.sh && \ + reuse --include-submodules lint && \ + python3 ../x.py test collect-license-metadata && \ + # Runs checks to ensure that there are no issues in our JS code. + es-check es2019 ../src/librustdoc/html/static/js/*.js && \ + tsc --project ../src/librustdoc/html/static/js/tsconfig.json diff --git a/src/ci/docker/host-x86_64/mingw-check-1/check-default-config-profiles.sh b/src/ci/docker/host-x86_64/pr-check-1/check-default-config-profiles.sh index 0c85d4b449d..0c85d4b449d 100755 --- a/src/ci/docker/host-x86_64/mingw-check-1/check-default-config-profiles.sh +++ b/src/ci/docker/host-x86_64/pr-check-1/check-default-config-profiles.sh diff --git a/src/ci/docker/host-x86_64/mingw-check-1/reuse-requirements.in b/src/ci/docker/host-x86_64/pr-check-1/reuse-requirements.in index d7c2d3fde5b..d7c2d3fde5b 100644 --- a/src/ci/docker/host-x86_64/mingw-check-1/reuse-requirements.in +++ b/src/ci/docker/host-x86_64/pr-check-1/reuse-requirements.in diff --git a/src/ci/docker/host-x86_64/mingw-check-1/reuse-requirements.txt b/src/ci/docker/host-x86_64/pr-check-1/reuse-requirements.txt index 8784e18864b..8784e18864b 100644 --- a/src/ci/docker/host-x86_64/mingw-check-1/reuse-requirements.txt +++ b/src/ci/docker/host-x86_64/pr-check-1/reuse-requirements.txt diff --git a/src/ci/docker/host-x86_64/mingw-check-1/validate-toolstate.sh b/src/ci/docker/host-x86_64/pr-check-1/validate-toolstate.sh index a5691da8cda..a5691da8cda 100755 --- a/src/ci/docker/host-x86_64/mingw-check-1/validate-toolstate.sh +++ b/src/ci/docker/host-x86_64/pr-check-1/validate-toolstate.sh diff --git a/src/ci/docker/host-x86_64/mingw-check-2/Dockerfile b/src/ci/docker/host-x86_64/pr-check-2/Dockerfile index ce18a181d31..ce18a181d31 100644 --- a/src/ci/docker/host-x86_64/mingw-check-2/Dockerfile +++ b/src/ci/docker/host-x86_64/pr-check-2/Dockerfile diff --git a/src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile b/src/ci/docker/host-x86_64/tidy/Dockerfile index 62cd8a31212..dbb950cbe0c 100644 --- a/src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile +++ b/src/ci/docker/host-x86_64/tidy/Dockerfile @@ -1,5 +1,5 @@ # We use the ghcr base image because ghcr doesn't have a rate limit -# and the mingw-check-tidy job doesn't cache docker images in CI. +# and the tidy job doesn't cache docker images in CI. FROM ghcr.io/rust-lang/ubuntu:22.04 ARG DEBIAN_FRONTEND=noninteractive @@ -29,20 +29,20 @@ RUN sh /scripts/nodejs.sh /node ENV PATH="/node/bin:${PATH}" # Install eslint -COPY host-x86_64/mingw-check-tidy/eslint.version /tmp/ +COPY host-x86_64/tidy/eslint.version /tmp/ COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -COPY host-x86_64/mingw-check-1/reuse-requirements.txt /tmp/ +COPY host-x86_64/pr-check-1/reuse-requirements.txt /tmp/ RUN pip3 install --no-deps --no-cache-dir --require-hashes -r /tmp/reuse-requirements.txt \ - && pip3 install virtualenv + && pip3 install virtualenv -COPY host-x86_64/mingw-check-1/validate-toolstate.sh /scripts/ +COPY host-x86_64/pr-check-1/validate-toolstate.sh /scripts/ RUN bash -c 'npm install -g eslint@$(cat /tmp/eslint.version)' # NOTE: intentionally uses python2 for x.py so we can test it still works. # validate-toolstate only runs in our CI, so it's ok for it to only support python3. ENV SCRIPT TIDY_PRINT_DIFF=1 python2.7 ../x.py test --stage 0 \ - src/tools/tidy tidyselftest --extra-checks=py,cpp + src/tools/tidy tidyselftest --extra-checks=py,cpp diff --git a/src/ci/docker/host-x86_64/mingw-check-tidy/eslint.version b/src/ci/docker/host-x86_64/tidy/eslint.version index 1acea15afd6..1acea15afd6 100644 --- a/src/ci/docker/host-x86_64/mingw-check-tidy/eslint.version +++ b/src/ci/docker/host-x86_64/tidy/eslint.version diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version index f8d54d44557..b9f8e558df4 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version @@ -1 +1 @@ -0.20.7 \ No newline at end of file +0.21.1 \ No newline at end of file diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 3aa435003d3..01993ad28aa 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -122,11 +122,11 @@ jobs: # These jobs automatically inherit envs.pr, to avoid repeating # it in each job definition. pr: - - name: mingw-check-1 + - name: pr-check-1 <<: *job-linux-4c - - name: mingw-check-2 + - name: pr-check-2 <<: *job-linux-4c - - name: mingw-check-tidy + - name: tidy continue_on_error: true free_disk: false env: @@ -160,6 +160,17 @@ pr: try: - <<: *job-dist-x86_64-linux +# Jobs that only run when explicitly invoked in one of the following ways: +# - comment `@bors2 try jobs=<job-name>` +# - `try-job: <job-name>` in the PR description and comment `@bors try` or `@bors2 try`. +optional: + # This job is used just to test optional jobs. + # It will be replaced by tier 2 and tier 3 jobs in the future. + - name: optional-mingw-check-1 + env: + IMAGE: mingw-check-1 + <<: *job-linux-4c + # Main CI jobs that have to be green to merge a commit into master # These jobs automatically inherit envs.auto, to avoid repeating # it in each job definition. @@ -312,13 +323,13 @@ auto: /scripts/stage_2_test_set2.sh <<: *job-linux-4c - - name: mingw-check-1 + - name: pr-check-1 <<: *job-linux-4c - - name: mingw-check-2 + - name: pr-check-2 <<: *job-linux-4c - - name: mingw-check-tidy + - name: tidy free_disk: false <<: *job-linux-4c diff --git a/src/doc/rustc-dev-guide/src/solve/opaque-types.md b/src/doc/rustc-dev-guide/src/solve/opaque-types.md index 6898ef3aa78..8880962d621 100644 --- a/src/doc/rustc-dev-guide/src/solve/opaque-types.md +++ b/src/doc/rustc-dev-guide/src/solve/opaque-types.md @@ -56,7 +56,7 @@ Finally, we check whether the item bounds of the opaque hold for the expected ty [source][item-bounds-ck]. [norm]: https://github.com/rust-lang/rust/blob/384d26fc7e3bdd7687cc17b2662b091f6017ec2a/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs#L13 -[coherence-example]: https://github.com/rust-lang/rust/blob/master/tests/ui/type-alias-impl-trait/coherence_different_hidden_ty.rs +[coherence-example]: https://github.com/rust-lang/rust/blob/master/tests/ui/type-alias-impl-trait/coherence/coherence_different_hidden_ty.rs [placeholder-ck]: https://github.com/rust-lang/rust/blob/384d26fc7e3bdd7687cc17b2662b091f6017ec2a/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs#L33 [check-storage]: https://github.com/rust-lang/rust/blob/384d26fc7e3bdd7687cc17b2662b091f6017ec2a/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs#L51-L52 [eq-prev]: https://github.com/rust-lang/rust/blob/384d26fc7e3bdd7687cc17b2662b091f6017ec2a/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs#L51-L59 diff --git a/src/doc/rustc-dev-guide/src/tests/ci.md b/src/doc/rustc-dev-guide/src/tests/ci.md index 96e4edc17a5..750e4fa1a0f 100644 --- a/src/doc/rustc-dev-guide/src/tests/ci.md +++ b/src/doc/rustc-dev-guide/src/tests/ci.md @@ -66,8 +66,8 @@ kinds of builds (sets of jobs). ### Pull Request builds After each push to a pull request, a set of `pr` jobs are executed. Currently, -these execute the `x86_64-gnu-llvm-X`, `x86_64-gnu-tools`, `mingw-check-1`, `mingw-check-2` -and `mingw-check-tidy` jobs, all running on Linux. These execute a relatively short +these execute the `x86_64-gnu-llvm-X`, `x86_64-gnu-tools`, `pr-check-1`, `pr-check-2` +and `tidy` jobs, all running on Linux. These execute a relatively short (~40 minutes) and lightweight test suite that should catch common issues. More specifically, they run a set of lints, they try to perform a cross-compile check build to Windows mingw (without producing any artifacts) and they test the @@ -148,6 +148,13 @@ for example `*msvc*` or `*-alt`. You can start at most 20 jobs in a single try b glob patterns, you might want to wrap them in backticks (`` ` ``) to avoid GitHub rendering the pattern as Markdown. +The job pattern needs to match one or more jobs defined in the `auto` or `optional` sections +of [`jobs.yml`]: + +- `auto` jobs are executed before a commit is merged into the `master` branch. +- `optional` jobs are executed only when explicitly requested via a try build. + They are typically used for tier 2 and tier 3 targets. + > **Using `try-job` PR description directives** > > 1. Identify which set of try-jobs you would like to exercise. You can diff --git a/src/doc/rustc-dev-guide/src/tests/minicore.md b/src/doc/rustc-dev-guide/src/tests/minicore.md index def9aaf8733..23b77279011 100644 --- a/src/doc/rustc-dev-guide/src/tests/minicore.md +++ b/src/doc/rustc-dev-guide/src/tests/minicore.md @@ -39,6 +39,12 @@ If you find a `core` item to be missing from the [`minicore`] stub, consider adding it to the test auxiliary if it's likely to be used or is already needed by more than one test. +## Staying in sync with `core` + +The `minicore` items must be kept up to date with `core`. For consistent +diagnostic output between using `core` and `minicore`, any `diagnostic` +attributes (e.g. `on_unimplemented`) should be replicated exactly in `minicore`. + ## Example codegen test that uses `minicore` ```rust,no_run diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 201a5503079..9fe4c218121 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -130,7 +130,7 @@ - [\*-win7-windows-msvc](platform-support/win7-windows-msvc.md) - [x86_64-fortanix-unknown-sgx](platform-support/x86_64-fortanix-unknown-sgx.md) - [x86_64-pc-cygwin](platform-support/x86_64-pc-cygwin.md) - - [x86_64-unknown-linux-none.md](platform-support/x86_64-unknown-linux-none.md) + - [x86_64-unknown-linux-none](platform-support/x86_64-unknown-linux-none.md) - [x86_64-unknown-none](platform-support/x86_64-unknown-none.md) - [xtensa-\*-none-elf](platform-support/xtensa.md) - [\*-nuttx-\*](platform-support/nuttx.md) diff --git a/src/etc/completions/x.py.fish b/src/etc/completions/x.py.fish index 64734d5bcaa..e982cde634f 100644 --- a/src/etc/completions/x.py.fish +++ b/src/etc/completions/x.py.fish @@ -293,7 +293,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand doc" -l skip-std-check-if-no-d 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 extra-checks -d 'comma-separated list of other files types to check (accepts py, py:lint, py:fmt, shell, shell:lint, cpp, cpp:fmt, spellcheck, spellcheck:fix)' -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 diff --git a/src/etc/completions/x.py.ps1 b/src/etc/completions/x.py.ps1 index 154f4f95eb5..f4b26fac0bc 100644 --- a/src/etc/completions/x.py.ps1 +++ b/src/etc/completions/x.py.ps1 @@ -339,7 +339,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { '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('--extra-checks', '--extra-checks', [CompletionResultType]::ParameterName, 'comma-separated list of other files types to check (accepts py, py:lint, py:fmt, shell, shell:lint, cpp, cpp:fmt, spellcheck, spellcheck:fix)') [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') diff --git a/src/etc/completions/x.py.zsh b/src/etc/completions/x.py.zsh index 177d60f9738..8fc4f052252 100644 --- a/src/etc/completions/x.py.zsh +++ b/src/etc/completions/x.py.zsh @@ -338,7 +338,7 @@ _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:_default' \ '*--compiletest-rustc-args=[extra options to pass the compiler when running compiletest tests]:ARGS:_default' \ -'--extra-checks=[comma-separated list of other files types to check (accepts py, py\:lint, py\:fmt, shell)]:EXTRA_CHECKS:_default' \ +'--extra-checks=[comma-separated list of other files types to check (accepts py, py\:lint, py\:fmt, shell, shell\:lint, cpp, cpp\:fmt, spellcheck, spellcheck\:fix)]:EXTRA_CHECKS:_default' \ '--compare-mode=[mode describing what file the actual ui output will be compared to]:COMPARE MODE:_default' \ '--pass=[force {check,build,run}-pass tests to this mode]:check | build | run:_default' \ '--run=[whether to execute run-* tests]:auto | always | never:_default' \ diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index c889f52b789..11d5b472d73 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -23,7 +23,7 @@ pub(crate) fn synthesize_blanket_impls( let ty = tcx.type_of(item_def_id); let mut blanket_impls = Vec::new(); - for trait_def_id in tcx.all_traits() { + for trait_def_id in tcx.visible_traits() { if !cx.cache.effective_visibilities.is_reachable(tcx, trait_def_id) || cx.generated_synthetics.contains(&(ty.skip_binder(), trait_def_id)) { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 3d027db2622..2ab827b3ace 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -66,8 +66,8 @@ use crate::visit_ast::Module as DocModule; pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<'tcx>) -> Item { let mut items: Vec<Item> = vec![]; let mut inserted = FxHashSet::default(); - items.extend(doc.foreigns.iter().map(|(item, renamed)| { - let item = clean_maybe_renamed_foreign_item(cx, item, *renamed); + items.extend(doc.foreigns.iter().map(|(item, renamed, import_id)| { + let item = clean_maybe_renamed_foreign_item(cx, item, *renamed, *import_id); if let Some(name) = item.name && (cx.render_options.document_hidden || !item.is_doc_hidden()) { @@ -89,7 +89,7 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext< Some(item) })); - // Split up imports from all other items. + // Split up glob imports from all other items. // // This covers the case where somebody does an import which should pull in an item, // but there's already an item with the same namespace and same name. Rust gives @@ -1171,7 +1171,7 @@ fn clean_poly_fn_sig<'tcx>( // If this comes from a fn item, let's not perpetuate anon params from Rust 2015; use `_` for them. // If this comes from a fn ptr ty, we just keep params unnamed since it's more conventional stylistically. // Since the param name is not part of the semantic type, these params never bear a name unlike - // in the HIR case, thus we can't peform any fancy fallback logic unlike `clean_bare_fn_ty`. + // in the HIR case, thus we can't perform any fancy fallback logic unlike `clean_bare_fn_ty`. let fallback = did.map(|_| kw::Underscore); let params = sig @@ -2746,7 +2746,8 @@ fn add_without_unwanted_attributes<'hir>( attrs.push((Cow::Owned(attr), import_parent)); } } - hir::Attribute::Parsed(..) if is_inline => { + // FIXME: make sure to exclude `#[cfg_trace]` here when it is ported to the new parsers + hir::Attribute::Parsed(..) => { attrs.push((Cow::Owned(attr), import_parent)); } _ => {} @@ -2761,7 +2762,6 @@ fn clean_maybe_renamed_item<'tcx>( import_id: Option<LocalDefId>, ) -> Vec<Item> { use hir::ItemKind; - fn get_name( cx: &DocContext<'_>, item: &hir::Item<'_>, @@ -2973,6 +2973,7 @@ fn clean_extern_crate<'tcx>( && !cx.is_json_output(); let krate_owner_def_id = krate.owner_id.def_id; + if please_inline && let Some(items) = inline::try_inline( cx, @@ -3134,6 +3135,7 @@ fn clean_maybe_renamed_foreign_item<'tcx>( cx: &mut DocContext<'tcx>, item: &hir::ForeignItem<'tcx>, renamed: Option<Symbol>, + import_id: Option<LocalDefId>, ) -> Item { let def_id = item.owner_id.to_def_id(); cx.with_param_env(def_id, |cx| { @@ -3149,11 +3151,13 @@ fn clean_maybe_renamed_foreign_item<'tcx>( hir::ForeignItemKind::Type => ForeignTypeItem, }; - Item::from_def_id_and_parts( - item.owner_id.def_id.to_def_id(), - Some(renamed.unwrap_or(item.ident.name)), - kind, + generate_item_with_correct_attrs( cx, + kind, + item.owner_id.def_id.to_def_id(), + item.ident.name, + import_id, + renamed, ) }) } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 600c564d714..c9530216968 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -7,7 +7,7 @@ use arrayvec::ArrayVec; use itertools::Either; use rustc_abi::{ExternAbi, VariantIdx}; use rustc_attr_data_structures::{ - AttributeKind, ConstStability, Deprecation, Stability, StableSince, + AttributeKind, ConstStability, Deprecation, Stability, StableSince, find_attr, }; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_hir::def::{CtorKind, DefKind, Res}; @@ -24,7 +24,7 @@ use rustc_resolve::rustdoc::{ }; use rustc_session::Session; use rustc_span::hygiene::MacroKind; -use rustc_span::symbol::{Ident, Symbol, kw, sym}; +use rustc_span::symbol::{Symbol, kw, sym}; use rustc_span::{DUMMY_SP, FileName, Loc}; use thin_vec::ThinVec; use tracing::{debug, trace}; @@ -770,6 +770,17 @@ impl Item { hir::Attribute::Parsed(AttributeKind::Deprecation { .. }) => None, // We have separate pretty-printing logic for `#[repr(..)]` attributes. hir::Attribute::Parsed(AttributeKind::Repr(..)) => None, + // target_feature is special-cased because cargo-semver-checks uses it + hir::Attribute::Parsed(AttributeKind::TargetFeature(features, _)) => { + let mut output = String::new(); + for (i, (feature, _)) in features.iter().enumerate() { + if i != 0 { + output.push_str(", "); + } + output.push_str(&format!("enable=\"{}\"", feature.as_str())); + } + Some(format!("#[target_feature({output})]")) + } _ => Some({ let mut s = rustc_hir_pretty::attribute_to_string(&tcx, attr); assert_eq!(s.pop(), Some('\n')); @@ -1075,16 +1086,10 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator<Item = &'a hir::Attribute> // treat #[target_feature(enable = "feat")] attributes as if they were // #[doc(cfg(target_feature = "feat"))] attributes as well - for attr in hir_attr_lists(attrs, sym::target_feature) { - if attr.has_name(sym::enable) && attr.value_str().is_some() { - // Clone `enable = "feat"`, change to `target_feature = "feat"`. - // Unwrap is safe because `value_str` succeeded above. - let mut meta = attr.meta_item().unwrap().clone(); - meta.path = ast::Path::from_ident(Ident::with_dummy_span(sym::target_feature)); - - if let Ok(feat_cfg) = Cfg::parse(&ast::MetaItemInner::MetaItem(meta)) { - cfg &= feat_cfg; - } + if let Some(features) = find_attr!(attrs, AttributeKind::TargetFeature(features, _) => features) + { + for (feature, _) in features { + cfg &= Cfg::Cfg(sym::target_feature, Some(*feature)); } } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index cf3c4ac97af..bd57bb21e63 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -353,7 +353,7 @@ pub(crate) fn run_global_ctxt( rustc_passes::stability::check_unused_or_stable_features(tcx); let auto_traits = - tcx.all_traits().filter(|&trait_def_id| tcx.trait_is_auto(trait_def_id)).collect(); + tcx.visible_traits().filter(|&trait_def_id| tcx.trait_is_auto(trait_def_id)).collect(); let mut ctxt = DocContext { tcx, diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 1b5c9fd4664..9b4d2533954 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -858,7 +858,7 @@ impl ScrapedDocTest { item_path.push(' '); } let name = - format!("{} - {item_path}(line {line})", filename.prefer_remapped_unconditionaly()); + format!("{} - {item_path}(line {line})", filename.prefer_remapped_unconditionally()); Self { filename, line, langstr, text, name, span, global_crate_attrs } } diff --git a/src/librustdoc/doctest/extracted.rs b/src/librustdoc/doctest/extracted.rs index 925fb6fee2c..3d046ec1835 100644 --- a/src/librustdoc/doctest/extracted.rs +++ b/src/librustdoc/doctest/extracted.rs @@ -62,7 +62,7 @@ impl ExtractedDocTests { Some(&opts.crate_name), ); self.doctests.push(ExtractedDocTest { - file: filename.prefer_remapped_unconditionaly().to_string(), + file: filename.prefer_remapped_unconditionally().to_string(), line, doctest_attributes: langstr.into(), doctest_code: match wrapped { diff --git a/src/librustdoc/externalfiles.rs b/src/librustdoc/externalfiles.rs index b81fc5a0a71..ea2aa963edd 100644 --- a/src/librustdoc/externalfiles.rs +++ b/src/librustdoc/externalfiles.rs @@ -35,10 +35,9 @@ impl ExternalHtml { ) -> Option<ExternalHtml> { let codes = ErrorCodes::from(nightly_build); let ih = load_external_files(in_header, dcx)?; - let bc = load_external_files(before_content, dcx)?; - let m_bc = load_external_files(md_before_content, dcx)?; - let bc = format!( - "{bc}{}", + let bc = { + let mut bc = load_external_files(before_content, dcx)?; + let m_bc = load_external_files(md_before_content, dcx)?; Markdown { content: &m_bc, links: &[], @@ -48,12 +47,13 @@ impl ExternalHtml { playground, heading_offset: HeadingOffset::H2, } - .into_string() - ); - let ac = load_external_files(after_content, dcx)?; - let m_ac = load_external_files(md_after_content, dcx)?; - let ac = format!( - "{ac}{}", + .write_into(&mut bc) + .unwrap(); + bc + }; + let ac = { + let mut ac = load_external_files(after_content, dcx)?; + let m_ac = load_external_files(md_after_content, dcx)?; Markdown { content: &m_ac, links: &[], @@ -63,8 +63,10 @@ impl ExternalHtml { playground, heading_offset: HeadingOffset::H2, } - .into_string() - ); + .write_into(&mut ac) + .unwrap(); + ac + }; Some(ExternalHtml { in_header: ih, before_content: bc, after_content: ac }) } } diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index f626e07b000..e41435de29c 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -21,13 +21,14 @@ //! playground: &None, //! heading_offset: HeadingOffset::H2, //! }; -//! let html = md.into_string(); +//! let mut html = String::new(); +//! md.write_into(&mut html).unwrap(); //! // ... something using html //! ``` use std::borrow::Cow; use std::collections::VecDeque; -use std::fmt::Write; +use std::fmt::{self, Write}; use std::iter::Peekable; use std::ops::{ControlFlow, Range}; use std::path::PathBuf; @@ -1328,16 +1329,13 @@ impl LangString { } impl<'a> Markdown<'a> { - pub fn into_string(self) -> String { + pub fn write_into(self, f: impl fmt::Write) -> fmt::Result { // This is actually common enough to special-case if self.content.is_empty() { - return String::new(); + return Ok(()); } - let mut s = String::with_capacity(self.content.len() * 3 / 2); - html::push_html(&mut s, self.into_iter()); - - s + html::write_html_fmt(f, self.into_iter()) } fn into_iter(self) -> CodeBlocks<'a, 'a, impl Iterator<Item = Event<'a>>> { @@ -1453,19 +1451,20 @@ impl MarkdownWithToc<'_> { (toc.into_toc(), s) } - pub(crate) fn into_string(self) -> String { + + pub(crate) fn write_into(self, mut f: impl fmt::Write) -> fmt::Result { let (toc, s) = self.into_parts(); - format!("<nav id=\"rustdoc\">{toc}</nav>{s}", toc = toc.print()) + write!(f, "<nav id=\"rustdoc\">{toc}</nav>{s}", toc = toc.print()) } } impl MarkdownItemInfo<'_> { - pub(crate) fn into_string(self) -> String { + pub(crate) fn write_into(self, mut f: impl fmt::Write) -> fmt::Result { let MarkdownItemInfo(md, ids) = self; // This is actually common enough to special-case if md.is_empty() { - return String::new(); + return Ok(()); } let p = Parser::new_ext(md, main_body_opts()).into_offset_iter(); @@ -1475,8 +1474,6 @@ impl MarkdownItemInfo<'_> { _ => event, }); - let mut s = String::with_capacity(md.len() * 3 / 2); - ids.handle_footnotes(|ids, existing_footnotes| { let p = HeadingLinks::new(p, None, ids, HeadingOffset::H1); let p = footnotes::Footnotes::new(p, existing_footnotes); @@ -1484,10 +1481,8 @@ impl MarkdownItemInfo<'_> { let p = p.filter(|event| { !matches!(event, Event::Start(Tag::Paragraph) | Event::End(TagEnd::Paragraph)) }); - html::push_html(&mut s, p); - }); - - s + html::write_html_fmt(&mut f, p) + }) } } diff --git a/src/librustdoc/html/markdown/footnotes.rs b/src/librustdoc/html/markdown/footnotes.rs index ded0585ddcc..7ee012c4da2 100644 --- a/src/librustdoc/html/markdown/footnotes.rs +++ b/src/librustdoc/html/markdown/footnotes.rs @@ -38,7 +38,7 @@ impl<'a, I: Iterator<Item = SpannedEvent<'a>>> Footnotes<'a, I> { let key = key.to_owned(); let FootnoteDef { content, id } = self.footnotes.entry(key).or_insert(FootnoteDef { content: Vec::new(), id: new_id }); - // Don't allow changing the ID of existing entrys, but allow changing the contents. + // Don't allow changing the ID of existing entries, but allow changing the contents. (content, *id) } @@ -82,7 +82,7 @@ impl<'a, I: Iterator<Item = SpannedEvent<'a>>> Iterator for Footnotes<'a, I> { return Some((self.handle_footnote_reference(reference), range)); } Some((Event::Start(Tag::FootnoteDefinition(def)), _)) => { - // When we see a footnote definition, collect the assocated content, and store + // When we see a footnote definition, collect the associated content, and store // that for rendering later. let content = self.collect_footnote_def(); let (entry_content, _) = self.get_entry(&def); diff --git a/src/librustdoc/html/markdown/tests.rs b/src/librustdoc/html/markdown/tests.rs index 784d0c5d21e..61fd4287463 100644 --- a/src/librustdoc/html/markdown/tests.rs +++ b/src/librustdoc/html/markdown/tests.rs @@ -297,7 +297,8 @@ fn test_lang_string_tokenizer() { fn test_header() { fn t(input: &str, expect: &str) { let mut map = IdMap::new(); - let output = Markdown { + let mut output = String::new(); + Markdown { content: input, links: &[], ids: &mut map, @@ -306,7 +307,8 @@ fn test_header() { playground: &None, heading_offset: HeadingOffset::H2, } - .into_string(); + .write_into(&mut output) + .unwrap(); assert_eq!(output, expect, "original: {}", input); } @@ -348,7 +350,8 @@ fn test_header() { fn test_header_ids_multiple_blocks() { let mut map = IdMap::new(); fn t(map: &mut IdMap, input: &str, expect: &str) { - let output = Markdown { + let mut output = String::new(); + Markdown { content: input, links: &[], ids: map, @@ -357,7 +360,8 @@ fn test_header_ids_multiple_blocks() { playground: &None, heading_offset: HeadingOffset::H2, } - .into_string(); + .write_into(&mut output) + .unwrap(); assert_eq!(output, expect, "original: {}", input); } @@ -466,7 +470,8 @@ fn test_plain_text_summary() { fn test_markdown_html_escape() { fn t(input: &str, expect: &str) { let mut idmap = IdMap::new(); - let output = MarkdownItemInfo(input, &mut idmap).into_string(); + let mut output = String::new(); + MarkdownItemInfo(input, &mut idmap).write_into(&mut output).unwrap(); assert_eq!(output, expect, "original: {}", input); } @@ -496,7 +501,8 @@ fn test_find_testable_code_line() { fn test_ascii_with_prepending_hashtag() { fn t(input: &str, expect: &str) { let mut map = IdMap::new(); - let output = Markdown { + let mut output = String::new(); + Markdown { content: input, links: &[], ids: &mut map, @@ -505,7 +511,8 @@ fn test_ascii_with_prepending_hashtag() { playground: &None, heading_offset: HeadingOffset::H2, } - .into_string(); + .write_into(&mut output) + .unwrap(); assert_eq!(output, expect, "original: {}", input); } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index ed58bae70bd..6a1fad06ae3 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -508,22 +508,21 @@ fn scrape_examples_help(shared: &SharedContext<'_>) -> String { the Rustdoc book]({DOC_RUST_LANG_ORG_VERSION}/rustdoc/scraped-examples.html)." )); - let mut ids = IdMap::default(); format!( "<div class=\"main-heading\">\ <h1>About scraped examples</h1>\ </div>\ <div>{}</div>", - Markdown { + fmt::from_fn(|f| Markdown { content: &content, links: &[], - ids: &mut ids, + ids: &mut IdMap::default(), error_codes: shared.codes, edition: shared.edition(), playground: &shared.playground, heading_offset: HeadingOffset::H1, } - .into_string() + .write_into(f)) ) } @@ -555,20 +554,18 @@ fn render_markdown( heading_offset: HeadingOffset, ) -> impl fmt::Display { fmt::from_fn(move |f| { - write!( - f, - "<div class=\"docblock\">{}</div>", - Markdown { - content: md_text, - links: &links, - ids: &mut cx.id_map.borrow_mut(), - error_codes: cx.shared.codes, - edition: cx.shared.edition(), - playground: &cx.shared.playground, - heading_offset, - } - .into_string() - ) + f.write_str("<div class=\"docblock\">")?; + Markdown { + content: md_text, + links: &links, + ids: &mut cx.id_map.borrow_mut(), + error_codes: cx.shared.codes, + edition: cx.shared.edition(), + playground: &cx.shared.playground, + heading_offset, + } + .write_into(&mut *f)?; + f.write_str("</div>") }) } @@ -752,7 +749,7 @@ fn short_item_info( let mut id_map = cx.id_map.borrow_mut(); let html = MarkdownItemInfo(note, &mut id_map); message.push_str(": "); - message.push_str(&html.into_string()); + html.write_into(&mut message).unwrap(); } extra_info.push(ShortItemInfo::Deprecation { message }); } @@ -1947,7 +1944,7 @@ fn render_impl( // 3. Functions // // This order is because you can have associated constants used in associated types (like array - // length), and both in associcated functions. So with this order, when reading from top to + // length), and both in associated functions. So with this order, when reading from top to // bottom, you should see items definitions before they're actually used most of the time. let mut assoc_types = Vec::new(); let mut methods = Vec::new(); diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index 606a9113908..41c3f03b91b 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -443,7 +443,7 @@ impl CratesIndexPart { .expect("Object Replacement Character (U+FFFC) should not appear in the --index-page") } - /// Might return parts that are duplicate with ones in prexisting index.html + /// Might return parts that are duplicate with ones in preexisting index.html fn get(crate_name: &str, external_crates: &[String]) -> Result<PartsAndLocations<Self>, Error> { let mut ret = PartsAndLocations::default(); let path = Path::new("index.html"); diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 7be83b65fbf..99b3da8b2cd 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -8,6 +8,8 @@ 3. Copy the filenames with updated suffixes from the directory. */ +/* ignore-tidy-filelength */ + :root { --nav-sub-mobile-padding: 8px; --search-typename-width: 6.75rem; @@ -915,32 +917,30 @@ ul.block, .block li, .block ul { overflow: auto; } -.example-wrap.digits-1:not(.hide-lines) [data-nosnippet] { - width: calc(1ch + var(--line-number-padding) * 2); -} -.example-wrap.digits-2:not(.hide-lines) [data-nosnippet] { - width: calc(2ch + var(--line-number-padding) * 2); -} -.example-wrap.digits-3:not(.hide-lines) [data-nosnippet] { - width: calc(3ch + var(--line-number-padding) * 2); -} -.example-wrap.digits-4:not(.hide-lines) [data-nosnippet] { - width: calc(4ch + var(--line-number-padding) * 2); -} -.example-wrap.digits-5:not(.hide-lines) [data-nosnippet] { - width: calc(5ch + var(--line-number-padding) * 2); -} -.example-wrap.digits-6:not(.hide-lines) [data-nosnippet] { - width: calc(6ch + var(--line-number-padding) * 2); +.example-wrap code { + position: relative; } -.example-wrap.digits-7:not(.hide-lines) [data-nosnippet] { - width: calc(7ch + var(--line-number-padding) * 2); +.example-wrap pre code span { + display: inline; } -.example-wrap.digits-8:not(.hide-lines) [data-nosnippet] { - width: calc(8ch + var(--line-number-padding) * 2); + +.example-wrap.digits-1 { --example-wrap-digits-count: 1ch; } +.example-wrap.digits-2 { --example-wrap-digits-count: 2ch; } +.example-wrap.digits-3 { --example-wrap-digits-count: 3ch; } +.example-wrap.digits-4 { --example-wrap-digits-count: 4ch; } +.example-wrap.digits-5 { --example-wrap-digits-count: 5ch; } +.example-wrap.digits-6 { --example-wrap-digits-count: 6ch; } +.example-wrap.digits-7 { --example-wrap-digits-count: 7ch; } +.example-wrap.digits-8 { --example-wrap-digits-count: 8ch; } +.example-wrap.digits-9 { --example-wrap-digits-count: 9ch; } + +.example-wrap [data-nosnippet] { + width: calc(var(--example-wrap-digits-count) + var(--line-number-padding) * 2); } -.example-wrap.digits-9:not(.hide-lines) [data-nosnippet] { - width: calc(9ch + var(--line-number-padding) * 2); +.example-wrap pre > code { + padding-left: calc( + var(--example-wrap-digits-count) + var(--line-number-padding) * 2 + + var(--line-number-right-margin)); } .example-wrap [data-nosnippet] { @@ -953,63 +953,25 @@ ul.block, .block li, .block ul { -ms-user-select: none; user-select: none; padding: 0 var(--line-number-padding); -} -.example-wrap [data-nosnippet]:target { - border-right: none; + position: absolute; + left: 0; } .example-wrap .line-highlighted[data-nosnippet] { background-color: var(--src-line-number-highlighted-background-color); } -:root.word-wrap-source-code .example-wrap [data-nosnippet] { - position: absolute; - left: 0; -} -.word-wrap-source-code .example-wrap pre > code { +.example-wrap pre > code { position: relative; - word-break: break-all; + display: block; } :root.word-wrap-source-code .example-wrap pre > code { - display: block; + word-break: break-all; white-space: pre-wrap; } :root.word-wrap-source-code .example-wrap pre > code * { word-break: break-all; } -:root.word-wrap-source-code .example-wrap.digits-1 pre > code { - padding-left: calc( - 1ch + var(--line-number-padding) * 2 + var(--line-number-right-margin)); -} -:root.word-wrap-source-code .example-wrap.digits-2 pre > code { - padding-left: calc( - 2ch + var(--line-number-padding) * 2 + var(--line-number-right-margin)); -} -:root.word-wrap-source-code .example-wrap.digits-3 pre > code { - padding-left: calc( - 3ch + var(--line-number-padding) * 2 + var(--line-number-right-margin)); -} -:root.word-wrap-source-code .example-wrap.digits-4 pre > code { - padding-left: calc( - 4ch + var(--line-number-padding) * 2 + var(--line-number-right-margin)); -} -:root.word-wrap-source-code .example-wrap.digits-5 pre > code { - padding-left: calc( - 5ch + var(--line-number-padding) * 2 + var(--line-number-right-margin)); -} -:root.word-wrap-source-code .example-wrap.digits-6 pre > code { - padding-left: calc( - 6ch + var(--line-number-padding) * 2 + var(--line-number-right-margin)); -} -:root.word-wrap-source-code .example-wrap.digits-7 pre > code { - padding-left: calc( - 7ch + var(--line-number-padding) * 2 + var(--line-number-right-margin)); -} -:root.word-wrap-source-code .example-wrap.digits-8 pre > code { - padding-left: calc( - 8ch + var(--line-number-padding) * 2 + var(--line-number-right-margin)); -} -:root.word-wrap-source-code .example-wrap.digits-9 pre > code { - padding-left: calc( - 9ch + var(--line-number-padding) * 2 + var(--line-number-right-margin)); +.example-wrap [data-nosnippet]:target { + border-right: none; } .example-wrap.hide-lines [data-nosnippet] { display: none; diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 2de8f836da3..3c4af0dc612 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -1719,7 +1719,7 @@ function preLoadCss(cssUrl) { // 300px, and the RUSTDOC_MOBILE_BREAKPOINT is 700px, so BODY_MIN must be // at most 400px. Otherwise, it would start out at the default size, then // grabbing the resize handle would suddenly cause it to jank to - // its contraint-generated maximum. + // its constraint-generated maximum. const RUSTDOC_MOBILE_BREAKPOINT = 700; const BODY_MIN = 400; // At half-way past the minimum size, vanish the sidebar entirely diff --git a/src/librustdoc/html/static/js/rustdoc.d.ts b/src/librustdoc/html/static/js/rustdoc.d.ts index bbcd96040be..ca2512e5ab6 100644 --- a/src/librustdoc/html/static/js/rustdoc.d.ts +++ b/src/librustdoc/html/static/js/rustdoc.d.ts @@ -464,7 +464,7 @@ declare namespace rustdoc { /** * Maps from crate names to trait implementation data. - * Provied by generated `trait.impl` files. + * Provided by generated `trait.impl` files. */ type Implementors = { [key: string]: Array<[string, number, Array<string>]> diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 76eac084907..4ca2c104888 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -8,7 +8,7 @@ //! //! [docs]: https://doc.rust-lang.org/stable/rustdoc/#using-standalone-markdown-files -use std::fmt::Write as _; +use std::fmt::{self, Write as _}; use std::fs::{File, create_dir_all, read_to_string}; use std::io::prelude::*; use std::path::Path; @@ -77,32 +77,33 @@ pub(crate) fn render_and_write<P: AsRef<Path>>( } let title = metadata[0]; - let mut ids = IdMap::new(); let error_codes = ErrorCodes::from(options.unstable_features.is_nightly_build()); - let text = if !options.markdown_no_toc { - MarkdownWithToc { - content: text, - links: &[], - ids: &mut ids, - error_codes, - edition, - playground: &playground, - } - .into_string() - } else { - Markdown { - content: text, - links: &[], - ids: &mut ids, - error_codes, - edition, - playground: &playground, - heading_offset: HeadingOffset::H1, + let text = fmt::from_fn(|f| { + if !options.markdown_no_toc { + MarkdownWithToc { + content: text, + links: &[], + ids: &mut IdMap::new(), + error_codes, + edition, + playground: &playground, + } + .write_into(f) + } else { + Markdown { + content: text, + links: &[], + ids: &mut IdMap::new(), + error_codes, + edition, + playground: &playground, + heading_offset: HeadingOffset::H1, + } + .write_into(f) } - .into_string() - }; + }); - let err = write!( + let res = write!( &mut out, r#"<!DOCTYPE html> <html lang="en"> @@ -130,15 +131,10 @@ pub(crate) fn render_and_write<P: AsRef<Path>>( </body> </html>"#, title = Escape(title), - css = css, in_header = options.external_html.in_header, before_content = options.external_html.before_content, - text = text, after_content = options.external_html.after_content, ); - match err { - Err(e) => Err(format!("cannot write to `{output}`: {e}", output = output.display())), - Ok(_) => Ok(()), - } + res.map_err(|e| format!("cannot write to `{output}`: {e}", output = output.display())) } diff --git a/src/librustdoc/passes/strip_aliased_non_local.rs b/src/librustdoc/passes/strip_aliased_non_local.rs index 7f5c7da3634..b53e3b4e3d7 100644 --- a/src/librustdoc/passes/strip_aliased_non_local.rs +++ b/src/librustdoc/passes/strip_aliased_non_local.rs @@ -42,7 +42,7 @@ struct NonLocalStripper<'tcx> { impl DocFolder for NonLocalStripper<'_> { fn fold_item(&mut self, i: Item) -> Option<Item> { // If not local, we want to respect the original visibility of - // the field and not the one given by the user for the currrent crate. + // the field and not the one given by the user for the current crate. // // FIXME(#125009): Not-local should probably consider same Cargo workspace if let Some(def_id) = i.def_id() diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs index 692ce21d6cf..3388ae46f05 100644 --- a/src/librustdoc/passes/strip_hidden.rs +++ b/src/librustdoc/passes/strip_hidden.rs @@ -168,7 +168,7 @@ impl DocFolder for Stripper<'_, '_> { self.update_retained = old; 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"); + debug!("strip_hidden: Not stripping local crate"); Some(ret) } else { Some(strip_item(ret)) diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 5b52e785b8f..2889bfae7b0 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -38,9 +38,18 @@ pub(crate) struct Module<'hir> { (LocalDefId, Option<Symbol>), (&'hir hir::Item<'hir>, Option<Symbol>, Option<LocalDefId>), >, - /// Same as for `items`. + + /// (def_id, renamed) -> (res, local_import_id) + /// + /// `inlined_foreigns` only contains `extern` items + /// that are cross-crate inlined. + /// + /// Locally inlined `extern` items are + /// stored in `foreigns` with the `import_id` set, + /// analogous to how `items` is. pub(crate) inlined_foreigns: FxIndexMap<(DefId, Option<Symbol>), (Res, LocalDefId)>, - pub(crate) foreigns: Vec<(&'hir hir::ForeignItem<'hir>, Option<Symbol>)>, + /// (item, renamed, import_id) + pub(crate) foreigns: Vec<(&'hir hir::ForeignItem<'hir>, Option<Symbol>, Option<LocalDefId>)>, } impl Module<'_> { @@ -327,7 +336,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } Node::ForeignItem(it) if !glob => { let prev = mem::replace(&mut self.inlining, true); - self.visit_foreign_item_inner(it, renamed); + self.visit_foreign_item_inner(it, renamed, Some(def_id)); self.inlining = prev; true } @@ -432,7 +441,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { hir::ItemKind::ForeignMod { items, .. } => { for item in items { let item = tcx.hir_foreign_item(item.id); - self.visit_foreign_item_inner(item, None); + self.visit_foreign_item_inner(item, None, None); } } // If we're inlining, skip private items. @@ -527,10 +536,11 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { &mut self, item: &'tcx hir::ForeignItem<'_>, renamed: Option<Symbol>, + import_id: Option<LocalDefId>, ) { // If inlining we only want to include public functions. if !self.inlining || self.cx.tcx.visibility(item.owner_id).is_public() { - self.modules.last_mut().unwrap().foreigns.push((item, renamed)); + self.modules.last_mut().unwrap().foreigns.push((item, renamed, import_id)); } } diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs index dc240dd067b..8453165818b 100644 --- a/src/tools/clippy/clippy_utils/src/diagnostics.rs +++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs @@ -98,6 +98,7 @@ fn validate_diag(diag: &Diag<'_, impl EmissionGuarantee>) { /// 17 | std::mem::forget(seven); /// | ^^^^^^^^^^^^^^^^^^^^^^^ /// ``` +#[track_caller] pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) { #[expect(clippy::disallowed_methods)] cx.span_lint(lint, sp, |diag| { @@ -143,6 +144,7 @@ pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: impl Into<Mult /// | /// = help: consider using `f64::NAN` if you would like a constant representing NaN /// ``` +#[track_caller] pub fn span_lint_and_help<T: LintContext>( cx: &T, lint: &'static Lint, @@ -203,6 +205,7 @@ pub fn span_lint_and_help<T: LintContext>( /// 10 | forget(&SomeStruct); /// | ^^^^^^^^^^^ /// ``` +#[track_caller] pub fn span_lint_and_note<T: LintContext>( cx: &T, lint: &'static Lint, @@ -244,6 +247,7 @@ pub fn span_lint_and_note<T: LintContext>( /// If you're unsure which function you should use, you can test if the `#[expect]` attribute works /// where you would expect it to. /// If it doesn't, you likely need to use [`span_lint_hir_and_then`] instead. +#[track_caller] pub fn span_lint_and_then<C, S, M, F>(cx: &C, lint: &'static Lint, sp: S, msg: M, f: F) where C: LintContext, @@ -286,6 +290,7 @@ where /// Instead, use this function and also pass the `HirId` of `<expr_1>`, which will let /// the compiler check lint level attributes at the place of the expression and /// the `#[allow]` will work. +#[track_caller] pub fn span_lint_hir(cx: &LateContext<'_>, lint: &'static Lint, hir_id: HirId, sp: Span, msg: impl Into<DiagMessage>) { #[expect(clippy::disallowed_methods)] cx.tcx.node_span_lint(lint, hir_id, sp, |diag| { @@ -321,6 +326,7 @@ pub fn span_lint_hir(cx: &LateContext<'_>, lint: &'static Lint, hir_id: HirId, s /// Instead, use this function and also pass the `HirId` of `<expr_1>`, which will let /// the compiler check lint level attributes at the place of the expression and /// the `#[allow]` will work. +#[track_caller] pub fn span_lint_hir_and_then( cx: &LateContext<'_>, lint: &'static Lint, @@ -374,6 +380,7 @@ pub fn span_lint_hir_and_then( /// = note: `-D fold-any` implied by `-D warnings` /// ``` #[cfg_attr(not(debug_assertions), expect(clippy::collapsible_span_lint_calls))] +#[track_caller] pub fn span_lint_and_sugg<T: LintContext>( cx: &T, lint: &'static Lint, diff --git a/src/tools/clippy/tests/ui/track-diagnostics-clippy.rs b/src/tools/clippy/tests/ui/track-diagnostics-clippy.rs new file mode 100644 index 00000000000..2e67fb65efc --- /dev/null +++ b/src/tools/clippy/tests/ui/track-diagnostics-clippy.rs @@ -0,0 +1,22 @@ +//@compile-flags: -Z track-diagnostics +//@no-rustfix + +// Normalize the emitted location so this doesn't need +// updating everytime someone adds or removes a line. +//@normalize-stderr-test: ".rs:\d+:\d+" -> ".rs:LL:CC" + +#![warn(clippy::let_and_return, clippy::unnecessary_cast)] + +fn main() { + // Check the provenance of a lint sent through `LintContext::span_lint()` + let a = 3u32; + let b = a as u32; + //~^ unnecessary_cast + + // Check the provenance of a lint sent through `TyCtxt::node_span_lint()` + let c = { + let d = 42; + d + //~^ let_and_return + }; +} diff --git a/src/tools/clippy/tests/ui/track-diagnostics-clippy.stderr b/src/tools/clippy/tests/ui/track-diagnostics-clippy.stderr new file mode 100644 index 00000000000..f3aca685417 --- /dev/null +++ b/src/tools/clippy/tests/ui/track-diagnostics-clippy.stderr @@ -0,0 +1,29 @@ +error: casting to the same type is unnecessary (`u32` -> `u32`) + --> tests/ui/track-diagnostics-clippy.rs:LL:CC + | +LL | let b = a as u32; + | ^^^^^^^^ help: try: `a` +-Ztrack-diagnostics: created at src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs:LL:CC + | + = note: `-D clippy::unnecessary-cast` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::unnecessary_cast)]` + +error: returning the result of a `let` binding from a block + --> tests/ui/track-diagnostics-clippy.rs:LL:CC + | +LL | let d = 42; + | ----------- unnecessary `let` binding +LL | d + | ^ +-Ztrack-diagnostics: created at src/tools/clippy/clippy_lints/src/returns.rs:LL:CC + | + = note: `-D clippy::let-and-return` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::let_and_return)]` +help: return the expression directly + | +LL ~ +LL ~ 42 + | + +error: aborting due to 2 previous errors + diff --git a/src/tools/compiletest/src/directive-list.rs b/src/tools/compiletest/src/directive-list.rs index 2ecb4fc8652..adf2a7bffef 100644 --- a/src/tools/compiletest/src/directive-list.rs +++ b/src/tools/compiletest/src/directive-list.rs @@ -1,6 +1,6 @@ /// This was originally generated by collecting directives from ui tests and then extracting their /// directive names. This is **not** an exhaustive list of all possible directives. Instead, this is -/// a best-effort approximation for diagnostics. Add new headers to this list when needed. +/// a best-effort approximation for diagnostics. Add new directives to this list when needed. const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ // tidy-alphabetical-start "add-core-stubs", diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/directives.rs index 5636a146b0f..a6242cf0c22 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/directives.rs @@ -11,10 +11,10 @@ use tracing::*; use crate::common::{Config, Debugger, FailMode, Mode, PassMode}; use crate::debuggers::{extract_cdb_version, extract_gdb_version}; +use crate::directives::auxiliary::{AuxProps, parse_and_update_aux}; +use crate::directives::needs::CachedNeedsConditions; use crate::errors::ErrorKind; use crate::executor::{CollectedTestDesc, ShouldPanic}; -use crate::header::auxiliary::{AuxProps, parse_and_update_aux}; -use crate::header::needs::CachedNeedsConditions; use crate::help; use crate::util::static_regex; @@ -24,11 +24,11 @@ mod needs; #[cfg(test)] mod tests; -pub struct HeadersCache { +pub struct DirectivesCache { needs: CachedNeedsConditions, } -impl HeadersCache { +impl DirectivesCache { pub fn load(config: &Config) -> Self { Self { needs: CachedNeedsConditions::load(config) } } @@ -54,7 +54,7 @@ impl EarlyProps { pub fn from_reader<R: Read>(config: &Config, testfile: &Utf8Path, rdr: R) -> Self { let mut props = EarlyProps::default(); let mut poisoned = false; - iter_header( + iter_directives( config.mode, &config.suite, &mut poisoned, @@ -138,12 +138,12 @@ pub struct TestProps { pub incremental_dir: Option<Utf8PathBuf>, // If `true`, this test will use incremental compilation. // - // This can be set manually with the `incremental` header, or implicitly + // This can be set manually with the `incremental` directive, or implicitly // by being a part of an incremental mode test. Using the `incremental` - // header should be avoided if possible; using an incremental mode test is + // directive should be avoided if possible; using an incremental mode test is // preferred. Incremental mode tests support multiple passes, which can // verify that the incremental cache can be loaded properly after being - // created. Just setting the header will only verify the behavior with + // created. Just setting the directive will only verify the behavior with // creating an incremental cache, but doesn't check that it is created // correctly. // @@ -347,7 +347,7 @@ impl TestProps { let mut poisoned = false; - iter_header( + iter_directives( config.mode, &config.suite, &mut poisoned, @@ -642,11 +642,11 @@ impl TestProps { let check_ui = |mode: &str| { // Mode::Crashes may need build-fail in order to trigger llvm errors or stack overflows if config.mode != Mode::Ui && config.mode != Mode::Crashes { - panic!("`{}-fail` header is only supported in UI tests", mode); + panic!("`{}-fail` directive is only supported in UI tests", mode); } }; if config.mode == Mode::Ui && config.parse_name_directive(ln, "compile-fail") { - panic!("`compile-fail` header is useless in UI tests"); + panic!("`compile-fail` directive is useless in UI tests"); } let fail_mode = if config.parse_name_directive(ln, "check-fail") { check_ui("check"); @@ -662,7 +662,7 @@ impl TestProps { }; match (self.fail_mode, fail_mode) { (None, Some(_)) => self.fail_mode = fail_mode, - (Some(_), Some(_)) => panic!("multiple `*-fail` headers in a single test"), + (Some(_), Some(_)) => panic!("multiple `*-fail` directives in a single test"), (_, None) => {} } } @@ -674,10 +674,10 @@ impl TestProps { (Mode::Codegen, "build-pass") => (), (Mode::Incremental, _) => { if revision.is_some() && !self.revisions.iter().all(|r| r.starts_with("cfail")) { - panic!("`{s}` header is only supported in `cfail` incremental tests") + panic!("`{s}` directive is only supported in `cfail` incremental tests") } } - (mode, _) => panic!("`{s}` header is not supported in `{mode}` tests"), + (mode, _) => panic!("`{s}` directive is not supported in `{mode}` tests"), }; let pass_mode = if config.parse_name_directive(ln, "check-pass") { check_no_run("check-pass"); @@ -693,7 +693,7 @@ impl TestProps { }; match (self.pass_mode, pass_mode) { (None, Some(_)) => self.pass_mode = pass_mode, - (Some(_), Some(_)) => panic!("multiple `*-pass` headers in a single test"), + (Some(_), Some(_)) => panic!("multiple `*-pass` directives in a single test"), (_, None) => {} } } @@ -794,7 +794,7 @@ const KNOWN_JSONDOCCK_DIRECTIVE_NAMES: &[&str] = &["count", "!count", "has", "!has", "is", "!is", "ismany", "!ismany", "set", "!set"]; /// The (partly) broken-down contents of a line containing a test directive, -/// which [`iter_header`] passes to its callback function. +/// which [`iter_directives`] passes to its callback function. /// /// For example: /// @@ -867,7 +867,7 @@ pub(crate) fn check_directive<'a>( const COMPILETEST_DIRECTIVE_PREFIX: &str = "//@"; -fn iter_header( +fn iter_directives( mode: Mode, _suite: &str, poisoned: &mut bool, @@ -1163,8 +1163,7 @@ enum NormalizeKind { Stderr64bit, } -/// Parses the regex and replacement values of a `//@ normalize-*` header, -/// in the format: +/// Parses the regex and replacement values of a `//@ normalize-*` directive, in the format: /// ```text /// "REGEX" -> "REPLACEMENT" /// ``` @@ -1373,7 +1372,7 @@ where pub(crate) fn make_test_description<R: Read>( config: &Config, - cache: &HeadersCache, + cache: &DirectivesCache, name: String, path: &Utf8Path, src: R, @@ -1387,7 +1386,7 @@ pub(crate) fn make_test_description<R: Read>( let mut local_poisoned = false; // Scan through the test file to handle `ignore-*`, `only-*`, and `needs-*` directives. - iter_header( + iter_directives( config.mode, &config.suite, &mut local_poisoned, diff --git a/src/tools/compiletest/src/header/auxiliary.rs b/src/tools/compiletest/src/directives/auxiliary.rs index 0e1f3a785f8..cdb75f6ffa9 100644 --- a/src/tools/compiletest/src/header/auxiliary.rs +++ b/src/tools/compiletest/src/directives/auxiliary.rs @@ -3,8 +3,8 @@ use std::iter; +use super::directives::{AUX_BIN, AUX_BUILD, AUX_CODEGEN_BACKEND, AUX_CRATE, PROC_MACRO}; use crate::common::Config; -use crate::header::directives::{AUX_BIN, AUX_BUILD, AUX_CODEGEN_BACKEND, AUX_CRATE, PROC_MACRO}; /// Properties parsed from `aux-*` test directives. #[derive(Clone, Debug, Default)] diff --git a/src/tools/compiletest/src/header/cfg.rs b/src/tools/compiletest/src/directives/cfg.rs index f1f1384afb9..35f6a9e1644 100644 --- a/src/tools/compiletest/src/header/cfg.rs +++ b/src/tools/compiletest/src/directives/cfg.rs @@ -1,7 +1,7 @@ use std::collections::HashSet; use crate::common::{CompareMode, Config, Debugger}; -use crate::header::IgnoreDecision; +use crate::directives::IgnoreDecision; const EXTRA_ARCHS: &[&str] = &["spirv"]; diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/directives/needs.rs index b1165f4bb18..ee46f4c70cb 100644 --- a/src/tools/compiletest/src/header/needs.rs +++ b/src/tools/compiletest/src/directives/needs.rs @@ -1,5 +1,5 @@ use crate::common::{Config, KNOWN_CRATE_TYPES, KNOWN_TARGET_HAS_ATOMIC_WIDTHS, Sanitizer}; -use crate::header::{IgnoreDecision, llvm_has_libzstd}; +use crate::directives::{IgnoreDecision, llvm_has_libzstd}; pub(super) fn handle_needs( cache: &CachedNeedsConditions, diff --git a/src/tools/compiletest/src/header/test-auxillary/error_annotation.rs b/src/tools/compiletest/src/directives/test-auxillary/error_annotation.rs index fea66a5e07b..fea66a5e07b 100644 --- a/src/tools/compiletest/src/header/test-auxillary/error_annotation.rs +++ b/src/tools/compiletest/src/directives/test-auxillary/error_annotation.rs diff --git a/src/tools/compiletest/src/header/test-auxillary/known_directive.rs b/src/tools/compiletest/src/directives/test-auxillary/known_directive.rs index 99834b14c1e..99834b14c1e 100644 --- a/src/tools/compiletest/src/header/test-auxillary/known_directive.rs +++ b/src/tools/compiletest/src/directives/test-auxillary/known_directive.rs diff --git a/src/tools/compiletest/src/header/test-auxillary/not_rs.Makefile b/src/tools/compiletest/src/directives/test-auxillary/not_rs.Makefile index 4b565e0e6df..4b565e0e6df 100644 --- a/src/tools/compiletest/src/header/test-auxillary/not_rs.Makefile +++ b/src/tools/compiletest/src/directives/test-auxillary/not_rs.Makefile diff --git a/src/tools/compiletest/src/header/test-auxillary/unknown_directive.rs b/src/tools/compiletest/src/directives/test-auxillary/unknown_directive.rs index d4406031043..d4406031043 100644 --- a/src/tools/compiletest/src/header/test-auxillary/unknown_directive.rs +++ b/src/tools/compiletest/src/directives/test-auxillary/unknown_directive.rs diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/directives/tests.rs index 31b49b09bcd..d4570f82677 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/directives/tests.rs @@ -4,7 +4,7 @@ use camino::Utf8Path; use semver::Version; use super::{ - EarlyProps, HeadersCache, extract_llvm_version, extract_version_range, iter_header, + DirectivesCache, EarlyProps, extract_llvm_version, extract_version_range, iter_directives, parse_normalize_rule, }; use crate::common::{Config, Debugger, Mode}; @@ -17,9 +17,9 @@ fn make_test_description<R: Read>( src: R, revision: Option<&str>, ) -> CollectedTestDesc { - let cache = HeadersCache::load(config); + let cache = DirectivesCache::load(config); let mut poisoned = false; - let test = crate::header::make_test_description( + let test = crate::directives::make_test_description( config, &cache, name, @@ -785,7 +785,7 @@ fn threads_support() { fn run_path(poisoned: &mut bool, path: &Utf8Path, buf: &[u8]) { let rdr = std::io::Cursor::new(&buf); - iter_header(Mode::Ui, "ui", poisoned, path, rdr, &mut |_| {}); + iter_directives(Mode::Ui, "ui", poisoned, path, rdr, &mut |_| {}); } #[test] diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 09de3eb4c70..dfce4b8b408 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -12,9 +12,9 @@ pub mod common; pub mod compute_diff; mod debuggers; pub mod diagnostics; +pub mod directives; pub mod errors; mod executor; -pub mod header; mod json; mod raise_fd_limit; mod read2; @@ -37,13 +37,13 @@ use rayon::iter::{ParallelBridge, ParallelIterator}; use tracing::debug; use walkdir::WalkDir; -use self::header::{EarlyProps, make_test_description}; +use self::directives::{EarlyProps, make_test_description}; use crate::common::{ CompareMode, Config, Debugger, Mode, PassMode, TestPaths, UI_EXTENSIONS, expected_output_path, output_base_dir, output_relative_path, }; +use crate::directives::DirectivesCache; use crate::executor::{CollectedTest, ColorConfig, OutputFormat}; -use crate::header::HeadersCache; use crate::util::logv; /// Creates the `Config` instance for this invocation of compiletest. @@ -254,8 +254,8 @@ pub fn parse_config(args: Vec<String>) -> Config { Some(x) => panic!("argument for --color must be auto, always, or never, but found `{}`", x), }; let llvm_version = - matches.opt_str("llvm-version").as_deref().map(header::extract_llvm_version).or_else( - || header::extract_llvm_version_from_binary(&matches.opt_str("llvm-filecheck")?), + matches.opt_str("llvm-version").as_deref().map(directives::extract_llvm_version).or_else( + || directives::extract_llvm_version_from_binary(&matches.opt_str("llvm-filecheck")?), ); let run_ignored = matches.opt_present("ignored"); @@ -618,7 +618,7 @@ pub fn run_tests(config: Arc<Config>) { /// Read-only context data used during test collection. struct TestCollectorCx { config: Arc<Config>, - cache: HeadersCache, + cache: DirectivesCache, common_inputs_stamp: Stamp, modified_tests: Vec<Utf8PathBuf>, } @@ -654,7 +654,7 @@ pub(crate) fn collect_and_make_tests(config: Arc<Config>) -> Vec<CollectedTest> modified_tests(&config, &config.src_test_suite_root).unwrap_or_else(|err| { fatal!("modified_tests: {}: {err}", config.src_test_suite_root); }); - let cache = HeadersCache::load(&config); + let cache = DirectivesCache::load(&config); let cx = TestCollectorCx { config, cache, common_inputs_stamp, modified_tests }; let collector = collect_tests_from_dir(&cx, &cx.config.src_test_suite_root, Utf8Path::new("")) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 53b5990d3cd..f8bf4ee3022 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -23,8 +23,8 @@ use crate::common::{ output_base_dir, output_base_name, output_testname_unique, }; use crate::compute_diff::{DiffLine, make_diff, write_diff, write_filtered_diff}; +use crate::directives::TestProps; use crate::errors::{Error, ErrorKind, load_errors}; -use crate::header::TestProps; use crate::read2::{Truncated, read2_abbreviated}; use crate::util::{Utf8PathBufExt, add_dylib_path, logv, static_regex}; use crate::{ColorConfig, help, json, stamp_file_path, warning}; @@ -2039,7 +2039,7 @@ impl<'test> TestCx<'test> { // Provide more context on failures. filecheck.args(&["--dump-input-context", "100"]); - // Add custom flags supplied by the `filecheck-flags:` test header. + // Add custom flags supplied by the `filecheck-flags:` test directive. filecheck.args(&self.props.filecheck_flags); // FIXME(jieyouxu): don't pass an empty Path diff --git a/src/tools/compiletest/src/runtest/debuginfo.rs b/src/tools/compiletest/src/runtest/debuginfo.rs index 31240dff9a1..d9e1e4dfc8d 100644 --- a/src/tools/compiletest/src/runtest/debuginfo.rs +++ b/src/tools/compiletest/src/runtest/debuginfo.rs @@ -49,7 +49,7 @@ impl TestCx<'_> { std::fs::remove_file(pdb_file).unwrap(); } - // compile test file (it should have 'compile-flags:-g' in the header) + // compile test file (it should have 'compile-flags:-g' in the directive) let should_run = self.run_if_enabled(); let compile_result = self.compile_test(should_run, Emit::None); if !compile_result.status.success() { @@ -135,7 +135,7 @@ impl TestCx<'_> { .unwrap_or_else(|e| self.fatal(&e)); let mut cmds = dbg_cmds.commands.join("\n"); - // compile test file (it should have 'compile-flags:-g' in the header) + // compile test file (it should have 'compile-flags:-g' in the directive) let should_run = self.run_if_enabled(); let compiler_run_result = self.compile_test(should_run, Emit::None); if !compiler_run_result.status.success() { @@ -359,7 +359,7 @@ impl TestCx<'_> { } fn run_debuginfo_lldb_test_no_opt(&self) { - // compile test file (it should have 'compile-flags:-g' in the header) + // compile test file (it should have 'compile-flags:-g' in the directive) let should_run = self.run_if_enabled(); let compile_result = self.compile_test(should_run, Emit::None); if !compile_result.status.success() { diff --git a/src/tools/compiletest/src/runtest/ui.rs b/src/tools/compiletest/src/runtest/ui.rs index cc50a918f75..f6bc85cd051 100644 --- a/src/tools/compiletest/src/runtest/ui.rs +++ b/src/tools/compiletest/src/runtest/ui.rs @@ -52,10 +52,10 @@ impl TestCx<'_> { // don't test rustfix with nll right now } else if self.config.rustfix_coverage { // Find out which tests have `MachineApplicable` suggestions but are missing - // `run-rustfix` or `run-rustfix-only-machine-applicable` headers. + // `run-rustfix` or `run-rustfix-only-machine-applicable` directives. // // This will return an empty `Vec` in case the executed test file has a - // `compile-flags: --error-format=xxxx` header with a value other than `json`. + // `compile-flags: --error-format=xxxx` directive with a value other than `json`. let suggestions = get_suggestions_from_json( &rustfix_input, &HashSet::new(), diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs index 1796120cf8a..3cc38fa087c 100644 --- a/src/tools/miri/src/alloc_addresses/mod.rs +++ b/src/tools/miri/src/alloc_addresses/mod.rs @@ -466,17 +466,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Some((alloc_id, Size::from_bytes(rel_offset))) } - /// Prepare all exposed memory for a native call. - /// This overapproximates the modifications which external code might make to memory: - /// We set all reachable allocations as initialized, mark all reachable provenances as exposed - /// and overwrite them with `Provenance::WILDCARD`. - fn prepare_exposed_for_native_call(&mut self) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); - // We need to make a deep copy of this list, but it's fine; it also serves as scratch space - // for the search within `prepare_for_native_call`. - let exposed: Vec<AllocId> = - this.machine.alloc_addresses.get_mut().exposed.iter().copied().collect(); - this.prepare_for_native_call(exposed) + /// Return a list of all exposed allocations. + fn exposed_allocs(&self) -> Vec<AllocId> { + let this = self.eval_context_ref(); + this.machine.alloc_addresses.borrow().exposed.iter().copied().collect() } } diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs index ed1851a19ae..4efa7dd4dcf 100644 --- a/src/tools/miri/src/intrinsics/mod.rs +++ b/src/tools/miri/src/intrinsics/mod.rs @@ -457,6 +457,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { throw_machine_stop!(TerminationInfo::Abort(format!("trace/breakpoint trap"))) } + "assert_inhabited" | "assert_zero_valid" | "assert_mem_uninitialized_valid" => { + // Make these a NOP, so we get the better Miri-native error messages. + } + _ => return interp_ok(EmulateItemResult::NotSupported), } diff --git a/src/tools/miri/src/shims/backtrace.rs b/src/tools/miri/src/shims/backtrace.rs index dd00b270b38..18d60915d20 100644 --- a/src/tools/miri/src/shims/backtrace.rs +++ b/src/tools/miri/src/shims/backtrace.rs @@ -104,7 +104,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.tcx.sess.source_map().lookup_char_pos(BytePos(offset.bytes().try_into().unwrap())); let name = fn_instance.to_string(); - let filename = lo.file.name.prefer_remapped_unconditionaly().to_string(); + let filename = lo.file.name.prefer_remapped_unconditionally().to_string(); interp_ok((fn_instance, lo, name, filename)) } diff --git a/src/tools/miri/src/shims/native_lib/mod.rs b/src/tools/miri/src/shims/native_lib/mod.rs index 9c659f65e50..9b30d8ce78b 100644 --- a/src/tools/miri/src/shims/native_lib/mod.rs +++ b/src/tools/miri/src/shims/native_lib/mod.rs @@ -198,7 +198,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let mut libffi_args = Vec::<CArg>::with_capacity(args.len()); for arg in args.iter() { if !matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) { - throw_unsup_format!("only scalar argument types are support for native calls") + throw_unsup_format!("only scalar argument types are supported for native calls") } let imm = this.read_immediate(arg)?; libffi_args.push(imm_to_carg(&imm, this)?); @@ -224,16 +224,42 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.expose_provenance(prov)?; } } - - // Prepare all exposed memory. - this.prepare_exposed_for_native_call()?; - - // Convert them to `libffi::high::Arg` type. + // Convert arguments to `libffi::high::Arg` type. let libffi_args = libffi_args .iter() .map(|arg| arg.arg_downcast()) .collect::<Vec<libffi::high::Arg<'_>>>(); + // Prepare all exposed memory (both previously exposed, and just newly exposed since a + // pointer was passed as argument). + this.visit_reachable_allocs(this.exposed_allocs(), |this, alloc_id, info| { + // If there is no data behind this pointer, skip this. + if !matches!(info.kind, AllocKind::LiveData) { + return interp_ok(()); + } + // It's okay to get raw access, what we do does not correspond to any actual + // AM operation, it just approximates the state to account for the native call. + let alloc = this.get_alloc_raw(alloc_id)?; + // Also expose the provenance of the interpreter-level allocation, so it can + // be read by FFI. The `black_box` is defensive programming as LLVM likes + // to (incorrectly) optimize away ptr2int casts whose result is unused. + std::hint::black_box(alloc.get_bytes_unchecked_raw().expose_provenance()); + // Expose all provenances in this allocation, since the native code can do $whatever. + for prov in alloc.provenance().provenances() { + this.expose_provenance(prov)?; + } + + // Prepare for possible write from native code if mutable. + if info.mutbl.is_mut() { + let alloc = &mut this.get_alloc_raw_mut(alloc_id)?.0; + alloc.prepare_for_native_access(); + // Also expose *mutable* provenance for the interpreter-level allocation. + std::hint::black_box(alloc.get_bytes_unchecked_raw_mut().expose_provenance()); + } + + interp_ok(()) + })?; + // Call the function and store output, depending on return type in the function signature. let (ret, maybe_memevents) = this.call_native_with_args(link_name, dest, code_ptr, libffi_args)?; @@ -321,7 +347,8 @@ fn imm_to_carg<'tcx>(v: &ImmTy<'tcx>, cx: &impl HasDataLayout) -> InterpResult<' CArg::USize(v.to_scalar().to_target_usize(cx)?.try_into().unwrap()), ty::RawPtr(..) => { let s = v.to_scalar().to_pointer(cx)?.addr(); - // This relies on the `expose_provenance` in `prepare_for_native_call`. + // This relies on the `expose_provenance` in the `visit_reachable_allocs` callback + // above. CArg::RawPtr(std::ptr::with_exposed_provenance_mut(s.bytes_usize())) } _ => throw_unsup_format!("unsupported argument type for native call: {}", v.layout.ty), diff --git a/src/tools/miri/tests/fail-dep/libc/libc-read-and-uninit-premature-eof.rs b/src/tools/miri/tests/fail-dep/libc/libc-read-and-uninit-premature-eof.rs index dd2dd346231..1dc334486c3 100644 --- a/src/tools/miri/tests/fail-dep/libc/libc-read-and-uninit-premature-eof.rs +++ b/src/tools/miri/tests/fail-dep/libc/libc-read-and-uninit-premature-eof.rs @@ -20,7 +20,7 @@ fn main() { let mut buf: MaybeUninit<[u8; 4]> = std::mem::MaybeUninit::uninit(); // Read 4 bytes from a 3-byte file. assert_eq!(libc::read(fd, buf.as_mut_ptr().cast::<std::ffi::c_void>(), 4), 3); - buf.assume_init(); //~ERROR: Undefined Behavior: constructing invalid value at .value[3]: encountered uninitialized memory, but expected an integer + buf.assume_init(); //~ERROR: encountered uninitialized memory, but expected an integer assert_eq!(libc::close(fd), 0); } remove_file(&path).unwrap(); diff --git a/src/tools/miri/tests/fail-dep/libc/libc-read-and-uninit-premature-eof.stderr b/src/tools/miri/tests/fail-dep/libc/libc-read-and-uninit-premature-eof.stderr index fadb31e3a8f..83119f087ff 100644 --- a/src/tools/miri/tests/fail-dep/libc/libc-read-and-uninit-premature-eof.stderr +++ b/src/tools/miri/tests/fail-dep/libc/libc-read-and-uninit-premature-eof.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: constructing invalid value at .value[3]: encountered uninitialized memory, but expected an integer +error: Undefined Behavior: constructing invalid value at [3]: encountered uninitialized memory, but expected an integer --> tests/fail-dep/libc/libc-read-and-uninit-premature-eof.rs:LL:CC | -LL | ... buf.assume_init(); - | ^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here +LL | buf.assume_init(); + | ^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.rs b/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.rs index dd3246d8120..34fef6b9ee5 100644 --- a/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.rs +++ b/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.rs @@ -1,11 +1,6 @@ -//@normalize-stderr-test: "\|.*::abort\(\).*" -> "| ABORT()" -//@normalize-stderr-test: "\| +\^+" -> "| ^" -//@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "" -//@normalize-stderr-test: "\n +at [^\n]+" -> "" -//@error-in-other-file: aborted execution #![feature(never_type)] #[allow(deprecated, invalid_value)] fn main() { - let _ = unsafe { std::mem::uninitialized::<!>() }; + let _ = unsafe { std::mem::uninitialized::<!>() }; //~ERROR: constructing invalid value } 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 3db8a5be205..36642208afe 100644 --- a/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr +++ b/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr @@ -1,27 +1,13 @@ - -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 `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 - | -LL | ABORT() - | ^ abnormal termination occurred here - | - = note: BACKTRACE: - = note: inside `std::sys::pal::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC - = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC - = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC - = note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC - = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC - = note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC -note: inside `main` +error: Undefined Behavior: constructing invalid value: encountered a value of the never type `!` --> tests/fail/intrinsics/uninit_uninhabited_type.rs:LL:CC | LL | let _ = unsafe { std::mem::uninitialized::<!>() }; - | ^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here + | + = 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 tests/fail/intrinsics/uninit_uninhabited_type.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.rs b/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.rs index 3d355bad626..cca2c5ae984 100644 --- a/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.rs +++ b/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.rs @@ -1,10 +1,4 @@ -//@normalize-stderr-test: "\|.*::abort\(\).*" -> "| ABORT()" -//@normalize-stderr-test: "\| +\^+" -> "| ^" -//@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "" -//@normalize-stderr-test: "\n +at [^\n]+" -> "" -//@error-in-other-file: aborted execution - #[allow(deprecated, invalid_value)] fn main() { - let _ = unsafe { std::mem::zeroed::<fn()>() }; + let _ = unsafe { std::mem::zeroed::<fn()>() }; //~ERROR: constructing invalid value } 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 a1e476328b0..53f3f8d1404 100644 --- a/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr +++ b/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr @@ -1,27 +1,13 @@ - -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 `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 - | -LL | ABORT() - | ^ abnormal termination occurred here - | - = note: BACKTRACE: - = note: inside `std::sys::pal::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC - = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC - = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC - = note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC - = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC - = note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC -note: inside `main` +error: Undefined Behavior: constructing invalid value: encountered a null function pointer --> tests/fail/intrinsics/zero_fn_ptr.rs:LL:CC | LL | let _ = unsafe { std::mem::zeroed::<fn()>() }; - | ^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here + | + = 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 tests/fail/intrinsics/zero_fn_ptr.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/validity/uninit_float.stderr b/src/tools/miri/tests/fail/validity/uninit_float.stderr index 1b948b062e1..0c859d72764 100644 --- a/src/tools/miri/tests/fail/validity/uninit_float.stderr +++ b/src/tools/miri/tests/fail/validity/uninit_float.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: constructing invalid value at .value[0]: encountered uninitialized memory, but expected a floating point number +error: Undefined Behavior: constructing invalid value at [0]: encountered uninitialized memory, but expected a floating point number --> tests/fail/validity/uninit_float.rs:LL:CC | LL | let _val: [f32; 1] = unsafe { std::mem::uninitialized() }; diff --git a/src/tools/miri/tests/fail/validity/uninit_integer.stderr b/src/tools/miri/tests/fail/validity/uninit_integer.stderr index b17bdee65da..5d31e2659ee 100644 --- a/src/tools/miri/tests/fail/validity/uninit_integer.stderr +++ b/src/tools/miri/tests/fail/validity/uninit_integer.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: constructing invalid value at .value[0]: encountered uninitialized memory, but expected an integer +error: Undefined Behavior: constructing invalid value at [0]: encountered uninitialized memory, but expected an integer --> tests/fail/validity/uninit_integer.rs:LL:CC | LL | let _val = unsafe { std::mem::MaybeUninit::<[usize; 1]>::uninit().assume_init() }; diff --git a/src/tools/miri/tests/fail/validity/uninit_raw_ptr.stderr b/src/tools/miri/tests/fail/validity/uninit_raw_ptr.stderr index 269af6061c2..d2e9408adbe 100644 --- a/src/tools/miri/tests/fail/validity/uninit_raw_ptr.stderr +++ b/src/tools/miri/tests/fail/validity/uninit_raw_ptr.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: constructing invalid value at .value[0]: encountered uninitialized memory, but expected a raw pointer +error: Undefined Behavior: constructing invalid value at [0]: encountered uninitialized memory, but expected a raw pointer --> tests/fail/validity/uninit_raw_ptr.rs:LL:CC | LL | let _val = unsafe { std::mem::MaybeUninit::<[*const u8; 1]>::uninit().assume_init() }; diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock index 7bf3bb195ee..aeae5b61b95 100644 --- a/src/tools/rustbook/Cargo.lock +++ b/src/tools/rustbook/Cargo.lock @@ -81,7 +81,7 @@ version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" dependencies = [ - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -92,7 +92,7 @@ checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -103,9 +103,9 @@ checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" [[package]] name = "autocfg" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "bincode" @@ -150,9 +150,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.18.1" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "cc" @@ -459,12 +459,12 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" +checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.60.2", ] [[package]] @@ -746,9 +746,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" +checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" dependencies = [ "equivalent", "hashbrown", @@ -863,9 +863,9 @@ checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" [[package]] name = "markup5ever" -version = "0.16.1" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a8096766c229e8c88a3900c9b44b7e06aa7f7343cc229158c3e58ef8f9973a" +checksum = "2e4cd8c02f18a011991a039855480c64d74291c5792fcc160d55d77dc4de4a39" dependencies = [ "log", "tendril", @@ -991,7 +991,7 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8911957c4b1549ac0dc74e30db9c8b0e66ddcd6d7acc33098f4c63a64a6d7ed" dependencies = [ - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -1060,7 +1060,7 @@ checksum = "771b9704f8cd8b424ec747a320b30b47517a6966ba2c7da90047c16f4a962223" dependencies = [ "bstr", "normpath", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -1083,7 +1083,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -1100,9 +1100,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.8.0" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "198db74531d58c70a361c42201efde7e2591e976d518caf7662a47dc5720e7b6" +checksum = "1db05f56d34358a8b1066f67cbb203ee3e7ed2ba674a6263a1d5ec6db2204323" dependencies = [ "memchr", "thiserror 2.0.12", @@ -1111,9 +1111,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.8.0" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d725d9cfd79e87dccc9341a2ef39d1b6f6353d68c4b33c177febbe1a402c97c5" +checksum = "bb056d9e8ea77922845ec74a1c4e8fb17e7c218cc4fc11a15c5d25e189aa40bc" dependencies = [ "pest", "pest_generator", @@ -1121,9 +1121,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.8.0" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db7d01726be8ab66ab32f9df467ae8b1148906685bbe75c82d1e65d7f5b3f841" +checksum = "87e404e638f781eb3202dc82db6760c8ae8a1eeef7fb3fa8264b2ef280504966" dependencies = [ "pest", "pest_meta", @@ -1134,11 +1134,10 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.8.0" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9f832470494906d1fca5329f8ab5791cc60beb230c74815dff541cbd2b5ca0" +checksum = "edd1101f170f5903fde0914f899bb503d9ff5271d7ba76bbb70bea63690cc0d5" dependencies = [ - "once_cell", "pest", "sha2", ] @@ -1315,9 +1314,9 @@ dependencies = [ [[package]] name = "r-efi" -version = "5.2.0" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "railroad" @@ -1403,7 +1402,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -1548,9 +1547,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.103" +version = "2.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4307e30089d6fd6aff212f2da3a1f9e32f3223b1f010fb09b7c95f90f3ca1e8" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" dependencies = [ "proc-macro2", "quote", @@ -1598,7 +1597,7 @@ dependencies = [ "getrandom", "once_cell", "rustix", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -1619,7 +1618,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45c6481c4829e4cc63825e62c49186a34538b7b2750b73b266581ffb612fb5ed" dependencies = [ "rustix", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -1894,7 +1893,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -1962,7 +1961,16 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.2", ] [[package]] @@ -1971,14 +1979,30 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "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]] +name = "windows-targets" +version = "0.53.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", ] [[package]] @@ -1988,48 +2012,96 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + +[[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + +[[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + +[[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + +[[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + +[[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + +[[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + +[[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + +[[package]] name = "winnow" version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/src/tools/rustdoc-gui-test/src/main.rs b/src/tools/rustdoc-gui-test/src/main.rs index addb0af4a54..6461f38f527 100644 --- a/src/tools/rustdoc-gui-test/src/main.rs +++ b/src/tools/rustdoc-gui-test/src/main.rs @@ -4,7 +4,7 @@ use std::sync::Arc; use std::{env, fs}; use build_helper::util::try_run; -use compiletest::header::TestProps; +use compiletest::directives::TestProps; use config::Config; mod config; diff --git a/src/tools/rustdoc-gui/tester.js b/src/tools/rustdoc-gui/tester.js index ff87b76aa45..9dc32f335a8 100644 --- a/src/tools/rustdoc-gui/tester.js +++ b/src/tools/rustdoc-gui/tester.js @@ -196,7 +196,7 @@ async function main(argv) { // This is more convenient that setting fields one by one. const args = [ "--variable", "DOC_PATH", opts["doc_folder"].split("\\").join("/"), - "--enable-fail-on-js-error", "--allow-file-access-from-files", + "--allow-file-access-from-files", ]; if (opts["debug"]) { debug = true; diff --git a/src/tools/rustfmt/tests/source/let_chains.rs b/src/tools/rustfmt/tests/source/let_chains.rs index 0c4d8aa85ea..fc2a9310569 100644 --- a/src/tools/rustfmt/tests/source/let_chains.rs +++ b/src/tools/rustfmt/tests/source/let_chains.rs @@ -1,3 +1,5 @@ +// rustfmt-edition: 2024 + fn main() { if let x = x && x {} diff --git a/src/tools/rustfmt/tests/target/let_chains.rs b/src/tools/rustfmt/tests/target/let_chains.rs index 204937b4cac..4fd6048d914 100644 --- a/src/tools/rustfmt/tests/target/let_chains.rs +++ b/src/tools/rustfmt/tests/target/let_chains.rs @@ -1,3 +1,5 @@ +// rustfmt-edition: 2024 + fn main() { if let x = x && x diff --git a/src/tools/tidy/src/ext_tool_checks.rs b/src/tools/tidy/src/ext_tool_checks.rs index 4f9a20fa9e2..2904908fd43 100644 --- a/src/tools/tidy/src/ext_tool_checks.rs +++ b/src/tools/tidy/src/ext_tool_checks.rs @@ -72,6 +72,8 @@ fn check_impl( let shell_lint = lint_args.contains(&"shell:lint") || shell_all; let cpp_all = lint_args.contains(&"cpp"); let cpp_fmt = lint_args.contains(&"cpp:fmt") || cpp_all; + let spellcheck_all = lint_args.contains(&"spellcheck"); + let spellcheck_fix = lint_args.contains(&"spellcheck:fix"); let mut py_path = None; @@ -224,6 +226,27 @@ fn check_impl( shellcheck_runner(&merge_args(&cfg_args, &file_args_shc))?; } + if spellcheck_all || spellcheck_fix { + let config_path = root_path.join("typos.toml"); + // sync target files with .github/workflows/spellcheck.yml + let mut args = vec![ + "-c", + config_path.as_os_str().to_str().unwrap(), + "./compiler", + "./library", + "./src/bootstrap", + "./src/librustdoc", + ]; + + if spellcheck_all { + eprintln!("spellcheck files"); + } else if spellcheck_fix { + eprintln!("spellcheck files and fix"); + args.push("--write-changes"); + } + spellcheck_runner(&args)?; + } + Ok(()) } @@ -491,6 +514,36 @@ fn shellcheck_runner(args: &[&OsStr]) -> Result<(), Error> { if status.success() { Ok(()) } else { Err(Error::FailedCheck("shellcheck")) } } +/// Check that spellchecker is installed then run it at the given path +fn spellcheck_runner(args: &[&str]) -> Result<(), Error> { + // sync version with .github/workflows/spellcheck.yml + let expected_version = "typos-cli 1.34.0"; + match Command::new("typos").arg("--version").output() { + Ok(o) => { + let stdout = String::from_utf8_lossy(&o.stdout); + if stdout.trim() != expected_version { + return Err(Error::Version { + program: "typos", + required: expected_version, + installed: stdout.trim().to_string(), + }); + } + } + Err(e) if e.kind() == io::ErrorKind::NotFound => { + return Err(Error::MissingReq( + "typos", + "spellcheck file checks", + // sync version with .github/workflows/spellcheck.yml + Some("install tool via `cargo install typos-cli@1.34.0`".to_owned()), + )); + } + Err(e) => return Err(e.into()), + } + + let status = Command::new("typos").args(args).status()?; + if status.success() { Ok(()) } else { Err(Error::FailedCheck("typos")) } +} + /// Check git for tracked files matching an extension fn find_with_extension( root_path: &Path, diff --git a/src/tools/tidy/src/rustdoc_js.rs b/src/tools/tidy/src/rustdoc_js.rs index 720f0712ee0..5e924544f0d 100644 --- a/src/tools/tidy/src/rustdoc_js.rs +++ b/src/tools/tidy/src/rustdoc_js.rs @@ -52,8 +52,7 @@ fn get_eslint_version() -> Option<String> { } pub fn check(librustdoc_path: &Path, tools_path: &Path, src_path: &Path, bad: &mut bool) { - let eslint_version_path = - src_path.join("ci/docker/host-x86_64/mingw-check-tidy/eslint.version"); + let eslint_version_path = src_path.join("ci/docker/host-x86_64/tidy/eslint.version"); let eslint_version = match std::fs::read_to_string(&eslint_version_path) { Ok(version) => version.trim().to_string(), Err(error) => { diff --git a/tests/auxiliary/minicore.rs b/tests/auxiliary/minicore.rs index 3e9841b179c..392ad1cee14 100644 --- a/tests/auxiliary/minicore.rs +++ b/tests/auxiliary/minicore.rs @@ -5,7 +5,8 @@ //! # Important notes //! //! - `minicore` is **only** intended for `core` items, and the stubs should match the actual `core` -//! items. +//! items. For identical error output, any `diagnostic` attributes (e.g. `on_unimplemented`) +//! should also be replicated here. //! - Be careful of adding new features and things that are only available for a subset of targets. //! //! # References @@ -41,12 +42,24 @@ macro_rules! impl_marker_trait { } #[lang = "pointee_sized"] +#[diagnostic::on_unimplemented( + message = "values of type `{Self}` may or may not have a size", + label = "may or may not have a known size" +)] pub trait PointeeSized {} #[lang = "meta_sized"] +#[diagnostic::on_unimplemented( + message = "the size for values of type `{Self}` cannot be known", + label = "doesn't have a known size" +)] pub trait MetaSized: PointeeSized {} #[lang = "sized"] +#[diagnostic::on_unimplemented( + message = "the size for values of type `{Self}` cannot be known at compilation time", + label = "doesn't have a size known at compile-time" +)] pub trait Sized: MetaSized {} #[lang = "legacy_receiver"] @@ -64,6 +77,10 @@ pub trait BikeshedGuaranteedNoDrop {} pub unsafe auto trait Freeze {} #[lang = "unpin"] +#[diagnostic::on_unimplemented( + note = "consider using the `pin!` macro\nconsider using `Box::pin` if you need to access the pinned value outside of the current scope", + message = "`{Self}` cannot be unpinned" +)] pub auto trait Unpin {} impl_marker_trait!( @@ -110,6 +127,7 @@ pub struct UnsafeCell<T: PointeeSized> { impl<T: PointeeSized> !Freeze for UnsafeCell<T> {} #[lang = "tuple_trait"] +#[diagnostic::on_unimplemented(message = "`{Self}` is not a tuple")] pub trait Tuple {} #[rustc_builtin_macro] diff --git a/tests/codegen/transmute-scalar.rs b/tests/codegen/transmute-scalar.rs index c57ade58c30..3ac6ba3beb1 100644 --- a/tests/codegen/transmute-scalar.rs +++ b/tests/codegen/transmute-scalar.rs @@ -1,6 +1,12 @@ +//@ add-core-stubs //@ compile-flags: -C opt-level=0 -C no-prepopulate-passes #![crate_type = "lib"] +#![feature(no_core, repr_simd, arm_target_feature, mips_target_feature, s390x_target_feature)] +#![no_core] +extern crate minicore; + +use minicore::*; // With opaque ptrs in LLVM, `transmute` can load/store any `alloca` as any type, // without needing to pointercast, and SRoA will turn that into a `bitcast`. @@ -14,7 +20,7 @@ // CHECK-NEXT: ret i32 %_0 #[no_mangle] pub fn f32_to_bits(x: f32) -> u32 { - unsafe { std::mem::transmute(x) } + unsafe { mem::transmute(x) } } // CHECK-LABEL: define{{.*}}i8 @bool_to_byte(i1 zeroext %b) @@ -22,7 +28,7 @@ pub fn f32_to_bits(x: f32) -> u32 { // CHECK-NEXT: ret i8 %_0 #[no_mangle] pub fn bool_to_byte(b: bool) -> u8 { - unsafe { std::mem::transmute(b) } + unsafe { mem::transmute(b) } } // CHECK-LABEL: define{{.*}}zeroext i1 @byte_to_bool(i8{{.*}} %byte) @@ -30,14 +36,14 @@ pub fn bool_to_byte(b: bool) -> u8 { // CHECK-NEXT: ret i1 %_0 #[no_mangle] pub unsafe fn byte_to_bool(byte: u8) -> bool { - std::mem::transmute(byte) + mem::transmute(byte) } // CHECK-LABEL: define{{.*}}ptr @ptr_to_ptr(ptr %p) // CHECK: ret ptr %p #[no_mangle] pub fn ptr_to_ptr(p: *mut u16) -> *mut u8 { - unsafe { std::mem::transmute(p) } + unsafe { mem::transmute(p) } } // CHECK: define{{.*}}[[USIZE:i[0-9]+]] @ptr_to_int(ptr %p) @@ -45,7 +51,7 @@ pub fn ptr_to_ptr(p: *mut u16) -> *mut u8 { // CHECK-NEXT: ret [[USIZE]] %_0 #[no_mangle] pub fn ptr_to_int(p: *mut u16) -> usize { - unsafe { std::mem::transmute(p) } + unsafe { mem::transmute(p) } } // CHECK: define{{.*}}ptr @int_to_ptr([[USIZE]] %i) @@ -53,7 +59,7 @@ pub fn ptr_to_int(p: *mut u16) -> usize { // CHECK-NEXT: ret ptr %_0 #[no_mangle] pub fn int_to_ptr(i: usize) -> *mut u16 { - unsafe { std::mem::transmute(i) } + unsafe { mem::transmute(i) } } // This is the one case where signedness matters to transmuting: @@ -70,7 +76,7 @@ pub enum FakeBoolSigned { // CHECK-NEXT: ret i8 %_0 #[no_mangle] pub fn bool_to_fake_bool_signed(b: bool) -> FakeBoolSigned { - unsafe { std::mem::transmute(b) } + unsafe { mem::transmute(b) } } // CHECK-LABEL: define{{.*}}i1 @fake_bool_signed_to_bool(i8 %b) @@ -78,7 +84,7 @@ pub fn bool_to_fake_bool_signed(b: bool) -> FakeBoolSigned { // CHECK-NEXT: ret i1 %_0 #[no_mangle] pub fn fake_bool_signed_to_bool(b: FakeBoolSigned) -> bool { - unsafe { std::mem::transmute(b) } + unsafe { mem::transmute(b) } } #[repr(u8)] @@ -91,12 +97,41 @@ pub enum FakeBoolUnsigned { // CHECK: ret i1 %b #[no_mangle] pub fn bool_to_fake_bool_unsigned(b: bool) -> FakeBoolUnsigned { - unsafe { std::mem::transmute(b) } + unsafe { mem::transmute(b) } } // CHECK-LABEL: define{{.*}}i1 @fake_bool_unsigned_to_bool(i1 zeroext %b) // CHECK: ret i1 %b #[no_mangle] pub fn fake_bool_unsigned_to_bool(b: FakeBoolUnsigned) -> bool { - unsafe { std::mem::transmute(b) } + unsafe { mem::transmute(b) } +} + +#[repr(simd)] +struct S([i64; 1]); + +// CHECK-LABEL: define{{.*}}i64 @single_element_simd_to_scalar(<1 x i64> %b) +// CHECK: bitcast <1 x i64> %b to i64 +// CHECK: ret i64 +#[no_mangle] +#[cfg_attr(target_family = "wasm", target_feature(enable = "simd128"))] +#[cfg_attr(target_arch = "arm", target_feature(enable = "neon"))] +#[cfg_attr(target_arch = "x86", target_feature(enable = "sse"))] +#[cfg_attr(target_arch = "mips", target_feature(enable = "msa"))] +#[cfg_attr(target_arch = "s390x", target_feature(enable = "vector"))] +pub extern "C" fn single_element_simd_to_scalar(b: S) -> i64 { + unsafe { mem::transmute(b) } +} + +// CHECK-LABEL: define{{.*}}<1 x i64> @scalar_to_single_element_simd(i64 %b) +// CHECK: bitcast i64 %b to <1 x i64> +// CHECK: ret <1 x i64> +#[no_mangle] +#[cfg_attr(target_family = "wasm", target_feature(enable = "simd128"))] +#[cfg_attr(target_arch = "arm", target_feature(enable = "neon"))] +#[cfg_attr(target_arch = "x86", target_feature(enable = "sse"))] +#[cfg_attr(target_arch = "mips", target_feature(enable = "msa"))] +#[cfg_attr(target_arch = "s390x", target_feature(enable = "vector"))] +pub extern "C" fn scalar_to_single_element_simd(b: i64) -> S { + unsafe { mem::transmute(b) } } diff --git a/tests/coverage/branch/if-let.coverage b/tests/coverage/branch/if-let.coverage index 9a3f0113f75..e55da7fb726 100644 --- a/tests/coverage/branch/if-let.coverage +++ b/tests/coverage/branch/if-let.coverage @@ -1,5 +1,5 @@ - LL| |#![feature(coverage_attribute, let_chains)] - LL| |//@ edition: 2021 + LL| |#![feature(coverage_attribute)] + LL| |//@ edition: 2024 LL| |//@ compile-flags: -Zcoverage-options=branch LL| |//@ llvm-cov-flags: --show-branches=count LL| | diff --git a/tests/coverage/branch/if-let.rs b/tests/coverage/branch/if-let.rs index 13db00a82b1..6f88de54cda 100644 --- a/tests/coverage/branch/if-let.rs +++ b/tests/coverage/branch/if-let.rs @@ -1,5 +1,5 @@ -#![feature(coverage_attribute, let_chains)] -//@ edition: 2021 +#![feature(coverage_attribute)] +//@ edition: 2024 //@ compile-flags: -Zcoverage-options=branch //@ llvm-cov-flags: --show-branches=count diff --git a/tests/mir-opt/inline_var_debug_info_kept.rs b/tests/mir-opt/inline_var_debug_info_kept.rs new file mode 100644 index 00000000000..e2f00fc6ee9 --- /dev/null +++ b/tests/mir-opt/inline_var_debug_info_kept.rs @@ -0,0 +1,50 @@ +//@ test-mir-pass: Inline +//@ revisions: PRESERVE FULL NONE LIMITED +//@ [PRESERVE]compile-flags: -O -C debuginfo=0 -Zinline-mir-preserve-debug +//@ [FULL]compile-flags: -O -C debuginfo=2 +//@ [NONE]compile-flags: -O -C debuginfo=0 +//@ [LIMITED]compile-flags: -O -C debuginfo=1 + +#[inline(always)] +fn inline_fn1(arg1: i32) -> i32 { + let local1 = arg1 + 1; + let _local2 = 10; + arg1 + local1 +} + +#[inline(always)] +fn inline_fn2(binding: i32) -> i32 { + { + let binding = inline_fn1(binding); + binding + } +} + +#[inline(never)] +fn test() -> i32 { + // CHECK-LABEL: fn test + inline_fn2(1) + // CHECK-LABEL: (inlined inline_fn2) + + // PRESERVE: debug binding => + // FULL: debug binding => + // NONE-NOT: debug binding => + // LIMITED-NOT: debug binding => + + // CHECK-LABEL: (inlined inline_fn1) + + // PRESERVE: debug arg1 => + // FULL: debug arg1 => + // NONE-NOT: debug arg1 => + // LIMITED-NOT: debug arg1 => + + // PRESERVE: debug local1 => + // FULL: debug local1 => + // NONE-NOT: debug local1 => + // LIMITED-NOT: debug local1 => + + // PRESERVE: debug _local2 => + // FULL: debug _local2 => + // NONE-NOT: debug _local2 => + // LIMITED-NOT: debug _local2 => +} diff --git a/tests/rustdoc-gui/docblock-code-block-line-number.goml b/tests/rustdoc-gui/docblock-code-block-line-number.goml index 97273ceb195..0df9cc2a659 100644 --- a/tests/rustdoc-gui/docblock-code-block-line-number.goml +++ b/tests/rustdoc-gui/docblock-code-block-line-number.goml @@ -129,13 +129,13 @@ define-function: ("check-line-numbers-existence", [], block { wait-for-local-storage-false: {"rustdoc-line-numbers": "true" } assert-false: ".example-line-numbers" // Line numbers should still be there. - assert-css: ("[data-nosnippet]", { "display": "inline-block"}) + assert-css: ("[data-nosnippet]", { "display": "block"}) // Now disabling the setting. click: "input#line-numbers" wait-for-local-storage: {"rustdoc-line-numbers": "true" } assert-false: ".example-line-numbers" // Line numbers should still be there. - assert-css: ("[data-nosnippet]", { "display": "inline-block"}) + assert-css: ("[data-nosnippet]", { "display": "block"}) // Closing settings menu. click: "#settings-menu" wait-for-css: ("#settings", {"display": "none"}) diff --git a/tests/rustdoc-gui/scrape-examples-button-focus.goml b/tests/rustdoc-gui/scrape-examples-button-focus.goml index 12246a37661..f6e836e2360 100644 --- a/tests/rustdoc-gui/scrape-examples-button-focus.goml +++ b/tests/rustdoc-gui/scrape-examples-button-focus.goml @@ -5,7 +5,7 @@ go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test.html" // The next/prev buttons vertically scroll the code viewport between examples move-cursor-to: ".scraped-example-list > .scraped-example" wait-for: ".scraped-example-list > .scraped-example .next" -store-value: (initialScrollTop, 250) +store-value: (initialScrollTop, 236) assert-property: (".scraped-example-list > .scraped-example .rust", { "scrollTop": |initialScrollTop|, }, NEAR) diff --git a/tests/rustdoc-gui/source-code-wrapping.goml b/tests/rustdoc-gui/source-code-wrapping.goml index cb2fd3052cd..0dab9c72ea9 100644 --- a/tests/rustdoc-gui/source-code-wrapping.goml +++ b/tests/rustdoc-gui/source-code-wrapping.goml @@ -31,17 +31,32 @@ go-to: "file://" + |DOC_PATH| + "/test_docs/trait_bounds/index.html" click: "#settings-menu" wait-for: "#settings" -store-size: (".example-wrap .rust code", {"width": rust_width, "height": rust_height}) -store-size: (".example-wrap .language-text code", {"width": txt_width, "height": txt_height}) +store-property: (".example-wrap .rust code", {"scrollWidth": rust_width, "scrollHeight": rust_height}) +store-property: (".example-wrap .language-text code", {"scrollWidth": txt_width, "scrollHeight": txt_height}) call-function: ("click-code-wrapping", {"expected": "true"}) -wait-for-size-false: (".example-wrap .rust code", {"width": |rust_width|, "height": |rust_height|}) +wait-for-property-false: ( + ".example-wrap .rust code", + {"scrollWidth": |rust_width|, "scrollHeight": |rust_height|}, +) -store-size: (".example-wrap .rust code", {"width": new_rust_width, "height": new_rust_height}) -store-size: (".example-wrap .language-text code", {"width": new_txt_width, "height": new_txt_height}) +store-property: ( + ".example-wrap .rust code", + {"scrollWidth": new_rust_width, "scrollHeight": new_rust_height}, +) +store-property: ( + ".example-wrap .language-text code", + {"scrollWidth": new_txt_width, "scrollHeight": new_txt_height}, +) assert: |rust_width| > |new_rust_width| && |rust_height| < |new_rust_height| assert: |txt_width| > |new_txt_width| && |txt_height| < |new_txt_height| call-function: ("click-code-wrapping", {"expected": "false"}) -wait-for-size: (".example-wrap .rust code", {"width": |rust_width|, "height": |rust_height|}) -assert-size: (".example-wrap .language-text code", {"width": |txt_width|, "height": |txt_height|}) +wait-for-property: ( + ".example-wrap .rust code", + {"scrollWidth": |rust_width|, "scrollHeight": |rust_height|}, +) +assert-property: ( + ".example-wrap .language-text code", + {"scrollWidth": |txt_width|, "scrollHeight": |txt_height|}, +) diff --git a/tests/rustdoc-json/attrs/target_feature.rs b/tests/rustdoc-json/attrs/target_feature.rs new file mode 100644 index 00000000000..ee2b3235f72 --- /dev/null +++ b/tests/rustdoc-json/attrs/target_feature.rs @@ -0,0 +1,17 @@ +//@ only-x86_64 + +//@ is "$.index[?(@.name=='test1')].attrs" '["#[target_feature(enable=\"avx\")]"]' +#[target_feature(enable = "avx")] +pub fn test1() {} + +//@ is "$.index[?(@.name=='test2')].attrs" '["#[target_feature(enable=\"avx\", enable=\"avx2\")]"]' +#[target_feature(enable = "avx,avx2")] +pub fn test2() {} + +//@ is "$.index[?(@.name=='test3')].attrs" '["#[target_feature(enable=\"avx\", enable=\"avx2\")]"]' +#[target_feature(enable = "avx", enable = "avx2")] +pub fn test3() {} + +//@ is "$.index[?(@.name=='test4')].attrs" '["#[target_feature(enable=\"avx\", enable=\"avx2\", enable=\"avx512f\")]"]' +#[target_feature(enable = "avx", enable = "avx2,avx512f")] +pub fn test4() {} diff --git a/tests/rustdoc/attributes-re-export.rs b/tests/rustdoc/attributes-re-export.rs new file mode 100644 index 00000000000..458826ea8a3 --- /dev/null +++ b/tests/rustdoc/attributes-re-export.rs @@ -0,0 +1,13 @@ +// Tests that attributes are correctly copied onto a re-exported item. +//@ edition:2021 +#![crate_name = "re_export"] + +//@ has 're_export/fn.thingy2.html' '//pre[@class="rust item-decl"]' '#[no_mangle]' +pub use thingymod::thingy as thingy2; + +mod thingymod { + #[no_mangle] + pub fn thingy() { + + } +} diff --git a/tests/rustdoc/reexport/extern-135092.rs b/tests/rustdoc/reexport/extern-135092.rs new file mode 100644 index 00000000000..fb5c71d56d5 --- /dev/null +++ b/tests/rustdoc/reexport/extern-135092.rs @@ -0,0 +1,26 @@ +// Test to make sure reexports of extern items are combined +// <https://github.com/rust-lang/rust/issues/135092> + +#![crate_name = "foo"] + +mod native { + extern "C" { + /// bar. + pub fn bar(); + } + + /// baz. + pub fn baz() {} +} + +//@ has 'foo/fn.bar.html' +//@ has - '//div[@class="docblock"]' 'bar.' +//@ has - '//div[@class="docblock"]' 'foo' +/// foo +pub use native::bar; + +//@ has 'foo/fn.baz.html' +//@ has - '//div[@class="docblock"]' 'baz.' +//@ has - '//div[@class="docblock"]' 'foo' +/// foo +pub use native::baz; diff --git a/tests/ui/abi/bad-custom.stderr b/tests/ui/abi/bad-custom.stderr index 893382875a2..372ef71375c 100644 --- a/tests/ui/abi/bad-custom.stderr +++ b/tests/ui/abi/bad-custom.stderr @@ -166,7 +166,7 @@ error: functions with the "custom" ABI cannot be `async` LL | async unsafe extern "custom" fn no_async_fn() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: remove the `async` keyword from this definiton +help: remove the `async` keyword from this definition | LL - async unsafe extern "custom" fn no_async_fn() { LL + unsafe extern "custom" fn no_async_fn() { diff --git a/tests/ui/abi/cannot-be-coroutine.avr.stderr b/tests/ui/abi/cannot-be-coroutine.avr.stderr index b06da0f3352..027f98c95c4 100644 --- a/tests/ui/abi/cannot-be-coroutine.avr.stderr +++ b/tests/ui/abi/cannot-be-coroutine.avr.stderr @@ -4,7 +4,7 @@ error: functions with the "avr-interrupt" ABI cannot be `async` LL | async extern "avr-interrupt" fn avr() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: remove the `async` keyword from this definiton +help: remove the `async` keyword from this definition | LL - async extern "avr-interrupt" fn avr() { LL + extern "avr-interrupt" fn avr() { diff --git a/tests/ui/abi/cannot-be-coroutine.i686.stderr b/tests/ui/abi/cannot-be-coroutine.i686.stderr index cbbddd087c8..8c9292b6a32 100644 --- a/tests/ui/abi/cannot-be-coroutine.i686.stderr +++ b/tests/ui/abi/cannot-be-coroutine.i686.stderr @@ -4,7 +4,7 @@ error: functions with the "x86-interrupt" ABI cannot be `async` LL | async extern "x86-interrupt" fn x86() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: remove the `async` keyword from this definiton +help: remove the `async` keyword from this definition | LL - async extern "x86-interrupt" fn x86() { LL + extern "x86-interrupt" fn x86() { diff --git a/tests/ui/abi/cannot-be-coroutine.msp430.stderr b/tests/ui/abi/cannot-be-coroutine.msp430.stderr index 951ce13b605..4b639cea9c1 100644 --- a/tests/ui/abi/cannot-be-coroutine.msp430.stderr +++ b/tests/ui/abi/cannot-be-coroutine.msp430.stderr @@ -4,7 +4,7 @@ error: functions with the "msp430-interrupt" ABI cannot be `async` LL | async extern "msp430-interrupt" fn msp430() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: remove the `async` keyword from this definiton +help: remove the `async` keyword from this definition | LL - async extern "msp430-interrupt" fn msp430() { LL + extern "msp430-interrupt" fn msp430() { diff --git a/tests/ui/abi/cannot-be-coroutine.riscv32.stderr b/tests/ui/abi/cannot-be-coroutine.riscv32.stderr index 8e3b3a2940a..1b18bc51f83 100644 --- a/tests/ui/abi/cannot-be-coroutine.riscv32.stderr +++ b/tests/ui/abi/cannot-be-coroutine.riscv32.stderr @@ -4,7 +4,7 @@ error: functions with the "riscv-interrupt-m" ABI cannot be `async` LL | async extern "riscv-interrupt-m" fn riscv_m() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: remove the `async` keyword from this definiton +help: remove the `async` keyword from this definition | LL - async extern "riscv-interrupt-m" fn riscv_m() { LL + extern "riscv-interrupt-m" fn riscv_m() { @@ -16,7 +16,7 @@ error: functions with the "riscv-interrupt-s" ABI cannot be `async` LL | async extern "riscv-interrupt-s" fn riscv_s() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: remove the `async` keyword from this definiton +help: remove the `async` keyword from this definition | LL - async extern "riscv-interrupt-s" fn riscv_s() { LL + extern "riscv-interrupt-s" fn riscv_s() { diff --git a/tests/ui/abi/cannot-be-coroutine.riscv64.stderr b/tests/ui/abi/cannot-be-coroutine.riscv64.stderr index 8e3b3a2940a..1b18bc51f83 100644 --- a/tests/ui/abi/cannot-be-coroutine.riscv64.stderr +++ b/tests/ui/abi/cannot-be-coroutine.riscv64.stderr @@ -4,7 +4,7 @@ error: functions with the "riscv-interrupt-m" ABI cannot be `async` LL | async extern "riscv-interrupt-m" fn riscv_m() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: remove the `async` keyword from this definiton +help: remove the `async` keyword from this definition | LL - async extern "riscv-interrupt-m" fn riscv_m() { LL + extern "riscv-interrupt-m" fn riscv_m() { @@ -16,7 +16,7 @@ error: functions with the "riscv-interrupt-s" ABI cannot be `async` LL | async extern "riscv-interrupt-s" fn riscv_s() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: remove the `async` keyword from this definiton +help: remove the `async` keyword from this definition | LL - async extern "riscv-interrupt-s" fn riscv_s() { LL + extern "riscv-interrupt-s" fn riscv_s() { diff --git a/tests/ui/abi/cannot-be-coroutine.x64.stderr b/tests/ui/abi/cannot-be-coroutine.x64.stderr index cbbddd087c8..8c9292b6a32 100644 --- a/tests/ui/abi/cannot-be-coroutine.x64.stderr +++ b/tests/ui/abi/cannot-be-coroutine.x64.stderr @@ -4,7 +4,7 @@ error: functions with the "x86-interrupt" ABI cannot be `async` LL | async extern "x86-interrupt" fn x86() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: remove the `async` keyword from this definiton +help: remove the `async` keyword from this definition | LL - async extern "x86-interrupt" fn x86() { LL + extern "x86-interrupt" fn x86() { diff --git a/tests/ui/abi/cannot-be-coroutine.x64_win.stderr b/tests/ui/abi/cannot-be-coroutine.x64_win.stderr index cbbddd087c8..8c9292b6a32 100644 --- a/tests/ui/abi/cannot-be-coroutine.x64_win.stderr +++ b/tests/ui/abi/cannot-be-coroutine.x64_win.stderr @@ -4,7 +4,7 @@ error: functions with the "x86-interrupt" ABI cannot be `async` LL | async extern "x86-interrupt" fn x86() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: remove the `async` keyword from this definiton +help: remove the `async` keyword from this definition | LL - async extern "x86-interrupt" fn x86() { LL + extern "x86-interrupt" fn x86() { diff --git a/tests/ui/abi/debug.rs b/tests/ui/abi/debug.rs index c0d8de05fda..97f5d5fba98 100644 --- a/tests/ui/abi/debug.rs +++ b/tests/ui/abi/debug.rs @@ -1,3 +1,4 @@ +//@ add-core-stubs //@ normalize-stderr: "(abi|pref|unadjusted_abi_align): Align\([1-8] bytes\)" -> "$1: $$SOME_ALIGN" //@ normalize-stderr: "randomization_seed: \d+" -> "randomization_seed: $$SEED" //@ normalize-stderr: "(size): Size\([48] bytes\)" -> "$1: $$SOME_SIZE" @@ -9,17 +10,26 @@ //@ compile-flags: -O #![feature(rustc_attrs)] #![crate_type = "lib"] +#![feature(no_core)] +#![no_std] +#![no_core] + +extern crate minicore; +use minicore::*; struct S(u16); #[rustc_abi(debug)] -fn test(_x: u8) -> bool { true } //~ ERROR: fn_abi +fn test(_x: u8) -> bool { + //~^ ERROR: fn_abi + true +} #[rustc_abi(debug)] type TestFnPtr = fn(bool) -> u8; //~ ERROR: fn_abi #[rustc_abi(debug)] -fn test_generic<T>(_x: *const T) { } //~ ERROR: fn_abi +fn test_generic<T>(_x: *const T) {} //~ ERROR: fn_abi #[rustc_abi(debug)] const C: () = (); //~ ERROR: can only be applied to @@ -31,7 +41,7 @@ impl S { impl S { #[rustc_abi(debug)] - fn assoc_test(&self) { } //~ ERROR: fn_abi + fn assoc_test(&self) {} //~ ERROR: fn_abi } #[rustc_abi(assert_eq)] diff --git a/tests/ui/abi/debug.stderr b/tests/ui/abi/debug.stderr index 8ed6dedf4d5..52351a2c260 100644 --- a/tests/ui/abi/debug.stderr +++ b/tests/ui/abi/debug.stderr @@ -89,9 +89,9 @@ error: fn_abi_of(test) = FnAbi { conv: Rust, can_unwind: $SOME_BOOL, } - --> $DIR/debug.rs:16:1 + --> $DIR/debug.rs:23:1 | -LL | fn test(_x: u8) -> bool { true } +LL | fn test(_x: u8) -> bool { | ^^^^^^^^^^^^^^^^^^^^^^^ error: fn_abi_of(TestFnPtr) = FnAbi { @@ -185,7 +185,7 @@ error: fn_abi_of(TestFnPtr) = FnAbi { conv: Rust, can_unwind: $SOME_BOOL, } - --> $DIR/debug.rs:19:1 + --> $DIR/debug.rs:29:1 | LL | type TestFnPtr = fn(bool) -> u8; | ^^^^^^^^^^^^^^ @@ -263,13 +263,13 @@ error: fn_abi_of(test_generic) = FnAbi { conv: Rust, can_unwind: $SOME_BOOL, } - --> $DIR/debug.rs:22:1 + --> $DIR/debug.rs:32:1 | -LL | fn test_generic<T>(_x: *const T) { } +LL | fn test_generic<T>(_x: *const T) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `#[rustc_abi]` can only be applied to function items, type aliases, and associated functions - --> $DIR/debug.rs:25:1 + --> $DIR/debug.rs:35:1 | LL | const C: () = (); | ^^^^^^^^^^^ @@ -419,7 +419,7 @@ error: ABIs are not compatible conv: Rust, can_unwind: $SOME_BOOL, } - --> $DIR/debug.rs:41:1 + --> $DIR/debug.rs:51:1 | LL | type TestAbiNe = (fn(u8), fn(u32)); | ^^^^^^^^^^^^^^ @@ -571,7 +571,7 @@ error: ABIs are not compatible conv: Rust, can_unwind: $SOME_BOOL, } - --> $DIR/debug.rs:44:1 + --> $DIR/debug.rs:54:1 | LL | type TestAbiNeLarger = (fn([u8; 32]), fn([u32; 32])); | ^^^^^^^^^^^^^^^^^^^^ @@ -720,7 +720,7 @@ error: ABIs are not compatible conv: Rust, can_unwind: $SOME_BOOL, } - --> $DIR/debug.rs:47:1 + --> $DIR/debug.rs:57:1 | LL | type TestAbiNeFloat = (fn(f32), fn(u32)); | ^^^^^^^^^^^^^^^^^^^ @@ -870,13 +870,13 @@ error: ABIs are not compatible conv: Rust, can_unwind: $SOME_BOOL, } - --> $DIR/debug.rs:51:1 + --> $DIR/debug.rs:61:1 | LL | type TestAbiNeSign = (fn(i32), fn(u32)); | ^^^^^^^^^^^^^^^^^^ error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/debug.rs:54:46 + --> $DIR/debug.rs:64:46 | LL | type TestAbiEqNonsense = (fn((str, str)), fn((str, str))); | ^^^^^^^^^^ doesn't have a size known at compile-time @@ -885,13 +885,13 @@ LL | type TestAbiEqNonsense = (fn((str, str)), fn((str, str))); = note: only the last element of a tuple may have a dynamically sized type error: unrecognized argument - --> $DIR/debug.rs:56:13 + --> $DIR/debug.rs:66:13 | LL | #[rustc_abi("assert_eq")] | ^^^^^^^^^^^ error: `#[rustc_abi]` can only be applied to function items, type aliases, and associated functions - --> $DIR/debug.rs:29:5 + --> $DIR/debug.rs:39:5 | LL | const C: () = (); | ^^^^^^^^^^^ @@ -981,9 +981,9 @@ error: fn_abi_of(assoc_test) = FnAbi { conv: Rust, can_unwind: $SOME_BOOL, } - --> $DIR/debug.rs:34:5 + --> $DIR/debug.rs:44:5 | -LL | fn assoc_test(&self) { } +LL | fn assoc_test(&self) {} | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to 12 previous errors diff --git a/tests/ui/abi/rust-cold-works-with-rustic-args.rs b/tests/ui/abi/rust-cold-works-with-rustic-args.rs index 57027364699..551485469d3 100644 --- a/tests/ui/abi/rust-cold-works-with-rustic-args.rs +++ b/tests/ui/abi/rust-cold-works-with-rustic-args.rs @@ -1,6 +1,15 @@ -//@build-pass -//@compile-flags: -Clink-dead-code=true --crate-type lib +//@ add-core-stubs +//@ build-pass +//@ compile-flags: -Clink-dead-code=true // We used to not handle all "rustic" ABIs in a (relatively) uniform way, // so we failed to fix up arguments for actually passing through the ABI... #![feature(rust_cold_cc)] +#![crate_type = "lib"] +#![feature(no_core)] +#![no_std] +#![no_core] + +extern crate minicore; +use minicore::*; + pub extern "rust-cold" fn foo(_: [usize; 3]) {} diff --git a/tests/ui/attributes/crate-type-macro-empty.rs b/tests/ui/attributes/crate-type-macro-empty.rs index 5ff7fc002fd..217ff598f7a 100644 --- a/tests/ui/attributes/crate-type-macro-empty.rs +++ b/tests/ui/attributes/crate-type-macro-empty.rs @@ -2,6 +2,6 @@ #[crate_type = foo!()] //~^ ERROR cannot find macro `foo` in this scope -macro_rules! foo {} //~ ERROR unexpected end of macro invocation +macro_rules! foo {} //~ ERROR macros must contain at least one rule fn main() {} diff --git a/tests/ui/attributes/crate-type-macro-empty.stderr b/tests/ui/attributes/crate-type-macro-empty.stderr index e48d3d95470..130fa454ca1 100644 --- a/tests/ui/attributes/crate-type-macro-empty.stderr +++ b/tests/ui/attributes/crate-type-macro-empty.stderr @@ -1,8 +1,8 @@ -error: unexpected end of macro invocation +error: macros must contain at least one rule --> $DIR/crate-type-macro-empty.rs:5:1 | LL | macro_rules! foo {} - | ^^^^^^^^^^^^^^^^^^^ missing tokens in macro arguments + | ^^^^^^^^^^^^^^^^^^^ error: cannot find macro `foo` in this scope --> $DIR/crate-type-macro-empty.rs:2:16 diff --git a/tests/ui/attributes/malformed-attrs.rs b/tests/ui/attributes/malformed-attrs.rs index 64c0d223f83..dbe9c35b0a4 100644 --- a/tests/ui/attributes/malformed-attrs.rs +++ b/tests/ui/attributes/malformed-attrs.rs @@ -33,6 +33,7 @@ //~^ ERROR malformed #[rustc_allow_const_fn_unstable] //~^ ERROR `rustc_allow_const_fn_unstable` expects a list of feature names +//~| ERROR attribute should be applied to `const fn` #[allow_internal_unstable] //~^ ERROR `allow_internal_unstable` expects a list of feature names #[rustc_confusables] diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr index bf063e8f6e5..c65eff8a550 100644 --- a/tests/ui/attributes/malformed-attrs.stderr +++ b/tests/ui/attributes/malformed-attrs.stderr @@ -1,11 +1,11 @@ error: `cfg` is not followed by parentheses - --> $DIR/malformed-attrs.rs:100:1 + --> $DIR/malformed-attrs.rs:101:1 | LL | #[cfg] | ^^^^^^ help: expected syntax is: `cfg(/* predicate */)` error: malformed `cfg_attr` attribute input - --> $DIR/malformed-attrs.rs:102:1 + --> $DIR/malformed-attrs.rs:103:1 | LL | #[cfg_attr] | ^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | #[cfg_attr(condition, attribute, other_attribute, ...)] | ++++++++++++++++++++++++++++++++++++++++++++ error[E0463]: can't find crate for `wloop` - --> $DIR/malformed-attrs.rs:209:1 + --> $DIR/malformed-attrs.rs:210:1 | LL | extern crate wloop; | ^^^^^^^^^^^^^^^^^^^ can't find crate @@ -35,25 +35,19 @@ LL | #![windows_subsystem] | ^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![windows_subsystem = "windows|console"]` error: malformed `crate_name` attribute input - --> $DIR/malformed-attrs.rs:72:1 + --> $DIR/malformed-attrs.rs:73:1 | LL | #[crate_name] | ^^^^^^^^^^^^^ help: must be of the form: `#[crate_name = "name"]` -error: malformed `target_feature` attribute input - --> $DIR/malformed-attrs.rs:77:1 - | -LL | #[target_feature] - | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[target_feature(enable = "name")]` - error: malformed `export_stable` attribute input - --> $DIR/malformed-attrs.rs:79:1 + --> $DIR/malformed-attrs.rs:80:1 | LL | #[export_stable = 1] | ^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[export_stable]` error: malformed `coverage` attribute input - --> $DIR/malformed-attrs.rs:88:1 + --> $DIR/malformed-attrs.rs:89:1 | LL | #[coverage] | ^^^^^^^^^^^ @@ -66,55 +60,55 @@ LL | #[coverage(on)] | ++++ error: malformed `no_sanitize` attribute input - --> $DIR/malformed-attrs.rs:90:1 + --> $DIR/malformed-attrs.rs:91:1 | LL | #[no_sanitize] | ^^^^^^^^^^^^^^ help: must be of the form: `#[no_sanitize(address, kcfi, memory, thread)]` error: malformed `no_implicit_prelude` attribute input - --> $DIR/malformed-attrs.rs:95:1 + --> $DIR/malformed-attrs.rs:96:1 | LL | #[no_implicit_prelude = 23] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[no_implicit_prelude]` error: malformed `proc_macro` attribute input - --> $DIR/malformed-attrs.rs:97:1 + --> $DIR/malformed-attrs.rs:98:1 | LL | #[proc_macro = 18] | ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro]` error: malformed `instruction_set` attribute input - --> $DIR/malformed-attrs.rs:104:1 + --> $DIR/malformed-attrs.rs:105:1 | LL | #[instruction_set] | ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[instruction_set(set)]` error: malformed `patchable_function_entry` attribute input - --> $DIR/malformed-attrs.rs:106:1 + --> $DIR/malformed-attrs.rs:107:1 | LL | #[patchable_function_entry] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[patchable_function_entry(prefix_nops = m, entry_nops = n)]` error: malformed `coroutine` attribute input - --> $DIR/malformed-attrs.rs:109:5 + --> $DIR/malformed-attrs.rs:110:5 | LL | #[coroutine = 63] || {} | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[coroutine]` error: malformed `proc_macro_attribute` attribute input - --> $DIR/malformed-attrs.rs:114:1 + --> $DIR/malformed-attrs.rs:115:1 | LL | #[proc_macro_attribute = 19] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro_attribute]` error: malformed `proc_macro_derive` attribute input - --> $DIR/malformed-attrs.rs:121:1 + --> $DIR/malformed-attrs.rs:122:1 | LL | #[proc_macro_derive] | ^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]` error: malformed `must_not_suspend` attribute input - --> $DIR/malformed-attrs.rs:130:1 + --> $DIR/malformed-attrs.rs:131:1 | LL | #[must_not_suspend()] | ^^^^^^^^^^^^^^^^^^^^^ @@ -129,115 +123,115 @@ LL + #[must_not_suspend] | error: malformed `cfi_encoding` attribute input - --> $DIR/malformed-attrs.rs:132:1 + --> $DIR/malformed-attrs.rs:133:1 | LL | #[cfi_encoding] | ^^^^^^^^^^^^^^^ help: must be of the form: `#[cfi_encoding = "encoding"]` error: malformed `type_const` attribute input - --> $DIR/malformed-attrs.rs:141:5 + --> $DIR/malformed-attrs.rs:142:5 | LL | #[type_const = 1] | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[type_const]` error: malformed `marker` attribute input - --> $DIR/malformed-attrs.rs:153:1 + --> $DIR/malformed-attrs.rs:154:1 | LL | #[marker = 3] | ^^^^^^^^^^^^^ help: must be of the form: `#[marker]` error: malformed `fundamental` attribute input - --> $DIR/malformed-attrs.rs:155:1 + --> $DIR/malformed-attrs.rs:156:1 | LL | #[fundamental()] | ^^^^^^^^^^^^^^^^ help: must be of the form: `#[fundamental]` error: malformed `ffi_pure` attribute input - --> $DIR/malformed-attrs.rs:163:5 + --> $DIR/malformed-attrs.rs:164:5 | LL | #[unsafe(ffi_pure = 1)] | ^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[ffi_pure]` error: malformed `link_ordinal` attribute input - --> $DIR/malformed-attrs.rs:165:5 + --> $DIR/malformed-attrs.rs:166:5 | LL | #[link_ordinal] | ^^^^^^^^^^^^^^^ help: must be of the form: `#[link_ordinal(ordinal)]` error: malformed `ffi_const` attribute input - --> $DIR/malformed-attrs.rs:169:5 + --> $DIR/malformed-attrs.rs:170:5 | LL | #[unsafe(ffi_const = 1)] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[ffi_const]` error: malformed `linkage` attribute input - --> $DIR/malformed-attrs.rs:171:5 + --> $DIR/malformed-attrs.rs:172:5 | LL | #[linkage] | ^^^^^^^^^^ help: must be of the form: `#[linkage = "external|internal|..."]` error: malformed `allow` attribute input - --> $DIR/malformed-attrs.rs:176:1 + --> $DIR/malformed-attrs.rs:177:1 | LL | #[allow] | ^^^^^^^^ help: must be of the form: `#[allow(lint1, lint2, ..., /*opt*/ reason = "...")]` error: malformed `expect` attribute input - --> $DIR/malformed-attrs.rs:178:1 + --> $DIR/malformed-attrs.rs:179:1 | LL | #[expect] | ^^^^^^^^^ help: must be of the form: `#[expect(lint1, lint2, ..., /*opt*/ reason = "...")]` error: malformed `warn` attribute input - --> $DIR/malformed-attrs.rs:180:1 + --> $DIR/malformed-attrs.rs:181:1 | LL | #[warn] | ^^^^^^^ help: must be of the form: `#[warn(lint1, lint2, ..., /*opt*/ reason = "...")]` error: malformed `deny` attribute input - --> $DIR/malformed-attrs.rs:182:1 + --> $DIR/malformed-attrs.rs:183:1 | LL | #[deny] | ^^^^^^^ help: must be of the form: `#[deny(lint1, lint2, ..., /*opt*/ reason = "...")]` error: malformed `forbid` attribute input - --> $DIR/malformed-attrs.rs:184:1 + --> $DIR/malformed-attrs.rs:185:1 | LL | #[forbid] | ^^^^^^^^^ help: must be of the form: `#[forbid(lint1, lint2, ..., /*opt*/ reason = "...")]` error: malformed `debugger_visualizer` attribute input - --> $DIR/malformed-attrs.rs:186:1 + --> $DIR/malformed-attrs.rs:187:1 | LL | #[debugger_visualizer] | ^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[debugger_visualizer(natvis_file = "...", gdb_script_file = "...")]` error: malformed `automatically_derived` attribute input - --> $DIR/malformed-attrs.rs:189:1 + --> $DIR/malformed-attrs.rs:190:1 | LL | #[automatically_derived = 18] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[automatically_derived]` error: malformed `non_exhaustive` attribute input - --> $DIR/malformed-attrs.rs:195:1 + --> $DIR/malformed-attrs.rs:196:1 | LL | #[non_exhaustive = 1] | ^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[non_exhaustive]` error: malformed `thread_local` attribute input - --> $DIR/malformed-attrs.rs:201:1 + --> $DIR/malformed-attrs.rs:202:1 | LL | #[thread_local()] | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[thread_local]` error: malformed `no_link` attribute input - --> $DIR/malformed-attrs.rs:205:1 + --> $DIR/malformed-attrs.rs:206:1 | LL | #[no_link()] | ^^^^^^^^^^^^ help: must be of the form: `#[no_link]` error: malformed `macro_use` attribute input - --> $DIR/malformed-attrs.rs:207:1 + --> $DIR/malformed-attrs.rs:208:1 | LL | #[macro_use = 1] | ^^^^^^^^^^^^^^^^ @@ -252,7 +246,7 @@ LL + #[macro_use] | error: malformed `macro_export` attribute input - --> $DIR/malformed-attrs.rs:212:1 + --> $DIR/malformed-attrs.rs:213:1 | LL | #[macro_export = 18] | ^^^^^^^^^^^^^^^^^^^^ @@ -267,31 +261,31 @@ LL + #[macro_export] | error: malformed `allow_internal_unsafe` attribute input - --> $DIR/malformed-attrs.rs:214:1 + --> $DIR/malformed-attrs.rs:215:1 | LL | #[allow_internal_unsafe = 1] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[allow_internal_unsafe]` error: the `#[proc_macro]` attribute is only usable with crates of the `proc-macro` crate type - --> $DIR/malformed-attrs.rs:97:1 + --> $DIR/malformed-attrs.rs:98:1 | LL | #[proc_macro = 18] | ^^^^^^^^^^^^^^^^^^ error: the `#[proc_macro_attribute]` attribute is only usable with crates of the `proc-macro` crate type - --> $DIR/malformed-attrs.rs:114:1 + --> $DIR/malformed-attrs.rs:115:1 | LL | #[proc_macro_attribute = 19] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type - --> $DIR/malformed-attrs.rs:121:1 + --> $DIR/malformed-attrs.rs:122:1 | LL | #[proc_macro_derive] | ^^^^^^^^^^^^^^^^^^^^ error[E0658]: allow_internal_unsafe side-steps the unsafe_code lint - --> $DIR/malformed-attrs.rs:214:1 + --> $DIR/malformed-attrs.rs:215:1 | LL | #[allow_internal_unsafe = 1] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -300,7 +294,7 @@ LL | #[allow_internal_unsafe = 1] = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: valid forms for the attribute are `#[doc(hidden|inline|...)]` and `#[doc = "string"]` - --> $DIR/malformed-attrs.rs:42:1 + --> $DIR/malformed-attrs.rs:43:1 | LL | #[doc] | ^^^^^^ @@ -310,7 +304,7 @@ LL | #[doc] = note: `#[deny(ill_formed_attribute_input)]` on by default error: valid forms for the attribute are `#[doc(hidden|inline|...)]` and `#[doc = "string"]` - --> $DIR/malformed-attrs.rs:74:1 + --> $DIR/malformed-attrs.rs:75:1 | LL | #[doc] | ^^^^^^ @@ -319,7 +313,7 @@ LL | #[doc] = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571> error: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...", /*opt*/ import_name_type = "decorated|noprefix|undecorated")]` - --> $DIR/malformed-attrs.rs:81:1 + --> $DIR/malformed-attrs.rs:82:1 | LL | #[link] | ^^^^^^^ @@ -328,7 +322,7 @@ LL | #[link] = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571> error: valid forms for the attribute are `#[ignore]` and `#[ignore = "reason"]` - --> $DIR/malformed-attrs.rs:92:1 + --> $DIR/malformed-attrs.rs:93:1 | LL | #[ignore()] | ^^^^^^^^^^^ @@ -337,7 +331,7 @@ LL | #[ignore()] = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571> error: invalid argument - --> $DIR/malformed-attrs.rs:186:1 + --> $DIR/malformed-attrs.rs:187:1 | LL | #[debugger_visualizer] | ^^^^^^^^^^^^^^^^^^^^^^ @@ -359,13 +353,13 @@ LL | #[rustc_allow_const_fn_unstable] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `allow_internal_unstable` expects a list of feature names - --> $DIR/malformed-attrs.rs:36:1 + --> $DIR/malformed-attrs.rs:37:1 | LL | #[allow_internal_unstable] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0539]: malformed `rustc_confusables` attribute input - --> $DIR/malformed-attrs.rs:38:1 + --> $DIR/malformed-attrs.rs:39:1 | LL | #[rustc_confusables] | ^^^^^^^^^^^^^^^^^^^^ @@ -374,7 +368,7 @@ LL | #[rustc_confusables] | help: must be of the form: `#[rustc_confusables("name1", "name2", ...)]` error[E0539]: malformed `deprecated` attribute input - --> $DIR/malformed-attrs.rs:40:1 + --> $DIR/malformed-attrs.rs:41:1 | LL | #[deprecated = 5] | ^^^^^^^^^^^^^^^-^ @@ -394,13 +388,13 @@ LL + #[deprecated] | error[E0539]: malformed `rustc_macro_transparency` attribute input - --> $DIR/malformed-attrs.rs:45:1 + --> $DIR/malformed-attrs.rs:46:1 | LL | #[rustc_macro_transparency] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_macro_transparency = "transparent|semitransparent|opaque"]` error[E0539]: malformed `repr` attribute input - --> $DIR/malformed-attrs.rs:47:1 + --> $DIR/malformed-attrs.rs:48:1 | LL | #[repr] | ^^^^^^^ @@ -409,7 +403,7 @@ LL | #[repr] | help: must be of the form: `#[repr(C | Rust | align(...) | packed(...) | <integer type> | transparent)]` error[E0565]: malformed `rustc_as_ptr` attribute input - --> $DIR/malformed-attrs.rs:49:1 + --> $DIR/malformed-attrs.rs:50:1 | LL | #[rustc_as_ptr = 5] | ^^^^^^^^^^^^^^^---^ @@ -418,7 +412,7 @@ LL | #[rustc_as_ptr = 5] | help: must be of the form: `#[rustc_as_ptr]` error[E0539]: malformed `align` attribute input - --> $DIR/malformed-attrs.rs:54:1 + --> $DIR/malformed-attrs.rs:55:1 | LL | #[align] | ^^^^^^^^ @@ -427,7 +421,7 @@ LL | #[align] | help: must be of the form: `#[align(<alignment in bytes>)]` error[E0539]: malformed `optimize` attribute input - --> $DIR/malformed-attrs.rs:56:1 + --> $DIR/malformed-attrs.rs:57:1 | LL | #[optimize] | ^^^^^^^^^^^ @@ -436,7 +430,7 @@ LL | #[optimize] | help: must be of the form: `#[optimize(size|speed|none)]` error[E0565]: malformed `cold` attribute input - --> $DIR/malformed-attrs.rs:58:1 + --> $DIR/malformed-attrs.rs:59:1 | LL | #[cold = 1] | ^^^^^^^---^ @@ -445,13 +439,13 @@ LL | #[cold = 1] | help: must be of the form: `#[cold]` error: valid forms for the attribute are `#[must_use = "reason"]` and `#[must_use]` - --> $DIR/malformed-attrs.rs:60:1 + --> $DIR/malformed-attrs.rs:61:1 | LL | #[must_use()] | ^^^^^^^^^^^^^ error[E0565]: malformed `no_mangle` attribute input - --> $DIR/malformed-attrs.rs:62:1 + --> $DIR/malformed-attrs.rs:63:1 | LL | #[no_mangle = 1] | ^^^^^^^^^^^^---^ @@ -460,7 +454,7 @@ LL | #[no_mangle = 1] | help: must be of the form: `#[no_mangle]` error[E0565]: malformed `naked` attribute input - --> $DIR/malformed-attrs.rs:64:1 + --> $DIR/malformed-attrs.rs:65:1 | LL | #[unsafe(naked())] | ^^^^^^^^^^^^^^--^^ @@ -469,7 +463,7 @@ LL | #[unsafe(naked())] | help: must be of the form: `#[naked]` error[E0565]: malformed `track_caller` attribute input - --> $DIR/malformed-attrs.rs:66:1 + --> $DIR/malformed-attrs.rs:67:1 | LL | #[track_caller()] | ^^^^^^^^^^^^^^--^ @@ -478,13 +472,13 @@ LL | #[track_caller()] | help: must be of the form: `#[track_caller]` error[E0539]: malformed `export_name` attribute input - --> $DIR/malformed-attrs.rs:68:1 + --> $DIR/malformed-attrs.rs:69:1 | LL | #[export_name()] | ^^^^^^^^^^^^^^^^ help: must be of the form: `#[export_name = "name"]` error[E0805]: malformed `used` attribute input - --> $DIR/malformed-attrs.rs:70:1 + --> $DIR/malformed-attrs.rs:71:1 | LL | #[used()] | ^^^^^^--^ @@ -499,20 +493,29 @@ LL - #[used()] LL + #[used] | +error[E0539]: malformed `target_feature` attribute input + --> $DIR/malformed-attrs.rs:78:1 + | +LL | #[target_feature] + | ^^^^^^^^^^^^^^^^^ + | | + | expected this to be a list + | help: must be of the form: `#[target_feature(enable = "feat1, feat2")]` + error[E0539]: malformed `link_name` attribute input - --> $DIR/malformed-attrs.rs:84:1 + --> $DIR/malformed-attrs.rs:85:1 | LL | #[link_name] | ^^^^^^^^^^^^ help: must be of the form: `#[link_name = "name"]` error[E0539]: malformed `link_section` attribute input - --> $DIR/malformed-attrs.rs:86:1 + --> $DIR/malformed-attrs.rs:87:1 | LL | #[link_section] | ^^^^^^^^^^^^^^^ help: must be of the form: `#[link_section = "name"]` error[E0539]: malformed `must_use` attribute input - --> $DIR/malformed-attrs.rs:117:1 + --> $DIR/malformed-attrs.rs:118:1 | LL | #[must_use = 1] | ^^^^^^^^^^^^^-^ @@ -529,7 +532,7 @@ LL + #[must_use] | error[E0539]: malformed `rustc_layout_scalar_valid_range_start` attribute input - --> $DIR/malformed-attrs.rs:126:1 + --> $DIR/malformed-attrs.rs:127:1 | LL | #[rustc_layout_scalar_valid_range_start] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -538,7 +541,7 @@ LL | #[rustc_layout_scalar_valid_range_start] | help: must be of the form: `#[rustc_layout_scalar_valid_range_start(start)]` error[E0539]: malformed `rustc_layout_scalar_valid_range_end` attribute input - --> $DIR/malformed-attrs.rs:128:1 + --> $DIR/malformed-attrs.rs:129:1 | LL | #[rustc_layout_scalar_valid_range_end] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -546,8 +549,20 @@ LL | #[rustc_layout_scalar_valid_range_end] | expected this to be a list | help: must be of the form: `#[rustc_layout_scalar_valid_range_end(end)]` +error: attribute should be applied to `const fn` + --> $DIR/malformed-attrs.rs:34:1 + | +LL | #[rustc_allow_const_fn_unstable] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | / fn test() { +LL | | #[coroutine = 63] || {} +... | +LL | | } + | |_- not a `const fn` + warning: `#[diagnostic::do_not_recommend]` does not expect any arguments - --> $DIR/malformed-attrs.rs:147:1 + --> $DIR/malformed-attrs.rs:148:1 | LL | #[diagnostic::do_not_recommend()] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -555,7 +570,7 @@ LL | #[diagnostic::do_not_recommend()] = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default warning: missing options for `on_unimplemented` attribute - --> $DIR/malformed-attrs.rs:136:1 + --> $DIR/malformed-attrs.rs:137:1 | LL | #[diagnostic::on_unimplemented] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -563,7 +578,7 @@ LL | #[diagnostic::on_unimplemented] = help: at least one of the `message`, `note` and `label` options are expected warning: malformed `on_unimplemented` attribute - --> $DIR/malformed-attrs.rs:138:1 + --> $DIR/malformed-attrs.rs:139:1 | LL | #[diagnostic::on_unimplemented = 1] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here @@ -571,7 +586,7 @@ LL | #[diagnostic::on_unimplemented = 1] = help: only `message`, `note` and `label` are allowed as options error: valid forms for the attribute are `#[inline(always|never)]` and `#[inline]` - --> $DIR/malformed-attrs.rs:51:1 + --> $DIR/malformed-attrs.rs:52:1 | LL | #[inline = 5] | ^^^^^^^^^^^^^ @@ -580,7 +595,7 @@ LL | #[inline = 5] = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571> error[E0308]: mismatched types - --> $DIR/malformed-attrs.rs:109:23 + --> $DIR/malformed-attrs.rs:110:23 | LL | fn test() { | - help: a return type might be missing here: `-> _` @@ -588,9 +603,9 @@ LL | #[coroutine = 63] || {} | ^^^^^ expected `()`, found coroutine | = note: expected unit type `()` - found coroutine `{coroutine@$DIR/malformed-attrs.rs:109:23: 109:25}` + found coroutine `{coroutine@$DIR/malformed-attrs.rs:110:23: 110:25}` -error: aborting due to 72 previous errors; 3 warnings emitted +error: aborting due to 73 previous errors; 3 warnings emitted Some errors have detailed explanations: E0308, E0463, E0539, E0565, E0658, E0805. For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index 532c1ab13d1..2484974cdc2 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -129,7 +129,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_abi = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_abi` are: ``, `abi64`, `abiv2`, `abiv2hf`, `eabi`, `eabihf`, `fortanix`, `ilp32`, `ilp32e`, `llvm`, `macabi`, `sim`, `softfloat`, `spe`, `uwp`, `vec-extabi`, and `x32` + = note: expected values for `target_abi` are: ``, `abi64`, `abiv2`, `abiv2hf`, `eabi`, `eabihf`, `elfv1`, `elfv2`, `fortanix`, `ilp32`, `ilp32e`, `llvm`, `macabi`, `sim`, `softfloat`, `spe`, `uwp`, `vec-extabi`, and `x32` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` diff --git a/tests/ui/drop/drop-order-comparisons-let-chains.rs b/tests/ui/drop/drop-order-comparisons-let-chains.rs new file mode 100644 index 00000000000..5dea5e1a580 --- /dev/null +++ b/tests/ui/drop/drop-order-comparisons-let-chains.rs @@ -0,0 +1,145 @@ +// See drop-order-comparisons.rs + +//@ edition: 2024 +//@ run-pass + +#![feature(if_let_guard)] + +fn t_if_let_chains_then() { + let e = Events::new(); + _ = if e.ok(1).is_ok() + && let true = e.ok(9).is_ok() + && let Ok(_v) = e.ok(8) + && let Ok(_) = e.ok(7) + && let Ok(_) = e.ok(6).as_ref() + && e.ok(2).is_ok() + && let Ok(_v) = e.ok(5) + && let Ok(_) = e.ok(4).as_ref() { + e.mark(3); + }; + e.assert(9); +} + +fn t_guard_if_let_chains_then() { + let e = Events::new(); + _ = match () { + () if e.ok(1).is_ok() + && let true = e.ok(9).is_ok() + && let Ok(_v) = e.ok(8) + && let Ok(_) = e.ok(7) + && let Ok(_) = e.ok(6).as_ref() + && e.ok(2).is_ok() + && let Ok(_v) = e.ok(5) + && let Ok(_) = e.ok(4).as_ref() => { + e.mark(3); + } + _ => {} + }; + e.assert(9); +} + +fn t_if_let_chains_then_else() { + let e = Events::new(); + _ = if e.ok(1).is_ok() + && let true = e.ok(8).is_ok() + && let Ok(_v) = e.ok(7) + && let Ok(_) = e.ok(6) + && let Ok(_) = e.ok(5).as_ref() + && e.ok(2).is_ok() + && let Ok(_v) = e.ok(4) + && let Ok(_) = e.err(3) {} else { + e.mark(9); + }; + e.assert(9); +} + +fn t_guard_if_let_chains_then_else() { + let e = Events::new(); + _ = match () { + () if e.ok(1).is_ok() + && let true = e.ok(8).is_ok() + && let Ok(_v) = e.ok(7) + && let Ok(_) = e.ok(6) + && let Ok(_) = e.ok(5).as_ref() + && e.ok(2).is_ok() + && let Ok(_v) = e.ok(4) + && let Ok(_) = e.err(3) => {} + _ => { + e.mark(9); + } + }; + e.assert(9); +} + +fn main() { + t_if_let_chains_then(); + t_guard_if_let_chains_then(); + t_if_let_chains_then_else(); + t_guard_if_let_chains_then_else(); +} + +// # Test scaffolding + +use core::cell::RefCell; +use std::collections::HashSet; + +/// A buffer to track the order of events. +/// +/// First, numbered events are logged into this buffer. +/// +/// Then, `assert` is called to verify that the correct number of +/// events were logged, and that they were logged in the expected +/// order. +struct Events(RefCell<Option<Vec<u64>>>); + +impl Events { + const fn new() -> Self { + Self(RefCell::new(Some(Vec::new()))) + } + #[track_caller] + fn assert(&self, max: u64) { + let buf = &self.0; + let v1 = buf.borrow().as_ref().unwrap().clone(); + let mut v2 = buf.borrow().as_ref().unwrap().clone(); + *buf.borrow_mut() = None; + v2.sort(); + let uniq_len = v2.iter().collect::<HashSet<_>>().len(); + // Check that the sequence is sorted. + assert_eq!(v1, v2); + // Check that there are no duplicates. + assert_eq!(v2.len(), uniq_len); + // Check that the length is the expected one. + assert_eq!(max, uniq_len as u64); + // Check that the last marker is the expected one. + assert_eq!(v2.last().unwrap(), &max); + } + /// Return an `Ok` value that logs its drop. + fn ok(&self, m: u64) -> Result<LogDrop<'_>, LogDrop<'_>> { + Ok(LogDrop(self, m)) + } + /// Return an `Err` value that logs its drop. + fn err(&self, m: u64) -> Result<LogDrop<'_>, LogDrop<'_>> { + Err(LogDrop(self, m)) + } + /// Log an event. + fn mark(&self, m: u64) { + self.0.borrow_mut().as_mut().unwrap().push(m); + } +} + +impl Drop for Events { + fn drop(&mut self) { + if self.0.borrow().is_some() { + panic!("failed to call `Events::assert()`"); + } + } +} + +/// A type that logs its drop events. +struct LogDrop<'b>(&'b Events, u64); + +impl<'b> Drop for LogDrop<'b> { + fn drop(&mut self) { + self.0.mark(self.1); + } +} diff --git a/tests/ui/drop/drop-order-comparisons.e2021.fixed b/tests/ui/drop/drop-order-comparisons.e2021.fixed index 42f805923ec..b0f6eb93f70 100644 --- a/tests/ui/drop/drop-order-comparisons.e2021.fixed +++ b/tests/ui/drop/drop-order-comparisons.e2021.fixed @@ -1,3 +1,6 @@ +// N.B. drop-order-comparisons-let-chains.rs is part of this test. +// It is separate because let chains cannot be parsed before Rust 2024. +// // This tests various aspects of the drop order with a focus on: // // - The lifetime of temporaries with the `if let` construct (and with @@ -25,7 +28,6 @@ //@ run-pass #![feature(if_let_guard)] -#![cfg_attr(e2021, feature(let_chains))] #![cfg_attr(e2021, warn(rust_2024_compatibility))] fn t_bindings() { @@ -313,59 +315,6 @@ fn t_let_else_chained_then() { #[cfg(e2021)] #[rustfmt::skip] -fn t_if_let_chains_then() { - let e = Events::new(); - _ = if e.ok(1).is_ok() - && let true = e.ok(9).is_ok() - && let Ok(_v) = e.ok(5) - && let Ok(_) = e.ok(8) - && let Ok(_) = e.ok(7).as_ref() - && e.ok(2).is_ok() - && let Ok(_v) = e.ok(4) - && let Ok(_) = e.ok(6).as_ref() { - e.mark(3); - }; - e.assert(9); -} - -#[cfg(e2024)] -#[rustfmt::skip] -fn t_if_let_chains_then() { - let e = Events::new(); - _ = if e.ok(1).is_ok() - && let true = e.ok(9).is_ok() - && let Ok(_v) = e.ok(8) - && let Ok(_) = e.ok(7) - && let Ok(_) = e.ok(6).as_ref() - && e.ok(2).is_ok() - && let Ok(_v) = e.ok(5) - && let Ok(_) = e.ok(4).as_ref() { - e.mark(3); - }; - e.assert(9); -} - -#[rustfmt::skip] -fn t_guard_if_let_chains_then() { - let e = Events::new(); - _ = match () { - () if e.ok(1).is_ok() - && let true = e.ok(9).is_ok() - && let Ok(_v) = e.ok(8) - && let Ok(_) = e.ok(7) - && let Ok(_) = e.ok(6).as_ref() - && e.ok(2).is_ok() - && let Ok(_v) = e.ok(5) - && let Ok(_) = e.ok(4).as_ref() => { - e.mark(3); - } - _ => {} - }; - e.assert(9); -} - -#[cfg(e2021)] -#[rustfmt::skip] fn t_if_let_nested_else() { let e = Events::new(); _ = if e.err(1).is_ok() {} else { @@ -470,59 +419,6 @@ fn t_let_else_chained_then_else() { e.assert(9); } -#[cfg(e2021)] -#[rustfmt::skip] -fn t_if_let_chains_then_else() { - let e = Events::new(); - _ = if e.ok(1).is_ok() - && let true = e.ok(9).is_ok() - && let Ok(_v) = e.ok(4) - && let Ok(_) = e.ok(8) - && let Ok(_) = e.ok(7).as_ref() - && e.ok(2).is_ok() - && let Ok(_v) = e.ok(3) - && let Ok(_) = e.err(6) {} else { - e.mark(5); - }; - e.assert(9); -} - -#[cfg(e2024)] -#[rustfmt::skip] -fn t_if_let_chains_then_else() { - let e = Events::new(); - _ = if e.ok(1).is_ok() - && let true = e.ok(8).is_ok() - && let Ok(_v) = e.ok(7) - && let Ok(_) = e.ok(6) - && let Ok(_) = e.ok(5).as_ref() - && e.ok(2).is_ok() - && let Ok(_v) = e.ok(4) - && let Ok(_) = e.err(3) {} else { - e.mark(9); - }; - e.assert(9); -} - -#[rustfmt::skip] -fn t_guard_if_let_chains_then_else() { - let e = Events::new(); - _ = match () { - () if e.ok(1).is_ok() - && let true = e.ok(8).is_ok() - && let Ok(_v) = e.ok(7) - && let Ok(_) = e.ok(6) - && let Ok(_) = e.ok(5).as_ref() - && e.ok(2).is_ok() - && let Ok(_v) = e.ok(4) - && let Ok(_) = e.err(3) => {} - _ => { - e.mark(9); - } - }; - e.assert(9); -} - fn main() { t_bindings(); t_tuples(); @@ -540,13 +436,9 @@ fn main() { t_if_let_else_tailexpr(); t_if_let_nested_then(); t_let_else_chained_then(); - t_if_let_chains_then(); - t_guard_if_let_chains_then(); t_if_let_nested_else(); t_if_let_nested_then_else(); t_let_else_chained_then_else(); - t_if_let_chains_then_else(); - t_guard_if_let_chains_then_else(); } // # Test scaffolding diff --git a/tests/ui/drop/drop-order-comparisons.e2021.stderr b/tests/ui/drop/drop-order-comparisons.e2021.stderr index 8b93376cc0d..15a3f274514 100644 --- a/tests/ui/drop/drop-order-comparisons.e2021.stderr +++ b/tests/ui/drop/drop-order-comparisons.e2021.stderr @@ -1,5 +1,5 @@ warning: relative drop order changing in Rust 2024 - --> $DIR/drop-order-comparisons.rs:77:9 + --> $DIR/drop-order-comparisons.rs:79:9 | LL | _ = ({ | _________- @@ -29,35 +29,35 @@ LL | | }, e.mark(3), e.ok(4)); = warning: this changes meaning in Rust 2024 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html> note: `#3` invokes this custom destructor - --> $DIR/drop-order-comparisons.rs:612:1 + --> $DIR/drop-order-comparisons.rs:504:1 | LL | impl<'b> Drop for LogDrop<'b> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: `#1` invokes this custom destructor - --> $DIR/drop-order-comparisons.rs:612:1 + --> $DIR/drop-order-comparisons.rs:504:1 | LL | impl<'b> Drop for LogDrop<'b> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: `_v` invokes this custom destructor - --> $DIR/drop-order-comparisons.rs:612:1 + --> $DIR/drop-order-comparisons.rs:504:1 | LL | impl<'b> Drop for LogDrop<'b> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: `#2` invokes this custom destructor - --> $DIR/drop-order-comparisons.rs:612:1 + --> $DIR/drop-order-comparisons.rs:504:1 | LL | impl<'b> Drop for LogDrop<'b> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages note: the lint level is defined here - --> $DIR/drop-order-comparisons.rs:29:25 + --> $DIR/drop-order-comparisons.rs:31:25 | LL | #![cfg_attr(e2021, warn(rust_2024_compatibility))] | ^^^^^^^^^^^^^^^^^^^^^^^ = note: `#[warn(tail_expr_drop_order)]` implied by `#[warn(rust_2024_compatibility)]` warning: relative drop order changing in Rust 2024 - --> $DIR/drop-order-comparisons.rs:101:45 + --> $DIR/drop-order-comparisons.rs:103:45 | LL | _ = ({ | _________- @@ -77,19 +77,19 @@ LL | | }, e.mark(1), e.ok(4)); = warning: this changes meaning in Rust 2024 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html> note: `#2` invokes this custom destructor - --> $DIR/drop-order-comparisons.rs:612:1 + --> $DIR/drop-order-comparisons.rs:504:1 | LL | impl<'b> Drop for LogDrop<'b> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: `#1` invokes this custom destructor - --> $DIR/drop-order-comparisons.rs:612:1 + --> $DIR/drop-order-comparisons.rs:504:1 | LL | impl<'b> Drop for LogDrop<'b> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages warning: relative drop order changing in Rust 2024 - --> $DIR/drop-order-comparisons.rs:101:19 + --> $DIR/drop-order-comparisons.rs:103:19 | LL | _ = ({ | _________- @@ -109,19 +109,19 @@ LL | | }, e.mark(1), e.ok(4)); = warning: this changes meaning in Rust 2024 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html> note: `#2` invokes this custom destructor - --> $DIR/drop-order-comparisons.rs:612:1 + --> $DIR/drop-order-comparisons.rs:504:1 | LL | impl<'b> Drop for LogDrop<'b> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: `#1` invokes this custom destructor - --> $DIR/drop-order-comparisons.rs:612:1 + --> $DIR/drop-order-comparisons.rs:504:1 | LL | impl<'b> Drop for LogDrop<'b> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages warning: relative drop order changing in Rust 2024 - --> $DIR/drop-order-comparisons.rs:222:24 + --> $DIR/drop-order-comparisons.rs:224:24 | LL | _ = ({ | _________- @@ -141,19 +141,19 @@ LL | | }, e.mark(2), e.ok(3)); = warning: this changes meaning in Rust 2024 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html> note: `#2` invokes this custom destructor - --> $DIR/drop-order-comparisons.rs:612:1 + --> $DIR/drop-order-comparisons.rs:504:1 | LL | impl<'b> Drop for LogDrop<'b> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: `#1` invokes this custom destructor - --> $DIR/drop-order-comparisons.rs:612:1 + --> $DIR/drop-order-comparisons.rs:504:1 | LL | impl<'b> Drop for LogDrop<'b> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages warning: relative drop order changing in Rust 2024 - --> $DIR/drop-order-comparisons.rs:248:24 + --> $DIR/drop-order-comparisons.rs:250:24 | LL | _ = ({ | _________- @@ -173,19 +173,19 @@ LL | | }, e.mark(2), e.ok(3)); = warning: this changes meaning in Rust 2024 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html> note: `#2` invokes this custom destructor - --> $DIR/drop-order-comparisons.rs:612:1 + --> $DIR/drop-order-comparisons.rs:504:1 | LL | impl<'b> Drop for LogDrop<'b> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: `#1` invokes this custom destructor - --> $DIR/drop-order-comparisons.rs:612:1 + --> $DIR/drop-order-comparisons.rs:504:1 | LL | impl<'b> Drop for LogDrop<'b> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages warning: `if let` assigns a shorter lifetime since Edition 2024 - --> $DIR/drop-order-comparisons.rs:124:13 + --> $DIR/drop-order-comparisons.rs:126:13 | LL | _ = (if let Ok(_) = e.ok(4).as_ref() { | ^^^^^^^^^^^^-------^^^^^^^^^ @@ -195,12 +195,12 @@ LL | _ = (if let Ok(_) = e.ok(4).as_ref() { = warning: this changes meaning in Rust 2024 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html> note: value invokes this custom destructor - --> $DIR/drop-order-comparisons.rs:612:1 + --> $DIR/drop-order-comparisons.rs:504:1 | LL | impl<'b> Drop for LogDrop<'b> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 - --> $DIR/drop-order-comparisons.rs:128:5 + --> $DIR/drop-order-comparisons.rs:130:5 | LL | }, e.mark(2), e.ok(3)); | ^ @@ -215,7 +215,7 @@ LL ~ } _ => {}}, e.mark(2), e.ok(3)); | warning: `if let` assigns a shorter lifetime since Edition 2024 - --> $DIR/drop-order-comparisons.rs:146:13 + --> $DIR/drop-order-comparisons.rs:148:13 | LL | _ = (if let Ok(_) = e.err(4).as_ref() {} else { | ^^^^^^^^^^^^--------^^^^^^^^^ @@ -225,12 +225,12 @@ LL | _ = (if let Ok(_) = e.err(4).as_ref() {} else { = warning: this changes meaning in Rust 2024 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html> note: value invokes this custom destructor - --> $DIR/drop-order-comparisons.rs:612:1 + --> $DIR/drop-order-comparisons.rs:504:1 | LL | impl<'b> Drop for LogDrop<'b> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 - --> $DIR/drop-order-comparisons.rs:146:44 + --> $DIR/drop-order-comparisons.rs:148:44 | LL | _ = (if let Ok(_) = e.err(4).as_ref() {} else { | ^ @@ -244,7 +244,7 @@ LL ~ }}, e.mark(2), e.ok(3)); | warning: `if let` assigns a shorter lifetime since Edition 2024 - --> $DIR/drop-order-comparisons.rs:248:12 + --> $DIR/drop-order-comparisons.rs:250:12 | LL | if let Ok(_) = e.err(4).as_ref() {} else { | ^^^^^^^^^^^^--------^^^^^^^^^ @@ -254,12 +254,12 @@ LL | if let Ok(_) = e.err(4).as_ref() {} else { = warning: this changes meaning in Rust 2024 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html> note: value invokes this custom destructor - --> $DIR/drop-order-comparisons.rs:612:1 + --> $DIR/drop-order-comparisons.rs:504:1 | LL | impl<'b> Drop for LogDrop<'b> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 - --> $DIR/drop-order-comparisons.rs:248:43 + --> $DIR/drop-order-comparisons.rs:250:43 | LL | if let Ok(_) = e.err(4).as_ref() {} else { | ^ @@ -273,7 +273,7 @@ LL ~ }} | warning: `if let` assigns a shorter lifetime since Edition 2024 - --> $DIR/drop-order-comparisons.rs:372:12 + --> $DIR/drop-order-comparisons.rs:321:12 | LL | if let true = e.err(9).is_ok() {} else { | ^^^^^^^^^^^--------^^^^^^^^ @@ -283,12 +283,12 @@ LL | if let true = e.err(9).is_ok() {} else { = warning: this changes meaning in Rust 2024 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html> note: value invokes this custom destructor - --> $DIR/drop-order-comparisons.rs:612:1 + --> $DIR/drop-order-comparisons.rs:504:1 | LL | impl<'b> Drop for LogDrop<'b> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 - --> $DIR/drop-order-comparisons.rs:372:41 + --> $DIR/drop-order-comparisons.rs:321:41 | LL | if let true = e.err(9).is_ok() {} else { | ^ @@ -302,7 +302,7 @@ LL ~ }}}}}}}}}; | warning: `if let` assigns a shorter lifetime since Edition 2024 - --> $DIR/drop-order-comparisons.rs:375:12 + --> $DIR/drop-order-comparisons.rs:324:12 | LL | if let Ok(_v) = e.err(8) {} else { | ^^^^^^^^^^^^^-------- @@ -312,12 +312,12 @@ LL | if let Ok(_v) = e.err(8) {} else { = warning: this changes meaning in Rust 2024 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html> note: value invokes this custom destructor - --> $DIR/drop-order-comparisons.rs:612:1 + --> $DIR/drop-order-comparisons.rs:504:1 | LL | impl<'b> Drop for LogDrop<'b> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 - --> $DIR/drop-order-comparisons.rs:375:35 + --> $DIR/drop-order-comparisons.rs:324:35 | LL | if let Ok(_v) = e.err(8) {} else { | ^ @@ -331,7 +331,7 @@ LL ~ }}}}}}}}}; | warning: `if let` assigns a shorter lifetime since Edition 2024 - --> $DIR/drop-order-comparisons.rs:378:12 + --> $DIR/drop-order-comparisons.rs:327:12 | LL | if let Ok(_) = e.err(7) {} else { | ^^^^^^^^^^^^-------- @@ -341,12 +341,12 @@ LL | if let Ok(_) = e.err(7) {} else { = warning: this changes meaning in Rust 2024 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html> note: value invokes this custom destructor - --> $DIR/drop-order-comparisons.rs:612:1 + --> $DIR/drop-order-comparisons.rs:504:1 | LL | impl<'b> Drop for LogDrop<'b> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 - --> $DIR/drop-order-comparisons.rs:378:34 + --> $DIR/drop-order-comparisons.rs:327:34 | LL | if let Ok(_) = e.err(7) {} else { | ^ @@ -360,7 +360,7 @@ LL ~ }}}}}}}}}; | warning: `if let` assigns a shorter lifetime since Edition 2024 - --> $DIR/drop-order-comparisons.rs:381:12 + --> $DIR/drop-order-comparisons.rs:330:12 | LL | if let Ok(_) = e.err(6).as_ref() {} else { | ^^^^^^^^^^^^--------^^^^^^^^^ @@ -370,12 +370,12 @@ LL | if let Ok(_) = e.err(6).as_ref() {} else { = warning: this changes meaning in Rust 2024 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html> note: value invokes this custom destructor - --> $DIR/drop-order-comparisons.rs:612:1 + --> $DIR/drop-order-comparisons.rs:504:1 | LL | impl<'b> Drop for LogDrop<'b> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 - --> $DIR/drop-order-comparisons.rs:381:43 + --> $DIR/drop-order-comparisons.rs:330:43 | LL | if let Ok(_) = e.err(6).as_ref() {} else { | ^ @@ -389,7 +389,7 @@ LL ~ }}}}}}}}}; | warning: `if let` assigns a shorter lifetime since Edition 2024 - --> $DIR/drop-order-comparisons.rs:385:12 + --> $DIR/drop-order-comparisons.rs:334:12 | LL | if let Ok(_v) = e.err(5) {} else { | ^^^^^^^^^^^^^-------- @@ -399,12 +399,12 @@ LL | if let Ok(_v) = e.err(5) {} else { = warning: this changes meaning in Rust 2024 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html> note: value invokes this custom destructor - --> $DIR/drop-order-comparisons.rs:612:1 + --> $DIR/drop-order-comparisons.rs:504:1 | LL | impl<'b> Drop for LogDrop<'b> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 - --> $DIR/drop-order-comparisons.rs:385:35 + --> $DIR/drop-order-comparisons.rs:334:35 | LL | if let Ok(_v) = e.err(5) {} else { | ^ @@ -418,7 +418,7 @@ LL ~ }}}}}}}}}; | warning: `if let` assigns a shorter lifetime since Edition 2024 - --> $DIR/drop-order-comparisons.rs:388:12 + --> $DIR/drop-order-comparisons.rs:337:12 | LL | if let Ok(_) = e.err(4) {} else { | ^^^^^^^^^^^^-------- @@ -428,12 +428,12 @@ LL | if let Ok(_) = e.err(4) {} else { = warning: this changes meaning in Rust 2024 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html> note: value invokes this custom destructor - --> $DIR/drop-order-comparisons.rs:612:1 + --> $DIR/drop-order-comparisons.rs:504:1 | LL | impl<'b> Drop for LogDrop<'b> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 - --> $DIR/drop-order-comparisons.rs:388:34 + --> $DIR/drop-order-comparisons.rs:337:34 | LL | if let Ok(_) = e.err(4) {} else { | ^ @@ -447,7 +447,7 @@ LL ~ }}}}}}}}}; | warning: `if let` assigns a shorter lifetime since Edition 2024 - --> $DIR/drop-order-comparisons.rs:424:12 + --> $DIR/drop-order-comparisons.rs:373:12 | LL | if let Ok(_) = e.err(4).as_ref() {} else { | ^^^^^^^^^^^^--------^^^^^^^^^ @@ -457,12 +457,12 @@ LL | if let Ok(_) = e.err(4).as_ref() {} else { = warning: this changes meaning in Rust 2024 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html> note: value invokes this custom destructor - --> $DIR/drop-order-comparisons.rs:612:1 + --> $DIR/drop-order-comparisons.rs:504:1 | LL | impl<'b> Drop for LogDrop<'b> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 - --> $DIR/drop-order-comparisons.rs:424:43 + --> $DIR/drop-order-comparisons.rs:373:43 | LL | if let Ok(_) = e.err(4).as_ref() {} else { | ^ diff --git a/tests/ui/drop/drop-order-comparisons.rs b/tests/ui/drop/drop-order-comparisons.rs index e7425159aa2..257c0c14ecf 100644 --- a/tests/ui/drop/drop-order-comparisons.rs +++ b/tests/ui/drop/drop-order-comparisons.rs @@ -1,3 +1,6 @@ +// N.B. drop-order-comparisons-let-chains.rs is part of this test. +// It is separate because let chains cannot be parsed before Rust 2024. +// // This tests various aspects of the drop order with a focus on: // // - The lifetime of temporaries with the `if let` construct (and with @@ -25,7 +28,6 @@ //@ run-pass #![feature(if_let_guard)] -#![cfg_attr(e2021, feature(let_chains))] #![cfg_attr(e2021, warn(rust_2024_compatibility))] fn t_bindings() { @@ -313,59 +315,6 @@ fn t_let_else_chained_then() { #[cfg(e2021)] #[rustfmt::skip] -fn t_if_let_chains_then() { - let e = Events::new(); - _ = if e.ok(1).is_ok() - && let true = e.ok(9).is_ok() - && let Ok(_v) = e.ok(5) - && let Ok(_) = e.ok(8) - && let Ok(_) = e.ok(7).as_ref() - && e.ok(2).is_ok() - && let Ok(_v) = e.ok(4) - && let Ok(_) = e.ok(6).as_ref() { - e.mark(3); - }; - e.assert(9); -} - -#[cfg(e2024)] -#[rustfmt::skip] -fn t_if_let_chains_then() { - let e = Events::new(); - _ = if e.ok(1).is_ok() - && let true = e.ok(9).is_ok() - && let Ok(_v) = e.ok(8) - && let Ok(_) = e.ok(7) - && let Ok(_) = e.ok(6).as_ref() - && e.ok(2).is_ok() - && let Ok(_v) = e.ok(5) - && let Ok(_) = e.ok(4).as_ref() { - e.mark(3); - }; - e.assert(9); -} - -#[rustfmt::skip] -fn t_guard_if_let_chains_then() { - let e = Events::new(); - _ = match () { - () if e.ok(1).is_ok() - && let true = e.ok(9).is_ok() - && let Ok(_v) = e.ok(8) - && let Ok(_) = e.ok(7) - && let Ok(_) = e.ok(6).as_ref() - && e.ok(2).is_ok() - && let Ok(_v) = e.ok(5) - && let Ok(_) = e.ok(4).as_ref() => { - e.mark(3); - } - _ => {} - }; - e.assert(9); -} - -#[cfg(e2021)] -#[rustfmt::skip] fn t_if_let_nested_else() { let e = Events::new(); _ = if e.err(1).is_ok() {} else { @@ -470,59 +419,6 @@ fn t_let_else_chained_then_else() { e.assert(9); } -#[cfg(e2021)] -#[rustfmt::skip] -fn t_if_let_chains_then_else() { - let e = Events::new(); - _ = if e.ok(1).is_ok() - && let true = e.ok(9).is_ok() - && let Ok(_v) = e.ok(4) - && let Ok(_) = e.ok(8) - && let Ok(_) = e.ok(7).as_ref() - && e.ok(2).is_ok() - && let Ok(_v) = e.ok(3) - && let Ok(_) = e.err(6) {} else { - e.mark(5); - }; - e.assert(9); -} - -#[cfg(e2024)] -#[rustfmt::skip] -fn t_if_let_chains_then_else() { - let e = Events::new(); - _ = if e.ok(1).is_ok() - && let true = e.ok(8).is_ok() - && let Ok(_v) = e.ok(7) - && let Ok(_) = e.ok(6) - && let Ok(_) = e.ok(5).as_ref() - && e.ok(2).is_ok() - && let Ok(_v) = e.ok(4) - && let Ok(_) = e.err(3) {} else { - e.mark(9); - }; - e.assert(9); -} - -#[rustfmt::skip] -fn t_guard_if_let_chains_then_else() { - let e = Events::new(); - _ = match () { - () if e.ok(1).is_ok() - && let true = e.ok(8).is_ok() - && let Ok(_v) = e.ok(7) - && let Ok(_) = e.ok(6) - && let Ok(_) = e.ok(5).as_ref() - && e.ok(2).is_ok() - && let Ok(_v) = e.ok(4) - && let Ok(_) = e.err(3) => {} - _ => { - e.mark(9); - } - }; - e.assert(9); -} - fn main() { t_bindings(); t_tuples(); @@ -540,13 +436,9 @@ fn main() { t_if_let_else_tailexpr(); t_if_let_nested_then(); t_let_else_chained_then(); - t_if_let_chains_then(); - t_guard_if_let_chains_then(); t_if_let_nested_else(); t_if_let_nested_then_else(); t_let_else_chained_then_else(); - t_if_let_chains_then_else(); - t_guard_if_let_chains_then_else(); } // # Test scaffolding diff --git a/tests/ui/drop/drop_order.rs b/tests/ui/drop/drop_order.rs index 34b1a0e8f75..ead498a21c3 100644 --- a/tests/ui/drop/drop_order.rs +++ b/tests/ui/drop/drop_order.rs @@ -5,8 +5,6 @@ //@ [edition2024] compile-flags: -Z lint-mir //@ [edition2024] edition: 2024 -#![cfg_attr(edition2021, feature(let_chains))] - use std::cell::RefCell; use std::convert::TryInto; @@ -210,68 +208,6 @@ impl DropOrderCollector { } } - fn let_chain(&self) { - // take the "then" branch - if self.option_loud_drop(1).is_some() // 1 - && self.option_loud_drop(2).is_some() // 2 - && let Some(_d) = self.option_loud_drop(4) { // 4 - self.print(3); // 3 - } - - #[cfg(edition2021)] - // take the "else" branch - if self.option_loud_drop(5).is_some() // 1 - && self.option_loud_drop(6).is_some() // 2 - && let None = self.option_loud_drop(8) { // 4 - unreachable!(); - } else { - self.print(7); // 3 - } - #[cfg(edition2024)] - // take the "else" branch - if self.option_loud_drop(5).is_some() // 1 - && self.option_loud_drop(6).is_some() // 2 - && let None = self.option_loud_drop(7) { // 4 - unreachable!(); - } else { - self.print(8); // 3 - } - - // let exprs interspersed - if self.option_loud_drop(9).is_some() // 1 - && let Some(_d) = self.option_loud_drop(13) // 5 - && self.option_loud_drop(10).is_some() // 2 - && let Some(_e) = self.option_loud_drop(12) { // 4 - self.print(11); // 3 - } - - // let exprs first - if let Some(_d) = self.option_loud_drop(18) // 5 - && let Some(_e) = self.option_loud_drop(17) // 4 - && self.option_loud_drop(14).is_some() // 1 - && self.option_loud_drop(15).is_some() { // 2 - self.print(16); // 3 - } - - // let exprs last - if self.option_loud_drop(19).is_some() // 1 - && self.option_loud_drop(20).is_some() // 2 - && let Some(_d) = self.option_loud_drop(23) // 5 - && let Some(_e) = self.option_loud_drop(22) { // 4 - self.print(21); // 3 - } - } - - fn while_(&self) { - let mut v = self.option_loud_drop(4); - while let Some(_d) = v - && self.option_loud_drop(1).is_some() - && self.option_loud_drop(2).is_some() { - self.print(3); - v = None; - } - } - fn assert_sorted(self) { assert!( self.0 @@ -313,14 +249,4 @@ fn main() { let collector = DropOrderCollector::default(); collector.match_(); collector.assert_sorted(); - - println!("-- let chain --"); - let collector = DropOrderCollector::default(); - collector.let_chain(); - collector.assert_sorted(); - - println!("-- while --"); - let collector = DropOrderCollector::default(); - collector.while_(); - collector.assert_sorted(); } diff --git a/tests/ui/drop/drop_order_let_chain.rs b/tests/ui/drop/drop_order_let_chain.rs new file mode 100644 index 00000000000..8d1b71c4dab --- /dev/null +++ b/tests/ui/drop/drop_order_let_chain.rs @@ -0,0 +1,103 @@ +//@ run-pass +//@ compile-flags: -Z validate-mir +//@ edition: 2024 + +use std::cell::RefCell; +use std::convert::TryInto; + +#[derive(Default)] +struct DropOrderCollector(RefCell<Vec<u32>>); + +struct LoudDrop<'a>(&'a DropOrderCollector, u32); + +impl Drop for LoudDrop<'_> { + fn drop(&mut self) { + println!("{}", self.1); + self.0.0.borrow_mut().push(self.1); + } +} + +impl DropOrderCollector { + fn option_loud_drop(&self, n: u32) -> Option<LoudDrop<'_>> { + Some(LoudDrop(self, n)) + } + + fn print(&self, n: u32) { + println!("{}", n); + self.0.borrow_mut().push(n) + } + + fn let_chain(&self) { + // take the "then" branch + if self.option_loud_drop(1).is_some() // 1 + && self.option_loud_drop(2).is_some() // 2 + && let Some(_d) = self.option_loud_drop(4) { // 4 + self.print(3); // 3 + } + + // take the "else" branch + if self.option_loud_drop(5).is_some() // 1 + && self.option_loud_drop(6).is_some() // 2 + && let None = self.option_loud_drop(7) { // 4 + unreachable!(); + } else { + self.print(8); // 3 + } + + // let exprs interspersed + if self.option_loud_drop(9).is_some() // 1 + && let Some(_d) = self.option_loud_drop(13) // 5 + && self.option_loud_drop(10).is_some() // 2 + && let Some(_e) = self.option_loud_drop(12) { // 4 + self.print(11); // 3 + } + + // let exprs first + if let Some(_d) = self.option_loud_drop(18) // 5 + && let Some(_e) = self.option_loud_drop(17) // 4 + && self.option_loud_drop(14).is_some() // 1 + && self.option_loud_drop(15).is_some() { // 2 + self.print(16); // 3 + } + + // let exprs last + if self.option_loud_drop(19).is_some() // 1 + && self.option_loud_drop(20).is_some() // 2 + && let Some(_d) = self.option_loud_drop(23) // 5 + && let Some(_e) = self.option_loud_drop(22) { // 4 + self.print(21); // 3 + } + } + + fn while_(&self) { + let mut v = self.option_loud_drop(4); + while let Some(_d) = v + && self.option_loud_drop(1).is_some() + && self.option_loud_drop(2).is_some() { + self.print(3); + v = None; + } + } + + fn assert_sorted(self) { + assert!( + self.0 + .into_inner() + .into_iter() + .enumerate() + .all(|(idx, item)| idx + 1 == item.try_into().unwrap()) + ); + } +} + +fn main() { + println!("-- let chain --"); + let collector = DropOrderCollector::default(); + collector.let_chain(); + collector.assert_sorted(); + + println!("-- while --"); + let collector = DropOrderCollector::default(); + collector.while_(); + collector.assert_sorted(); +} diff --git a/tests/ui/drop/issue-100276.rs b/tests/ui/drop/issue-100276.rs index 5d212b3a0a9..c8e25e48b15 100644 --- a/tests/ui/drop/issue-100276.rs +++ b/tests/ui/drop/issue-100276.rs @@ -1,11 +1,6 @@ //@ check-pass -//@ compile-flags: -Z validate-mir -//@ revisions: edition2021 edition2024 -//@ [edition2021] edition: 2021 -//@ [edition2024] compile-flags: -Z lint-mir -//@ [edition2024] edition: 2024 - -#![cfg_attr(edition2021, feature(let_chains))] +//@ compile-flags: -Z lint-mir -Z validate-mir +//@ edition: 2024 fn let_chains(entry: std::io::Result<std::fs::DirEntry>) { if let Ok(entry) = entry diff --git a/tests/ui/error-codes/E0637.stderr b/tests/ui/error-codes/E0637.stderr index 95a5a58ab85..88c08cb94ba 100644 --- a/tests/ui/error-codes/E0637.stderr +++ b/tests/ui/error-codes/E0637.stderr @@ -3,6 +3,8 @@ error[E0637]: `'_` cannot be used here | LL | fn underscore_lifetime<'_>(str1: &'_ str, str2: &'_ str) -> &'_ str { | ^^ `'_` is a reserved lifetime name + | + = help: use another lifetime specifier error[E0106]: missing lifetime specifier --> $DIR/E0637.rs:1:62 diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr index 02b9e2f06ee..9280dfdf92e 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr @@ -387,14 +387,6 @@ LL | #![link()] | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -warning: attribute should be applied to a function definition - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:62:1 - | -LL | #![cold] - | ^^^^^^^^ cannot be applied to crates - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - warning: attribute should be applied to a foreign function or static --> $DIR/issue-43106-gating-of-builtin-attrs.rs:66:1 | @@ -417,6 +409,14 @@ warning: `#[must_use]` has no effect when applied to a module LL | #![must_use] | ^^^^^^^^^^^^ +warning: attribute should be applied to a function definition + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:62:1 + | +LL | #![cold] + | ^^^^^^^^ cannot be applied to crates + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + warning: `#[macro_use]` only has an effect on `extern crate` and modules --> $DIR/issue-43106-gating-of-builtin-attrs.rs:176:5 | diff --git a/tests/ui/lint/lint-unnecessary-parens.fixed b/tests/ui/lint/lint-unnecessary-parens.fixed index a8c8dd1d512..be322a31363 100644 --- a/tests/ui/lint/lint-unnecessary-parens.fixed +++ b/tests/ui/lint/lint-unnecessary-parens.fixed @@ -1,5 +1,6 @@ //@ run-rustfix +#![feature(impl_trait_in_fn_trait_return)] #![deny(unused_parens)] #![allow(while_true)] // for rustfix @@ -16,11 +17,11 @@ fn bar(y: bool) -> X { return X { y }; //~ ERROR unnecessary parentheses around `return` value } -pub fn unused_parens_around_return_type() -> u32 { //~ ERROR unnecessary parentheses around type +pub fn around_return_type() -> u32 { //~ ERROR unnecessary parentheses around type panic!() } -pub fn unused_parens_around_block_return() -> u32 { +pub fn around_block_return() -> u32 { let _foo = { 5 //~ ERROR unnecessary parentheses around block return value }; @@ -31,10 +32,90 @@ pub trait Trait { fn test(&self); } -pub fn passes_unused_parens_lint() -> &'static (dyn Trait) { +pub fn around_multi_bound_ref() -> &'static (dyn Trait + Send) { panic!() } +//~v ERROR unnecessary parentheses around type +pub fn around_single_bound_ref() -> &'static dyn Trait { + panic!() +} + +pub fn around_multi_bound_ptr() -> *const (dyn Trait + Send) { + panic!() +} + +//~v ERROR unnecessary parentheses around type +pub fn around_single_bound_ptr() -> *const dyn Trait { + panic!() +} + +pub fn around_multi_bound_dyn_fn_output() -> &'static dyn FnOnce() -> (impl Send + Sync) { + &|| () +} + +//~v ERROR unnecessary parentheses around type +pub fn around_single_bound_dyn_fn_output() -> &'static dyn FnOnce() -> impl Send { + &|| () +} + +pub fn around_dyn_fn_output_given_more_bounds() -> &'static (dyn FnOnce() -> (impl Send) + Sync) { + &|| () +} + +pub fn around_multi_bound_impl_fn_output() -> impl FnOnce() -> (impl Send + Sync) { + || () +} + +//~v ERROR unnecessary parentheses around type +pub fn around_single_bound_impl_fn_output() -> impl FnOnce() -> impl Send { + || () +} + +pub fn around_impl_fn_output_given_more_bounds() -> impl FnOnce() -> (impl Send) + Sync { + || () +} + +//~v ERROR unnecessary parentheses around type +pub fn around_dyn_bound() -> &'static dyn FnOnce() { + &|| () +} + +//~v ERROR unnecessary parentheses around type +pub fn around_impl_trait_bound() -> impl FnOnce() { + || () +} + +// these parens aren't strictly required but they help disambiguate => no lint +pub fn around_fn_bound_with_explicit_ret_ty() -> impl (Fn() -> ()) + Send { + || () +} + +//~v ERROR unnecessary parentheses around type +pub fn around_fn_bound_with_implicit_ret_ty() -> impl Fn() + Send { + || () +} + +//~v ERROR unnecessary parentheses around type +pub fn around_last_fn_bound_with_explicit_ret_ty() -> impl Send + Fn() -> () { + || () +} + +//~v ERROR unnecessary parentheses around type +pub fn around_regular_bound1() -> &'static (dyn Send + Sync) { + &|| () +} + +//~v ERROR unnecessary parentheses around type +pub fn around_regular_bound2() -> &'static (dyn Send + Sync) { + &|| () +} + +//~v ERROR unnecessary parentheses around type +pub fn around_regular_bound3() -> &'static (dyn Send + ::std::marker::Sync) { + &|| () +} + pub fn parens_with_keyword(e: &[()]) -> i32 { if true {} //~ ERROR unnecessary parentheses around `if` while true {} //~ ERROR unnecessary parentheses around `while` diff --git a/tests/ui/lint/lint-unnecessary-parens.rs b/tests/ui/lint/lint-unnecessary-parens.rs index 02aa78283c7..dccad07311b 100644 --- a/tests/ui/lint/lint-unnecessary-parens.rs +++ b/tests/ui/lint/lint-unnecessary-parens.rs @@ -1,5 +1,6 @@ //@ run-rustfix +#![feature(impl_trait_in_fn_trait_return)] #![deny(unused_parens)] #![allow(while_true)] // for rustfix @@ -16,11 +17,11 @@ fn bar(y: bool) -> X { return (X { y }); //~ ERROR unnecessary parentheses around `return` value } -pub fn unused_parens_around_return_type() -> (u32) { //~ ERROR unnecessary parentheses around type +pub fn around_return_type() -> (u32) { //~ ERROR unnecessary parentheses around type panic!() } -pub fn unused_parens_around_block_return() -> u32 { +pub fn around_block_return() -> u32 { let _foo = { (5) //~ ERROR unnecessary parentheses around block return value }; @@ -31,10 +32,90 @@ pub trait Trait { fn test(&self); } -pub fn passes_unused_parens_lint() -> &'static (dyn Trait) { +pub fn around_multi_bound_ref() -> &'static (dyn Trait + Send) { panic!() } +//~v ERROR unnecessary parentheses around type +pub fn around_single_bound_ref() -> &'static (dyn Trait) { + panic!() +} + +pub fn around_multi_bound_ptr() -> *const (dyn Trait + Send) { + panic!() +} + +//~v ERROR unnecessary parentheses around type +pub fn around_single_bound_ptr() -> *const (dyn Trait) { + panic!() +} + +pub fn around_multi_bound_dyn_fn_output() -> &'static dyn FnOnce() -> (impl Send + Sync) { + &|| () +} + +//~v ERROR unnecessary parentheses around type +pub fn around_single_bound_dyn_fn_output() -> &'static dyn FnOnce() -> (impl Send) { + &|| () +} + +pub fn around_dyn_fn_output_given_more_bounds() -> &'static (dyn FnOnce() -> (impl Send) + Sync) { + &|| () +} + +pub fn around_multi_bound_impl_fn_output() -> impl FnOnce() -> (impl Send + Sync) { + || () +} + +//~v ERROR unnecessary parentheses around type +pub fn around_single_bound_impl_fn_output() -> impl FnOnce() -> (impl Send) { + || () +} + +pub fn around_impl_fn_output_given_more_bounds() -> impl FnOnce() -> (impl Send) + Sync { + || () +} + +//~v ERROR unnecessary parentheses around type +pub fn around_dyn_bound() -> &'static dyn (FnOnce()) { + &|| () +} + +//~v ERROR unnecessary parentheses around type +pub fn around_impl_trait_bound() -> impl (FnOnce()) { + || () +} + +// these parens aren't strictly required but they help disambiguate => no lint +pub fn around_fn_bound_with_explicit_ret_ty() -> impl (Fn() -> ()) + Send { + || () +} + +//~v ERROR unnecessary parentheses around type +pub fn around_fn_bound_with_implicit_ret_ty() -> impl (Fn()) + Send { + || () +} + +//~v ERROR unnecessary parentheses around type +pub fn around_last_fn_bound_with_explicit_ret_ty() -> impl Send + (Fn() -> ()) { + || () +} + +//~v ERROR unnecessary parentheses around type +pub fn around_regular_bound1() -> &'static (dyn (Send) + Sync) { + &|| () +} + +//~v ERROR unnecessary parentheses around type +pub fn around_regular_bound2() -> &'static (dyn Send + (Sync)) { + &|| () +} + +//~v ERROR unnecessary parentheses around type +pub fn around_regular_bound3() -> &'static (dyn Send + (::std::marker::Sync)) { + &|| () +} + pub fn parens_with_keyword(e: &[()]) -> i32 { if(true) {} //~ ERROR unnecessary parentheses around `if` while(true) {} //~ ERROR unnecessary parentheses around `while` diff --git a/tests/ui/lint/lint-unnecessary-parens.stderr b/tests/ui/lint/lint-unnecessary-parens.stderr index f2e5debd6e0..a7fc1e89c6c 100644 --- a/tests/ui/lint/lint-unnecessary-parens.stderr +++ b/tests/ui/lint/lint-unnecessary-parens.stderr @@ -1,11 +1,11 @@ error: unnecessary parentheses around `return` value - --> $DIR/lint-unnecessary-parens.rs:13:12 + --> $DIR/lint-unnecessary-parens.rs:14:12 | LL | return (1); | ^ ^ | note: the lint level is defined here - --> $DIR/lint-unnecessary-parens.rs:3:9 + --> $DIR/lint-unnecessary-parens.rs:4:9 | LL | #![deny(unused_parens)] | ^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL + return 1; | error: unnecessary parentheses around `return` value - --> $DIR/lint-unnecessary-parens.rs:16:12 + --> $DIR/lint-unnecessary-parens.rs:17:12 | LL | return (X { y }); | ^ ^ @@ -28,19 +28,19 @@ LL + return X { y }; | error: unnecessary parentheses around type - --> $DIR/lint-unnecessary-parens.rs:19:46 + --> $DIR/lint-unnecessary-parens.rs:20:32 | -LL | pub fn unused_parens_around_return_type() -> (u32) { - | ^ ^ +LL | pub fn around_return_type() -> (u32) { + | ^ ^ | help: remove these parentheses | -LL - pub fn unused_parens_around_return_type() -> (u32) { -LL + pub fn unused_parens_around_return_type() -> u32 { +LL - pub fn around_return_type() -> (u32) { +LL + pub fn around_return_type() -> u32 { | error: unnecessary parentheses around block return value - --> $DIR/lint-unnecessary-parens.rs:25:9 + --> $DIR/lint-unnecessary-parens.rs:26:9 | LL | (5) | ^ ^ @@ -52,7 +52,7 @@ LL + 5 | error: unnecessary parentheses around block return value - --> $DIR/lint-unnecessary-parens.rs:27:5 + --> $DIR/lint-unnecessary-parens.rs:28:5 | LL | (5) | ^ ^ @@ -63,8 +63,140 @@ LL - (5) LL + 5 | +error: unnecessary parentheses around type + --> $DIR/lint-unnecessary-parens.rs:40:46 + | +LL | pub fn around_single_bound_ref() -> &'static (dyn Trait) { + | ^ ^ + | +help: remove these parentheses + | +LL - pub fn around_single_bound_ref() -> &'static (dyn Trait) { +LL + pub fn around_single_bound_ref() -> &'static dyn Trait { + | + +error: unnecessary parentheses around type + --> $DIR/lint-unnecessary-parens.rs:49:44 + | +LL | pub fn around_single_bound_ptr() -> *const (dyn Trait) { + | ^ ^ + | +help: remove these parentheses + | +LL - pub fn around_single_bound_ptr() -> *const (dyn Trait) { +LL + pub fn around_single_bound_ptr() -> *const dyn Trait { + | + +error: unnecessary parentheses around type + --> $DIR/lint-unnecessary-parens.rs:58:72 + | +LL | pub fn around_single_bound_dyn_fn_output() -> &'static dyn FnOnce() -> (impl Send) { + | ^ ^ + | +help: remove these parentheses + | +LL - pub fn around_single_bound_dyn_fn_output() -> &'static dyn FnOnce() -> (impl Send) { +LL + pub fn around_single_bound_dyn_fn_output() -> &'static dyn FnOnce() -> impl Send { + | + +error: unnecessary parentheses around type + --> $DIR/lint-unnecessary-parens.rs:71:65 + | +LL | pub fn around_single_bound_impl_fn_output() -> impl FnOnce() -> (impl Send) { + | ^ ^ + | +help: remove these parentheses + | +LL - pub fn around_single_bound_impl_fn_output() -> impl FnOnce() -> (impl Send) { +LL + pub fn around_single_bound_impl_fn_output() -> impl FnOnce() -> impl Send { + | + +error: unnecessary parentheses around type + --> $DIR/lint-unnecessary-parens.rs:80:43 + | +LL | pub fn around_dyn_bound() -> &'static dyn (FnOnce()) { + | ^ ^ + | +help: remove these parentheses + | +LL - pub fn around_dyn_bound() -> &'static dyn (FnOnce()) { +LL + pub fn around_dyn_bound() -> &'static dyn FnOnce() { + | + +error: unnecessary parentheses around type + --> $DIR/lint-unnecessary-parens.rs:85:42 + | +LL | pub fn around_impl_trait_bound() -> impl (FnOnce()) { + | ^ ^ + | +help: remove these parentheses + | +LL - pub fn around_impl_trait_bound() -> impl (FnOnce()) { +LL + pub fn around_impl_trait_bound() -> impl FnOnce() { + | + +error: unnecessary parentheses around type + --> $DIR/lint-unnecessary-parens.rs:95:55 + | +LL | pub fn around_fn_bound_with_implicit_ret_ty() -> impl (Fn()) + Send { + | ^ ^ + | +help: remove these parentheses + | +LL - pub fn around_fn_bound_with_implicit_ret_ty() -> impl (Fn()) + Send { +LL + pub fn around_fn_bound_with_implicit_ret_ty() -> impl Fn() + Send { + | + +error: unnecessary parentheses around type + --> $DIR/lint-unnecessary-parens.rs:100:67 + | +LL | pub fn around_last_fn_bound_with_explicit_ret_ty() -> impl Send + (Fn() -> ()) { + | ^ ^ + | +help: remove these parentheses + | +LL - pub fn around_last_fn_bound_with_explicit_ret_ty() -> impl Send + (Fn() -> ()) { +LL + pub fn around_last_fn_bound_with_explicit_ret_ty() -> impl Send + Fn() -> () { + | + +error: unnecessary parentheses around type + --> $DIR/lint-unnecessary-parens.rs:105:49 + | +LL | pub fn around_regular_bound1() -> &'static (dyn (Send) + Sync) { + | ^ ^ + | +help: remove these parentheses + | +LL - pub fn around_regular_bound1() -> &'static (dyn (Send) + Sync) { +LL + pub fn around_regular_bound1() -> &'static (dyn Send + Sync) { + | + +error: unnecessary parentheses around type + --> $DIR/lint-unnecessary-parens.rs:110:56 + | +LL | pub fn around_regular_bound2() -> &'static (dyn Send + (Sync)) { + | ^ ^ + | +help: remove these parentheses + | +LL - pub fn around_regular_bound2() -> &'static (dyn Send + (Sync)) { +LL + pub fn around_regular_bound2() -> &'static (dyn Send + Sync) { + | + +error: unnecessary parentheses around type + --> $DIR/lint-unnecessary-parens.rs:115:56 + | +LL | pub fn around_regular_bound3() -> &'static (dyn Send + (::std::marker::Sync)) { + | ^ ^ + | +help: remove these parentheses + | +LL - pub fn around_regular_bound3() -> &'static (dyn Send + (::std::marker::Sync)) { +LL + pub fn around_regular_bound3() -> &'static (dyn Send + ::std::marker::Sync) { + | + error: unnecessary parentheses around `if` condition - --> $DIR/lint-unnecessary-parens.rs:39:7 + --> $DIR/lint-unnecessary-parens.rs:120:7 | LL | if(true) {} | ^ ^ @@ -76,7 +208,7 @@ LL + if true {} | error: unnecessary parentheses around `while` condition - --> $DIR/lint-unnecessary-parens.rs:40:10 + --> $DIR/lint-unnecessary-parens.rs:121:10 | LL | while(true) {} | ^ ^ @@ -88,7 +220,7 @@ LL + while true {} | error: unnecessary parentheses around `for` iterator expression - --> $DIR/lint-unnecessary-parens.rs:41:13 + --> $DIR/lint-unnecessary-parens.rs:122:13 | LL | for _ in(e) {} | ^ ^ @@ -100,7 +232,7 @@ LL + for _ in e {} | error: unnecessary parentheses around `match` scrutinee expression - --> $DIR/lint-unnecessary-parens.rs:42:10 + --> $DIR/lint-unnecessary-parens.rs:123:10 | LL | match(1) { _ => ()} | ^ ^ @@ -112,7 +244,7 @@ LL + match 1 { _ => ()} | error: unnecessary parentheses around `return` value - --> $DIR/lint-unnecessary-parens.rs:43:11 + --> $DIR/lint-unnecessary-parens.rs:124:11 | LL | return(1); | ^ ^ @@ -124,7 +256,7 @@ LL + return 1; | error: unnecessary parentheses around assigned value - --> $DIR/lint-unnecessary-parens.rs:74:31 + --> $DIR/lint-unnecessary-parens.rs:155:31 | LL | pub const CONST_ITEM: usize = (10); | ^ ^ @@ -136,7 +268,7 @@ LL + pub const CONST_ITEM: usize = 10; | error: unnecessary parentheses around assigned value - --> $DIR/lint-unnecessary-parens.rs:75:33 + --> $DIR/lint-unnecessary-parens.rs:156:33 | LL | pub static STATIC_ITEM: usize = (10); | ^ ^ @@ -148,7 +280,7 @@ LL + pub static STATIC_ITEM: usize = 10; | error: unnecessary parentheses around function argument - --> $DIR/lint-unnecessary-parens.rs:79:9 + --> $DIR/lint-unnecessary-parens.rs:160:9 | LL | bar((true)); | ^ ^ @@ -160,7 +292,7 @@ LL + bar(true); | error: unnecessary parentheses around `if` condition - --> $DIR/lint-unnecessary-parens.rs:81:8 + --> $DIR/lint-unnecessary-parens.rs:162:8 | LL | if (true) {} | ^ ^ @@ -172,7 +304,7 @@ LL + if true {} | error: unnecessary parentheses around `while` condition - --> $DIR/lint-unnecessary-parens.rs:82:11 + --> $DIR/lint-unnecessary-parens.rs:163:11 | LL | while (true) {} | ^ ^ @@ -184,7 +316,7 @@ LL + while true {} | error: unnecessary parentheses around `match` scrutinee expression - --> $DIR/lint-unnecessary-parens.rs:83:11 + --> $DIR/lint-unnecessary-parens.rs:164:11 | LL | match (true) { | ^ ^ @@ -196,7 +328,7 @@ LL + match true { | error: unnecessary parentheses around `let` scrutinee expression - --> $DIR/lint-unnecessary-parens.rs:86:16 + --> $DIR/lint-unnecessary-parens.rs:167:16 | LL | if let 1 = (1) {} | ^ ^ @@ -208,7 +340,7 @@ LL + if let 1 = 1 {} | error: unnecessary parentheses around `let` scrutinee expression - --> $DIR/lint-unnecessary-parens.rs:87:19 + --> $DIR/lint-unnecessary-parens.rs:168:19 | LL | while let 1 = (2) {} | ^ ^ @@ -220,7 +352,7 @@ LL + while let 1 = 2 {} | error: unnecessary parentheses around method argument - --> $DIR/lint-unnecessary-parens.rs:103:24 + --> $DIR/lint-unnecessary-parens.rs:184:24 | LL | X { y: false }.foo((true)); | ^ ^ @@ -232,7 +364,7 @@ LL + X { y: false }.foo(true); | error: unnecessary parentheses around assigned value - --> $DIR/lint-unnecessary-parens.rs:105:18 + --> $DIR/lint-unnecessary-parens.rs:186:18 | LL | let mut _a = (0); | ^ ^ @@ -244,7 +376,7 @@ LL + let mut _a = 0; | error: unnecessary parentheses around assigned value - --> $DIR/lint-unnecessary-parens.rs:106:10 + --> $DIR/lint-unnecessary-parens.rs:187:10 | LL | _a = (0); | ^ ^ @@ -256,7 +388,7 @@ LL + _a = 0; | error: unnecessary parentheses around assigned value - --> $DIR/lint-unnecessary-parens.rs:107:11 + --> $DIR/lint-unnecessary-parens.rs:188:11 | LL | _a += (1); | ^ ^ @@ -268,7 +400,7 @@ LL + _a += 1; | error: unnecessary parentheses around pattern - --> $DIR/lint-unnecessary-parens.rs:109:8 + --> $DIR/lint-unnecessary-parens.rs:190:8 | LL | let(mut _a) = 3; | ^ ^ @@ -280,7 +412,7 @@ LL + let mut _a = 3; | error: unnecessary parentheses around pattern - --> $DIR/lint-unnecessary-parens.rs:110:9 + --> $DIR/lint-unnecessary-parens.rs:191:9 | LL | let (mut _a) = 3; | ^ ^ @@ -292,7 +424,7 @@ LL + let mut _a = 3; | error: unnecessary parentheses around pattern - --> $DIR/lint-unnecessary-parens.rs:111:8 + --> $DIR/lint-unnecessary-parens.rs:192:8 | LL | let( mut _a) = 3; | ^^ ^ @@ -304,7 +436,7 @@ LL + let mut _a = 3; | error: unnecessary parentheses around pattern - --> $DIR/lint-unnecessary-parens.rs:113:8 + --> $DIR/lint-unnecessary-parens.rs:194:8 | LL | let(_a) = 3; | ^ ^ @@ -316,7 +448,7 @@ LL + let _a = 3; | error: unnecessary parentheses around pattern - --> $DIR/lint-unnecessary-parens.rs:114:9 + --> $DIR/lint-unnecessary-parens.rs:195:9 | LL | let (_a) = 3; | ^ ^ @@ -328,7 +460,7 @@ LL + let _a = 3; | error: unnecessary parentheses around pattern - --> $DIR/lint-unnecessary-parens.rs:115:8 + --> $DIR/lint-unnecessary-parens.rs:196:8 | LL | let( _a) = 3; | ^^ ^ @@ -340,7 +472,7 @@ LL + let _a = 3; | error: unnecessary parentheses around block return value - --> $DIR/lint-unnecessary-parens.rs:121:9 + --> $DIR/lint-unnecessary-parens.rs:202:9 | LL | (unit!() - One) | ^ ^ @@ -352,7 +484,7 @@ LL + unit!() - One | error: unnecessary parentheses around block return value - --> $DIR/lint-unnecessary-parens.rs:123:9 + --> $DIR/lint-unnecessary-parens.rs:204:9 | LL | (unit![] - One) | ^ ^ @@ -364,7 +496,7 @@ LL + unit![] - One | error: unnecessary parentheses around block return value - --> $DIR/lint-unnecessary-parens.rs:126:9 + --> $DIR/lint-unnecessary-parens.rs:207:9 | LL | (unit! {} - One) | ^ ^ @@ -376,7 +508,7 @@ LL + unit! {} - One | error: unnecessary parentheses around assigned value - --> $DIR/lint-unnecessary-parens.rs:131:14 + --> $DIR/lint-unnecessary-parens.rs:212:14 | LL | let _r = (&x); | ^ ^ @@ -388,7 +520,7 @@ LL + let _r = &x; | error: unnecessary parentheses around assigned value - --> $DIR/lint-unnecessary-parens.rs:132:14 + --> $DIR/lint-unnecessary-parens.rs:213:14 | LL | let _r = (&mut x); | ^ ^ @@ -399,5 +531,5 @@ LL - let _r = (&mut x); LL + let _r = &mut x; | -error: aborting due to 33 previous errors +error: aborting due to 44 previous errors diff --git a/tests/ui/lint/unused/issue-105061-should-lint.rs b/tests/ui/lint/unused/issue-105061-should-lint.rs index 433c2882089..74a0ff83739 100644 --- a/tests/ui/lint/unused/issue-105061-should-lint.rs +++ b/tests/ui/lint/unused/issue-105061-should-lint.rs @@ -14,7 +14,7 @@ where trait Hello<T> {} fn with_dyn_bound<T>() where - (dyn Hello<(for<'b> fn(&'b ()))>): Hello<T> //~ ERROR unnecessary parentheses around type + dyn Hello<(for<'b> fn(&'b ()))>: Hello<T> //~ ERROR unnecessary parentheses around type {} fn main() { diff --git a/tests/ui/lint/unused/issue-105061-should-lint.stderr b/tests/ui/lint/unused/issue-105061-should-lint.stderr index e591f1ffb6b..ae69f018eae 100644 --- a/tests/ui/lint/unused/issue-105061-should-lint.stderr +++ b/tests/ui/lint/unused/issue-105061-should-lint.stderr @@ -17,15 +17,15 @@ LL + for<'b> for<'a> fn(Inv<'a>): Trait<'b>, | error: unnecessary parentheses around type - --> $DIR/issue-105061-should-lint.rs:17:16 + --> $DIR/issue-105061-should-lint.rs:17:15 | -LL | (dyn Hello<(for<'b> fn(&'b ()))>): Hello<T> - | ^ ^ +LL | dyn Hello<(for<'b> fn(&'b ()))>: Hello<T> + | ^ ^ | help: remove these parentheses | -LL - (dyn Hello<(for<'b> fn(&'b ()))>): Hello<T> -LL + (dyn Hello<for<'b> fn(&'b ())>): Hello<T> +LL - dyn Hello<(for<'b> fn(&'b ()))>: Hello<T> +LL + dyn Hello<for<'b> fn(&'b ())>: Hello<T> | error: aborting due to 2 previous errors diff --git a/tests/ui/lint/unused/unused-parens-trait-obj.edition2018.fixed b/tests/ui/lint/unused/unused-parens-trait-obj.edition2018.fixed new file mode 100644 index 00000000000..f95418868e1 --- /dev/null +++ b/tests/ui/lint/unused/unused-parens-trait-obj.edition2018.fixed @@ -0,0 +1,27 @@ +//@ revisions: edition2015 edition2018 +//@[edition2015] check-pass +//@[edition2015] edition: 2015 +//@[edition2018] run-rustfix +//@[edition2018] edition: 2018 + +#![deny(unused_parens)] + +#[allow(unused)] +macro_rules! edition2015_only { + () => { + mod dyn { + pub type IsAContextualKeywordIn2015 = (); + } + + pub type DynIsAContextualKeywordIn2015A = dyn::IsAContextualKeywordIn2015; + } +} + +#[cfg(edition2015)] +edition2015_only!(); + +// there's a lint for 2018 and later only because of how dyn is parsed in edition 2015 +//[edition2018]~v ERROR unnecessary parentheses around type +pub type DynIsAContextualKeywordIn2015B = Box<dyn ::std::ops::Fn()>; + +fn main() {} diff --git a/tests/ui/lint/unused/unused-parens-trait-obj.edition2018.stderr b/tests/ui/lint/unused/unused-parens-trait-obj.edition2018.stderr new file mode 100644 index 00000000000..aed8cec68e8 --- /dev/null +++ b/tests/ui/lint/unused/unused-parens-trait-obj.edition2018.stderr @@ -0,0 +1,19 @@ +error: unnecessary parentheses around type + --> $DIR/unused-parens-trait-obj.rs:25:51 + | +LL | pub type DynIsAContextualKeywordIn2015B = Box<dyn (::std::ops::Fn())>; + | ^ ^ + | +note: the lint level is defined here + --> $DIR/unused-parens-trait-obj.rs:7:9 + | +LL | #![deny(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - pub type DynIsAContextualKeywordIn2015B = Box<dyn (::std::ops::Fn())>; +LL + pub type DynIsAContextualKeywordIn2015B = Box<dyn ::std::ops::Fn()>; + | + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/unused/unused-parens-trait-obj.rs b/tests/ui/lint/unused/unused-parens-trait-obj.rs new file mode 100644 index 00000000000..2192baa2e02 --- /dev/null +++ b/tests/ui/lint/unused/unused-parens-trait-obj.rs @@ -0,0 +1,27 @@ +//@ revisions: edition2015 edition2018 +//@[edition2015] check-pass +//@[edition2015] edition: 2015 +//@[edition2018] run-rustfix +//@[edition2018] edition: 2018 + +#![deny(unused_parens)] + +#[allow(unused)] +macro_rules! edition2015_only { + () => { + mod dyn { + pub type IsAContextualKeywordIn2015 = (); + } + + pub type DynIsAContextualKeywordIn2015A = dyn::IsAContextualKeywordIn2015; + } +} + +#[cfg(edition2015)] +edition2015_only!(); + +// there's a lint for 2018 and later only because of how dyn is parsed in edition 2015 +//[edition2018]~v ERROR unnecessary parentheses around type +pub type DynIsAContextualKeywordIn2015B = Box<dyn (::std::ops::Fn())>; + +fn main() {} diff --git a/tests/ui/loop-match/invalid.rs b/tests/ui/loop-match/invalid.rs index 2ddc19f4fc6..0c47b1e0057 100644 --- a/tests/ui/loop-match/invalid.rs +++ b/tests/ui/loop-match/invalid.rs @@ -159,3 +159,34 @@ fn arm_has_guard(cond: bool) { } } } + +fn non_exhaustive() { + let mut state = State::A; + #[loop_match] + loop { + state = 'blk: { + match state { + //~^ ERROR non-exhaustive patterns: `State::B` and `State::C` not covered + State::A => State::B, + } + } + } +} + +fn invalid_range_pattern(state: f32) { + #[loop_match] + loop { + state = 'blk: { + match state { + 1.0 => { + #[const_continue] + break 'blk 2.5; + } + 4.0..3.0 => { + //~^ ERROR lower range bound must be less than upper + todo!() + } + } + } + } +} diff --git a/tests/ui/loop-match/invalid.stderr b/tests/ui/loop-match/invalid.stderr index 51fdd024c6f..70f246caa9c 100644 --- a/tests/ui/loop-match/invalid.stderr +++ b/tests/ui/loop-match/invalid.stderr @@ -86,6 +86,36 @@ error: match arms that are part of a `#[loop_match]` cannot have guards LL | State::B if cond => break 'a, | ^^^^ -error: aborting due to 12 previous errors +error[E0004]: non-exhaustive patterns: `State::B` and `State::C` not covered + --> $DIR/invalid.rs:168:19 + | +LL | match state { + | ^^^^^ patterns `State::B` and `State::C` not covered + | +note: `State` defined here + --> $DIR/invalid.rs:7:6 + | +LL | enum State { + | ^^^^^ +LL | A, +LL | B, + | - not covered +LL | C, + | - not covered + = note: the matched value is of type `State` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ State::A => State::B, +LL ~ State::B | State::C => todo!(), + | + +error[E0579]: lower range bound must be less than upper + --> $DIR/invalid.rs:185:17 + | +LL | 4.0..3.0 => { + | ^^^^^^^^ + +error: aborting due to 14 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0004, E0308, E0579. +For more information about an error, try `rustc --explain E0004`. diff --git a/tests/ui/macros/missing-semi.stderr b/tests/ui/macros/missing-semi.stderr index 0a7afe50059..c2e12adbb4b 100644 --- a/tests/ui/macros/missing-semi.stderr +++ b/tests/ui/macros/missing-semi.stderr @@ -1,8 +1,10 @@ error: expected `;`, found `(` --> $DIR/missing-semi.rs:6:5 | +LL | } + | - expected `;` LL | () => { - | ^ no rules expected this token in macro call + | ^ unexpected token error: aborting due to 1 previous error diff --git a/tests/ui/macros/stringify.rs b/tests/ui/macros/stringify.rs index c858051a7eb..fa06da5cbfb 100644 --- a/tests/ui/macros/stringify.rs +++ b/tests/ui/macros/stringify.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ edition:2021 +//@ edition:2024 //@ compile-flags: --test #![allow(incomplete_features)] @@ -10,7 +10,6 @@ #![feature(decl_macro)] #![feature(explicit_tail_calls)] #![feature(if_let_guard)] -#![feature(let_chains)] #![feature(more_qualified_paths)] #![feature(never_patterns)] #![feature(trait_alias)] diff --git a/tests/ui/mir/enum/negative_discr_break.rs b/tests/ui/mir/enum/negative_discr_break.rs new file mode 100644 index 00000000000..fa1284f72a0 --- /dev/null +++ b/tests/ui/mir/enum/negative_discr_break.rs @@ -0,0 +1,14 @@ +//@ run-fail +//@ compile-flags: -C debug-assertions +//@ error-pattern: trying to construct an enum from an invalid value 0xfd + +#[allow(dead_code)] +enum Foo { + A = -2, + B = -1, + C = 1, +} + +fn main() { + let _val: Foo = unsafe { std::mem::transmute::<i8, Foo>(-3) }; +} diff --git a/tests/ui/mir/enum/negative_discr_ok.rs b/tests/ui/mir/enum/negative_discr_ok.rs new file mode 100644 index 00000000000..5c15b33fa84 --- /dev/null +++ b/tests/ui/mir/enum/negative_discr_ok.rs @@ -0,0 +1,53 @@ +//@ run-pass +//@ compile-flags: -C debug-assertions + +#[allow(dead_code)] +#[derive(Debug, PartialEq)] +enum Foo { + A = -12121, + B = -2, + C = -1, + D = 1, + E = 2, + F = 12121, +} + +#[allow(dead_code)] +#[repr(i64)] +#[derive(Debug, PartialEq)] +enum Bar { + A = i64::MIN, + B = -2, + C = -1, + D = 1, + E = 2, + F = i64::MAX, +} + +fn main() { + let val: Foo = unsafe { std::mem::transmute::<i16, Foo>(-12121) }; + assert_eq!(val, Foo::A); + let val: Foo = unsafe { std::mem::transmute::<i16, Foo>(-2) }; + assert_eq!(val, Foo::B); + let val: Foo = unsafe { std::mem::transmute::<i16, Foo>(-1) }; + assert_eq!(val, Foo::C); + let val: Foo = unsafe { std::mem::transmute::<i16, Foo>(1) }; + assert_eq!(val, Foo::D); + let val: Foo = unsafe { std::mem::transmute::<i16, Foo>(2) }; + assert_eq!(val, Foo::E); + let val: Foo = unsafe { std::mem::transmute::<i16, Foo>(12121) }; + assert_eq!(val, Foo::F); + + let val: Bar = unsafe { std::mem::transmute::<i64, Bar>(i64::MIN) }; + assert_eq!(val, Bar::A); + let val: Bar = unsafe { std::mem::transmute::<i64, Bar>(-2) }; + assert_eq!(val, Bar::B); + let val: Bar = unsafe { std::mem::transmute::<i64, Bar>(-1) }; + assert_eq!(val, Bar::C); + let val: Bar = unsafe { std::mem::transmute::<i64, Bar>(1) }; + assert_eq!(val, Bar::D); + let val: Bar = unsafe { std::mem::transmute::<i64, Bar>(2) }; + assert_eq!(val, Bar::E); + let val: Bar = unsafe { std::mem::transmute::<i64, Bar>(i64::MAX) }; + assert_eq!(val, Bar::F); +} diff --git a/tests/ui/mir/mir_let_chains_drop_order.rs b/tests/ui/mir/mir_let_chains_drop_order.rs index 4794f3427dd..8a54f21b57f 100644 --- a/tests/ui/mir/mir_let_chains_drop_order.rs +++ b/tests/ui/mir/mir_let_chains_drop_order.rs @@ -1,12 +1,9 @@ //@ run-pass //@ needs-unwind -//@ revisions: edition2021 edition2024 -//@ [edition2021] edition: 2021 -//@ [edition2024] edition: 2024 +//@ edition: 2024 // See `mir_drop_order.rs` for more information -#![cfg_attr(edition2021, feature(let_chains))] #![allow(irrefutable_let_patterns)] use std::cell::RefCell; @@ -64,9 +61,6 @@ fn main() { d(10, None) }, ); - #[cfg(edition2021)] - assert_eq!(get(), vec![8, 7, 1, 3, 2]); - #[cfg(edition2024)] assert_eq!(get(), vec![3, 2, 8, 7, 1]); } assert_eq!(get(), vec![0, 4, 6, 9, 5]); @@ -101,8 +95,5 @@ fn main() { panic::panic_any(InjectedFailure), ); }); - #[cfg(edition2021)] - assert_eq!(get(), vec![20, 17, 15, 11, 19, 18, 16, 12, 14, 13]); - #[cfg(edition2024)] assert_eq!(get(), vec![14, 13, 19, 18, 20, 17, 15, 11, 16, 12]); } diff --git a/tests/ui/parser/issues/issue-7970b.rs b/tests/ui/parser/issues/issue-7970b.rs index 1c4abce3959..ae06aff7cef 100644 --- a/tests/ui/parser/issues/issue-7970b.rs +++ b/tests/ui/parser/issues/issue-7970b.rs @@ -1,4 +1,4 @@ fn main() {} macro_rules! test {} -//~^ ERROR unexpected end of macro invocation +//~^ ERROR macros must contain at least one rule diff --git a/tests/ui/parser/issues/issue-7970b.stderr b/tests/ui/parser/issues/issue-7970b.stderr index b23b09e752c..4715eb07c6d 100644 --- a/tests/ui/parser/issues/issue-7970b.stderr +++ b/tests/ui/parser/issues/issue-7970b.stderr @@ -1,8 +1,8 @@ -error: unexpected end of macro invocation +error: macros must contain at least one rule --> $DIR/issue-7970b.rs:3:1 | LL | macro_rules! test {} - | ^^^^^^^^^^^^^^^^^^^^ missing tokens in macro arguments + | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/parser/macros-no-semicolon-items.rs b/tests/ui/parser/macros-no-semicolon-items.rs index 3afc275d61a..86889279cea 100644 --- a/tests/ui/parser/macros-no-semicolon-items.rs +++ b/tests/ui/parser/macros-no-semicolon-items.rs @@ -1,5 +1,5 @@ macro_rules! foo() //~ ERROR semicolon - //~| ERROR unexpected end of macro + //~| ERROR macros must contain at least one rule macro_rules! bar { ($($tokens:tt)*) => {} diff --git a/tests/ui/parser/macros-no-semicolon-items.stderr b/tests/ui/parser/macros-no-semicolon-items.stderr index 07fa2439df5..f8f3ed83688 100644 --- a/tests/ui/parser/macros-no-semicolon-items.stderr +++ b/tests/ui/parser/macros-no-semicolon-items.stderr @@ -38,11 +38,11 @@ help: add a semicolon LL | ); | + -error: unexpected end of macro invocation +error: macros must contain at least one rule --> $DIR/macros-no-semicolon-items.rs:1:1 | LL | macro_rules! foo() - | ^^^^^^^^^^^^^^^^^^ missing tokens in macro arguments + | ^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui/pattern/usefulness/conflicting_bindings.rs b/tests/ui/pattern/usefulness/conflicting_bindings.rs index 16737e0a894..883ce4333ca 100644 --- a/tests/ui/pattern/usefulness/conflicting_bindings.rs +++ b/tests/ui/pattern/usefulness/conflicting_bindings.rs @@ -1,4 +1,6 @@ -#![feature(if_let_guard, let_chains)] +//@ edition: 2024 + +#![feature(if_let_guard)] fn main() { let mut x = Some(String::new()); diff --git a/tests/ui/pattern/usefulness/conflicting_bindings.stderr b/tests/ui/pattern/usefulness/conflicting_bindings.stderr index 6f6504e6f64..7ab3393c8d1 100644 --- a/tests/ui/pattern/usefulness/conflicting_bindings.stderr +++ b/tests/ui/pattern/usefulness/conflicting_bindings.stderr @@ -1,5 +1,5 @@ error: cannot borrow value as mutable more than once at a time - --> $DIR/conflicting_bindings.rs:5:9 + --> $DIR/conflicting_bindings.rs:7:9 | LL | let ref mut y @ ref mut z = x; | ^^^^^^^^^ --------- value is mutably borrowed by `z` here @@ -7,7 +7,7 @@ LL | let ref mut y @ ref mut z = x; | value is mutably borrowed by `y` here error: cannot borrow value as mutable more than once at a time - --> $DIR/conflicting_bindings.rs:7:14 + --> $DIR/conflicting_bindings.rs:9:14 | LL | let Some(ref mut y @ ref mut z) = x else { return }; | ^^^^^^^^^ --------- value is mutably borrowed by `z` here @@ -15,7 +15,7 @@ LL | let Some(ref mut y @ ref mut z) = x else { return }; | value is mutably borrowed by `y` here error: cannot borrow value as mutable more than once at a time - --> $DIR/conflicting_bindings.rs:9:17 + --> $DIR/conflicting_bindings.rs:11:17 | LL | if let Some(ref mut y @ ref mut z) = x {} | ^^^^^^^^^ --------- value is mutably borrowed by `z` here @@ -23,7 +23,7 @@ LL | if let Some(ref mut y @ ref mut z) = x {} | value is mutably borrowed by `y` here error: cannot borrow value as mutable more than once at a time - --> $DIR/conflicting_bindings.rs:11:17 + --> $DIR/conflicting_bindings.rs:13:17 | LL | if let Some(ref mut y @ ref mut z) = x && true {} | ^^^^^^^^^ --------- value is mutably borrowed by `z` here @@ -31,7 +31,7 @@ LL | if let Some(ref mut y @ ref mut z) = x && true {} | value is mutably borrowed by `y` here error: cannot borrow value as mutable more than once at a time - --> $DIR/conflicting_bindings.rs:13:43 + --> $DIR/conflicting_bindings.rs:15:43 | LL | if let Some(_) = Some(()) && let Some(ref mut y @ ref mut z) = x && true {} | ^^^^^^^^^ --------- value is mutably borrowed by `z` here @@ -39,7 +39,7 @@ LL | if let Some(_) = Some(()) && let Some(ref mut y @ ref mut z) = x && tru | value is mutably borrowed by `y` here error: cannot borrow value as mutable more than once at a time - --> $DIR/conflicting_bindings.rs:15:20 + --> $DIR/conflicting_bindings.rs:17:20 | LL | while let Some(ref mut y @ ref mut z) = x {} | ^^^^^^^^^ --------- value is mutably borrowed by `z` here @@ -47,7 +47,7 @@ LL | while let Some(ref mut y @ ref mut z) = x {} | value is mutably borrowed by `y` here error: cannot borrow value as mutable more than once at a time - --> $DIR/conflicting_bindings.rs:17:20 + --> $DIR/conflicting_bindings.rs:19:20 | LL | while let Some(ref mut y @ ref mut z) = x && true {} | ^^^^^^^^^ --------- value is mutably borrowed by `z` here @@ -55,7 +55,7 @@ LL | while let Some(ref mut y @ ref mut z) = x && true {} | value is mutably borrowed by `y` here error: cannot borrow value as mutable more than once at a time - --> $DIR/conflicting_bindings.rs:20:9 + --> $DIR/conflicting_bindings.rs:22:9 | LL | ref mut y @ ref mut z => {} | ^^^^^^^^^ --------- value is mutably borrowed by `z` here @@ -63,7 +63,7 @@ LL | ref mut y @ ref mut z => {} | value is mutably borrowed by `y` here error: cannot borrow value as mutable more than once at a time - --> $DIR/conflicting_bindings.rs:23:24 + --> $DIR/conflicting_bindings.rs:25:24 | LL | () if let Some(ref mut y @ ref mut z) = x => {} | ^^^^^^^^^ --------- value is mutably borrowed by `z` here diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/drop-scope-let-chains.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/drop-scope-let-chains.rs new file mode 100644 index 00000000000..4d2eac2ea2d --- /dev/null +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/drop-scope-let-chains.rs @@ -0,0 +1,57 @@ +// Ensure that temporaries in if-let guards live for the arm +// regression test for #118593 + +//@ check-pass +//@ edition: 2024 + +#![feature(if_let_guard)] + +fn get_temp() -> Option<String> { + None +} + +fn let_let_chain_guard(num: u8) { + match num { + 5 | 6 + if let Some(ref a) = get_temp() + && let Some(ref b) = get_temp() => + { + let _x = a; + let _y = b; + } + _ => {} + } + match num { + 7 | 8 + if let Some(ref mut c) = get_temp() + && let Some(ref mut d) = get_temp() => + { + let _w = c; + let _z = d; + } + _ => {} + } +} + +fn let_cond_chain_guard(num: u8) { + match num { + 9 | 10 + if let Some(ref a) = get_temp() + && true => + { + let _x = a; + } + _ => {} + } + match num { + 11 | 12 + if let Some(ref mut b) = get_temp() + && true => + { + let _w = b; + } + _ => {} + } +} + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/drop-scope.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/drop-scope.rs index 0578b827a47..59e33bb6af8 100644 --- a/tests/ui/rfcs/rfc-2294-if-let-guard/drop-scope.rs +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/drop-scope.rs @@ -4,7 +4,6 @@ //@ check-pass #![feature(if_let_guard)] -#![feature(let_chains)] fn get_temp() -> Option<String> { None @@ -25,48 +24,4 @@ fn let_guard(num: u8) { } } -fn let_let_chain_guard(num: u8) { - match num { - 5 | 6 - if let Some(ref a) = get_temp() - && let Some(ref b) = get_temp() => - { - let _x = a; - let _y = b; - } - _ => {} - } - match num { - 7 | 8 - if let Some(ref mut c) = get_temp() - && let Some(ref mut d) = get_temp() => - { - let _w = c; - let _z = d; - } - _ => {} - } -} - -fn let_cond_chain_guard(num: u8) { - match num { - 9 | 10 - if let Some(ref a) = get_temp() - && true => - { - let _x = a; - } - _ => {} - } - match num { - 11 | 12 - if let Some(ref mut b) = get_temp() - && true => - { - let _w = b; - } - _ => {} - } -} - fn main() {} diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/partially-macro-expanded.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/partially-macro-expanded.rs index e836b0b88ff..294a0d02770 100644 --- a/tests/ui/rfcs/rfc-2294-if-let-guard/partially-macro-expanded.rs +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/partially-macro-expanded.rs @@ -2,7 +2,6 @@ //@ check-pass #![feature(if_let_guard)] -#![feature(let_chains)] macro_rules! m { (pattern $i:ident) => { Some($i) }; diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/scope.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/scope.rs index 56a6fb5bfa3..47cc7a64bd1 100644 --- a/tests/ui/rfcs/rfc-2294-if-let-guard/scope.rs +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/scope.rs @@ -3,7 +3,6 @@ //@run-pass #![feature(if_let_guard)] -#![feature(let_chains)] #![allow(irrefutable_let_patterns)] fn lhs_let(opt: Option<bool>) { diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.no_feature.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.e2021.stderr index dda09de4c53..15e7be8c65f 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.no_feature.stderr +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.e2021.stderr @@ -1,239 +1,263 @@ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:33:9 + --> $DIR/disallowed-positions.rs:32:9 | LL | if (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:33:9 + --> $DIR/disallowed-positions.rs:32:9 | LL | if (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:36:11 + --> $DIR/disallowed-positions.rs:35:11 | LL | if (((let 0 = 1))) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:36:11 + --> $DIR/disallowed-positions.rs:35:11 | LL | if (((let 0 = 1))) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:39:9 + --> $DIR/disallowed-positions.rs:38:9 | LL | if (let 0 = 1) && true {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:39:9 + --> $DIR/disallowed-positions.rs:38:9 | LL | if (let 0 = 1) && true {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:42:17 + --> $DIR/disallowed-positions.rs:41:17 | LL | if true && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:42:17 + --> $DIR/disallowed-positions.rs:41:17 | LL | if true && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:45:9 + --> $DIR/disallowed-positions.rs:44:9 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:45:9 + --> $DIR/disallowed-positions.rs:44:9 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:45:24 + --> $DIR/disallowed-positions.rs:44:24 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:45:24 + --> $DIR/disallowed-positions.rs:44:24 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ +error: let chains are only allowed in Rust 2024 or later + --> $DIR/disallowed-positions.rs:48:8 + | +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^ + +error: let chains are only allowed in Rust 2024 or later + --> $DIR/disallowed-positions.rs:48:21 + | +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^ + error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:49:35 + --> $DIR/disallowed-positions.rs:48:35 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:49:35 + --> $DIR/disallowed-positions.rs:48:35 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:49:48 + --> $DIR/disallowed-positions.rs:48:48 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:49:35 + --> $DIR/disallowed-positions.rs:48:35 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:49:61 + --> $DIR/disallowed-positions.rs:48:61 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:49:35 + --> $DIR/disallowed-positions.rs:48:35 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:59:12 + --> $DIR/disallowed-positions.rs:58:12 | LL | while (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:59:12 + --> $DIR/disallowed-positions.rs:58:12 | LL | while (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:62:14 + --> $DIR/disallowed-positions.rs:61:14 | LL | while (((let 0 = 1))) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:62:14 + --> $DIR/disallowed-positions.rs:61:14 | LL | while (((let 0 = 1))) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:65:12 + --> $DIR/disallowed-positions.rs:64:12 | LL | while (let 0 = 1) && true {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:65:12 + --> $DIR/disallowed-positions.rs:64:12 | LL | while (let 0 = 1) && true {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:68:20 + --> $DIR/disallowed-positions.rs:67:20 | LL | while true && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:68:20 + --> $DIR/disallowed-positions.rs:67:20 | LL | while true && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:71:12 + --> $DIR/disallowed-positions.rs:70:12 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:71:12 + --> $DIR/disallowed-positions.rs:70:12 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:71:27 + --> $DIR/disallowed-positions.rs:70:27 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:71:27 + --> $DIR/disallowed-positions.rs:70:27 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ +error: let chains are only allowed in Rust 2024 or later + --> $DIR/disallowed-positions.rs:74:11 + | +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^ + +error: let chains are only allowed in Rust 2024 or later + --> $DIR/disallowed-positions.rs:74:24 + | +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^ + error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:75:38 + --> $DIR/disallowed-positions.rs:74:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:75:38 + --> $DIR/disallowed-positions.rs:74:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:75:51 + --> $DIR/disallowed-positions.rs:74:51 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:75:38 + --> $DIR/disallowed-positions.rs:74:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:75:64 + --> $DIR/disallowed-positions.rs:74:64 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:75:38 + --> $DIR/disallowed-positions.rs:74:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:103:9 + --> $DIR/disallowed-positions.rs:102:9 | LL | if &let 0 = 0 {} | ^^^^^^^^^ @@ -241,7 +265,7 @@ LL | if &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:106:9 + --> $DIR/disallowed-positions.rs:105:9 | LL | if !let 0 = 0 {} | ^^^^^^^^^ @@ -249,7 +273,7 @@ LL | if !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:108:9 + --> $DIR/disallowed-positions.rs:107:9 | LL | if *let 0 = 0 {} | ^^^^^^^^^ @@ -257,7 +281,7 @@ LL | if *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:110:9 + --> $DIR/disallowed-positions.rs:109:9 | LL | if -let 0 = 0 {} | ^^^^^^^^^ @@ -265,7 +289,7 @@ LL | if -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:118:9 + --> $DIR/disallowed-positions.rs:117:9 | LL | if (let 0 = 0)? {} | ^^^^^^^^^ @@ -273,13 +297,13 @@ LL | if (let 0 = 0)? {} = note: only supported directly in conditions of `if` and `while` expressions error: `||` operators are not supported in let chain conditions - --> $DIR/disallowed-positions.rs:121:13 + --> $DIR/disallowed-positions.rs:120:13 | LL | if true || let 0 = 0 {} | ^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:123:17 + --> $DIR/disallowed-positions.rs:122:17 | LL | if (true || let 0 = 0) {} | ^^^^^^^^^ @@ -287,7 +311,7 @@ LL | if (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:125:25 + --> $DIR/disallowed-positions.rs:124:25 | LL | if true && (true || let 0 = 0) {} | ^^^^^^^^^ @@ -295,7 +319,7 @@ LL | if true && (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:127:25 + --> $DIR/disallowed-positions.rs:126:25 | LL | if true || (true && let 0 = 0) {} | ^^^^^^^^^ @@ -303,7 +327,7 @@ LL | if true || (true && let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:131:12 + --> $DIR/disallowed-positions.rs:130:12 | LL | if x = let 0 = 0 {} | ^^^ @@ -311,7 +335,7 @@ LL | if x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:134:15 + --> $DIR/disallowed-positions.rs:133:15 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^ @@ -319,7 +343,7 @@ LL | if true..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:137:11 + --> $DIR/disallowed-positions.rs:136:11 | LL | if ..(let 0 = 0) {} | ^^^^^^^^^ @@ -327,7 +351,7 @@ LL | if ..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:139:9 + --> $DIR/disallowed-positions.rs:138:9 | LL | if (let 0 = 0).. {} | ^^^^^^^^^ @@ -335,7 +359,7 @@ LL | if (let 0 = 0).. {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:143:8 + --> $DIR/disallowed-positions.rs:142:8 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -343,7 +367,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:146:8 + --> $DIR/disallowed-positions.rs:145:8 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -351,7 +375,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:152:8 + --> $DIR/disallowed-positions.rs:151:8 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -359,7 +383,7 @@ LL | if let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:158:8 + --> $DIR/disallowed-positions.rs:157:8 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -367,7 +391,7 @@ LL | if let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:162:19 + --> $DIR/disallowed-positions.rs:161:19 | LL | if let true = let true = true {} | ^^^ @@ -375,7 +399,7 @@ LL | if let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:165:15 + --> $DIR/disallowed-positions.rs:164:15 | LL | if return let 0 = 0 {} | ^^^ @@ -383,7 +407,7 @@ LL | if return let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:168:21 + --> $DIR/disallowed-positions.rs:167:21 | LL | loop { if break let 0 = 0 {} } | ^^^ @@ -391,7 +415,7 @@ LL | loop { if break let 0 = 0 {} } = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:171:15 + --> $DIR/disallowed-positions.rs:170:15 | LL | if (match let 0 = 0 { _ => { false } }) {} | ^^^ @@ -399,7 +423,7 @@ LL | if (match let 0 = 0 { _ => { false } }) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:174:9 + --> $DIR/disallowed-positions.rs:173:9 | LL | if (let 0 = 0, false).1 {} | ^^^^^^^^^ @@ -407,7 +431,7 @@ LL | if (let 0 = 0, false).1 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:177:9 + --> $DIR/disallowed-positions.rs:176:9 | LL | if (let 0 = 0,) {} | ^^^^^^^^^ @@ -415,7 +439,7 @@ LL | if (let 0 = 0,) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:181:13 + --> $DIR/disallowed-positions.rs:180:13 | LL | if (let 0 = 0).await {} | ^^^^^^^^^ @@ -423,7 +447,7 @@ LL | if (let 0 = 0).await {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:185:12 + --> $DIR/disallowed-positions.rs:184:12 | LL | if (|| let 0 = 0) {} | ^^^ @@ -431,7 +455,7 @@ LL | if (|| let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:188:9 + --> $DIR/disallowed-positions.rs:187:9 | LL | if (let 0 = 0)() {} | ^^^^^^^^^ @@ -439,7 +463,7 @@ LL | if (let 0 = 0)() {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:194:12 + --> $DIR/disallowed-positions.rs:193:12 | LL | while &let 0 = 0 {} | ^^^^^^^^^ @@ -447,7 +471,7 @@ LL | while &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:197:12 + --> $DIR/disallowed-positions.rs:196:12 | LL | while !let 0 = 0 {} | ^^^^^^^^^ @@ -455,7 +479,7 @@ LL | while !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:199:12 + --> $DIR/disallowed-positions.rs:198:12 | LL | while *let 0 = 0 {} | ^^^^^^^^^ @@ -463,7 +487,7 @@ LL | while *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:201:12 + --> $DIR/disallowed-positions.rs:200:12 | LL | while -let 0 = 0 {} | ^^^^^^^^^ @@ -471,7 +495,7 @@ LL | while -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:209:12 + --> $DIR/disallowed-positions.rs:208:12 | LL | while (let 0 = 0)? {} | ^^^^^^^^^ @@ -479,13 +503,13 @@ LL | while (let 0 = 0)? {} = note: only supported directly in conditions of `if` and `while` expressions error: `||` operators are not supported in let chain conditions - --> $DIR/disallowed-positions.rs:212:16 + --> $DIR/disallowed-positions.rs:211:16 | LL | while true || let 0 = 0 {} | ^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:214:20 + --> $DIR/disallowed-positions.rs:213:20 | LL | while (true || let 0 = 0) {} | ^^^^^^^^^ @@ -493,7 +517,7 @@ LL | while (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:216:28 + --> $DIR/disallowed-positions.rs:215:28 | LL | while true && (true || let 0 = 0) {} | ^^^^^^^^^ @@ -501,7 +525,7 @@ LL | while true && (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:218:28 + --> $DIR/disallowed-positions.rs:217:28 | LL | while true || (true && let 0 = 0) {} | ^^^^^^^^^ @@ -509,7 +533,7 @@ LL | while true || (true && let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:222:15 + --> $DIR/disallowed-positions.rs:221:15 | LL | while x = let 0 = 0 {} | ^^^ @@ -517,7 +541,7 @@ LL | while x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:225:18 + --> $DIR/disallowed-positions.rs:224:18 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^ @@ -525,7 +549,7 @@ LL | while true..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:228:14 + --> $DIR/disallowed-positions.rs:227:14 | LL | while ..(let 0 = 0) {} | ^^^^^^^^^ @@ -533,7 +557,7 @@ LL | while ..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:230:12 + --> $DIR/disallowed-positions.rs:229:12 | LL | while (let 0 = 0).. {} | ^^^^^^^^^ @@ -541,7 +565,7 @@ LL | while (let 0 = 0).. {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:234:11 + --> $DIR/disallowed-positions.rs:233:11 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -549,7 +573,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:237:11 + --> $DIR/disallowed-positions.rs:236:11 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -557,7 +581,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:243:11 + --> $DIR/disallowed-positions.rs:242:11 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -565,7 +589,7 @@ LL | while let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:249:11 + --> $DIR/disallowed-positions.rs:248:11 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -573,7 +597,7 @@ LL | while let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:253:22 + --> $DIR/disallowed-positions.rs:252:22 | LL | while let true = let true = true {} | ^^^ @@ -581,7 +605,7 @@ LL | while let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:256:18 + --> $DIR/disallowed-positions.rs:255:18 | LL | while return let 0 = 0 {} | ^^^ @@ -589,7 +613,7 @@ LL | while return let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:259:39 + --> $DIR/disallowed-positions.rs:258:39 | LL | 'outer: loop { while break 'outer let 0 = 0 {} } | ^^^ @@ -597,7 +621,7 @@ LL | 'outer: loop { while break 'outer let 0 = 0 {} } = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:262:18 + --> $DIR/disallowed-positions.rs:261:18 | LL | while (match let 0 = 0 { _ => { false } }) {} | ^^^ @@ -605,7 +629,7 @@ LL | while (match let 0 = 0 { _ => { false } }) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:265:12 + --> $DIR/disallowed-positions.rs:264:12 | LL | while (let 0 = 0, false).1 {} | ^^^^^^^^^ @@ -613,7 +637,7 @@ LL | while (let 0 = 0, false).1 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:268:12 + --> $DIR/disallowed-positions.rs:267:12 | LL | while (let 0 = 0,) {} | ^^^^^^^^^ @@ -621,7 +645,7 @@ LL | while (let 0 = 0,) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:272:16 + --> $DIR/disallowed-positions.rs:271:16 | LL | while (let 0 = 0).await {} | ^^^^^^^^^ @@ -629,7 +653,7 @@ LL | while (let 0 = 0).await {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:276:15 + --> $DIR/disallowed-positions.rs:275:15 | LL | while (|| let 0 = 0) {} | ^^^ @@ -637,7 +661,7 @@ LL | while (|| let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:279:12 + --> $DIR/disallowed-positions.rs:278:12 | LL | while (let 0 = 0)() {} | ^^^^^^^^^ @@ -645,7 +669,7 @@ LL | while (let 0 = 0)() {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:296:6 + --> $DIR/disallowed-positions.rs:295:6 | LL | &let 0 = 0; | ^^^ @@ -653,7 +677,7 @@ LL | &let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:299:6 + --> $DIR/disallowed-positions.rs:298:6 | LL | !let 0 = 0; | ^^^ @@ -661,7 +685,7 @@ LL | !let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:301:6 + --> $DIR/disallowed-positions.rs:300:6 | LL | *let 0 = 0; | ^^^ @@ -669,7 +693,7 @@ LL | *let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:303:6 + --> $DIR/disallowed-positions.rs:302:6 | LL | -let 0 = 0; | ^^^ @@ -677,7 +701,7 @@ LL | -let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:305:13 + --> $DIR/disallowed-positions.rs:304:13 | LL | let _ = let _ = 3; | ^^^ @@ -685,7 +709,7 @@ LL | let _ = let _ = 3; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:313:6 + --> $DIR/disallowed-positions.rs:312:6 | LL | (let 0 = 0)?; | ^^^ @@ -693,7 +717,7 @@ LL | (let 0 = 0)?; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:316:13 + --> $DIR/disallowed-positions.rs:315:13 | LL | true || let 0 = 0; | ^^^ @@ -701,7 +725,7 @@ LL | true || let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:318:14 + --> $DIR/disallowed-positions.rs:317:14 | LL | (true || let 0 = 0); | ^^^ @@ -709,7 +733,7 @@ LL | (true || let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:320:22 + --> $DIR/disallowed-positions.rs:319:22 | LL | true && (true || let 0 = 0); | ^^^ @@ -717,7 +741,7 @@ LL | true && (true || let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:324:9 + --> $DIR/disallowed-positions.rs:323:9 | LL | x = let 0 = 0; | ^^^ @@ -725,7 +749,7 @@ LL | x = let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:327:12 + --> $DIR/disallowed-positions.rs:326:12 | LL | true..(let 0 = 0); | ^^^ @@ -733,7 +757,7 @@ LL | true..(let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:329:8 + --> $DIR/disallowed-positions.rs:328:8 | LL | ..(let 0 = 0); | ^^^ @@ -741,7 +765,7 @@ LL | ..(let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:331:6 + --> $DIR/disallowed-positions.rs:330:6 | LL | (let 0 = 0)..; | ^^^ @@ -749,7 +773,7 @@ LL | (let 0 = 0)..; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:334:6 + --> $DIR/disallowed-positions.rs:333:6 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^ @@ -757,7 +781,7 @@ LL | (let Range { start: _, end: _ } = true..true || false); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:338:6 + --> $DIR/disallowed-positions.rs:337:6 | LL | (let true = let true = true); | ^^^ @@ -765,7 +789,7 @@ LL | (let true = let true = true); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:338:17 + --> $DIR/disallowed-positions.rs:337:17 | LL | (let true = let true = true); | ^^^ @@ -773,7 +797,7 @@ LL | (let true = let true = true); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:344:25 + --> $DIR/disallowed-positions.rs:343:25 | LL | let x = true && let y = 1; | ^^^ @@ -781,7 +805,7 @@ LL | let x = true && let y = 1; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:350:19 + --> $DIR/disallowed-positions.rs:349:19 | LL | [1, 2, 3][let _ = ()] | ^^^ @@ -789,7 +813,7 @@ LL | [1, 2, 3][let _ = ()] = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:355:6 + --> $DIR/disallowed-positions.rs:354:6 | LL | &let 0 = 0 | ^^^ @@ -797,7 +821,7 @@ LL | &let 0 = 0 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:366:17 + --> $DIR/disallowed-positions.rs:365:17 | LL | true && let 1 = 1 | ^^^ @@ -805,7 +829,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:371:17 + --> $DIR/disallowed-positions.rs:370:17 | LL | true && let 1 = 1 | ^^^ @@ -813,7 +837,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:376:17 + --> $DIR/disallowed-positions.rs:375:17 | LL | true && let 1 = 1 | ^^^ @@ -821,7 +845,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:387:17 + --> $DIR/disallowed-positions.rs:386:17 | LL | true && let 1 = 1 | ^^^ @@ -829,7 +853,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/disallowed-positions.rs:387:9 + --> $DIR/disallowed-positions.rs:386:9 | LL | true && let 1 = 1 | ^^^^^^^^^^^^^^^^^ @@ -840,124 +864,154 @@ LL | { true && let 1 = 1 } | + + error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:397:9 + --> $DIR/disallowed-positions.rs:396:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:397:9 + --> $DIR/disallowed-positions.rs:396:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:401:9 + --> $DIR/disallowed-positions.rs:400:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:401:9 + --> $DIR/disallowed-positions.rs:400:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:404:9 + --> $DIR/disallowed-positions.rs:403:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:404:9 + --> $DIR/disallowed-positions.rs:403:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:404:32 + --> $DIR/disallowed-positions.rs:403:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:404:32 + --> $DIR/disallowed-positions.rs:403:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ +error: let chains are only allowed in Rust 2024 or later + --> $DIR/disallowed-positions.rs:407:8 + | +LL | if let Some(a) = opt && (true && true) { + | ^^^^^^^^^^^^^^^^^ + error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:412:9 + --> $DIR/disallowed-positions.rs:411:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:412:9 + --> $DIR/disallowed-positions.rs:411:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:412:31 + --> $DIR/disallowed-positions.rs:411:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:412:31 + --> $DIR/disallowed-positions.rs:411:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:416:9 + --> $DIR/disallowed-positions.rs:415:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:416:9 + --> $DIR/disallowed-positions.rs:415:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:416:31 + --> $DIR/disallowed-positions.rs:415:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:416:31 + --> $DIR/disallowed-positions.rs:415:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:420:9 + --> $DIR/disallowed-positions.rs:419:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:420:9 + --> $DIR/disallowed-positions.rs:419:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: let chains are only allowed in Rust 2024 or later + --> $DIR/disallowed-positions.rs:423:28 + | +LL | if (true && (true)) && let Some(a) = opt { + | ^^^^^^^^^^^^^^^^^ + +error: let chains are only allowed in Rust 2024 or later + --> $DIR/disallowed-positions.rs:426:18 + | +LL | if (true) && let Some(a) = opt { + | ^^^^^^^^^^^^^^^^^ + +error: let chains are only allowed in Rust 2024 or later + --> $DIR/disallowed-positions.rs:429:16 + | +LL | if true && let Some(a) = opt { + | ^^^^^^^^^^^^^^^^^ + +error: let chains are only allowed in Rust 2024 or later + --> $DIR/disallowed-positions.rs:434:8 + | +LL | if let true = (true && fun()) && (true) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:440:22 + --> $DIR/disallowed-positions.rs:439:22 | LL | let x = (true && let y = 1); | ^^^ @@ -965,7 +1019,7 @@ LL | let x = (true && let y = 1); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:445:20 + --> $DIR/disallowed-positions.rs:444:20 | LL | ([1, 2, 3][let _ = ()]) | ^^^ @@ -973,7 +1027,7 @@ LL | ([1, 2, 3][let _ = ()]) = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:91:16 + --> $DIR/disallowed-positions.rs:90:16 | LL | use_expr!((let 0 = 1 && 0 == 0)); | ^^^ @@ -981,7 +1035,7 @@ LL | use_expr!((let 0 = 1 && 0 == 0)); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:91:16 + --> $DIR/disallowed-positions.rs:90:16 | LL | use_expr!((let 0 = 1 && 0 == 0)); | ^^^ @@ -990,7 +1044,7 @@ LL | use_expr!((let 0 = 1 && 0 == 0)); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:91:16 + --> $DIR/disallowed-positions.rs:90:16 | LL | use_expr!((let 0 = 1 && 0 == 0)); | ^^^ @@ -999,7 +1053,7 @@ LL | use_expr!((let 0 = 1 && 0 == 0)); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:95:16 + --> $DIR/disallowed-positions.rs:94:16 | LL | use_expr!((let 0 = 1)); | ^^^ @@ -1007,7 +1061,7 @@ LL | use_expr!((let 0 = 1)); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:95:16 + --> $DIR/disallowed-positions.rs:94:16 | LL | use_expr!((let 0 = 1)); | ^^^ @@ -1016,7 +1070,7 @@ LL | use_expr!((let 0 = 1)); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:95:16 + --> $DIR/disallowed-positions.rs:94:16 | LL | use_expr!((let 0 = 1)); | ^^^ @@ -1024,98 +1078,8 @@ LL | use_expr!((let 0 = 1)); = note: only supported directly in conditions of `if` and `while` expressions = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0658]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:49:8 - | -LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^ - | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` 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]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:49:21 - | -LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^ - | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` 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]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:75:11 - | -LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^ - | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` 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]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:75:24 - | -LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^ - | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` 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]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:408:8 - | -LL | if let Some(a) = opt && (true && true) { - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` 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]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:424:28 - | -LL | if (true && (true)) && let Some(a) = opt { - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` 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]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:427:18 - | -LL | if (true) && let Some(a) = opt { - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` 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]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:430:16 - | -LL | if true && let Some(a) = opt { - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` 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]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:435:8 - | -LL | if let true = (true && fun()) && (true) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` 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[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:134:8 + --> $DIR/disallowed-positions.rs:133:8 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>` @@ -1124,7 +1088,7 @@ LL | if true..(let 0 = 0) {} found struct `std::ops::Range<bool>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:143:12 + --> $DIR/disallowed-positions.rs:142:12 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1135,7 +1099,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:146:12 + --> $DIR/disallowed-positions.rs:145:12 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1146,7 +1110,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:152:12 + --> $DIR/disallowed-positions.rs:151:12 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` @@ -1157,7 +1121,7 @@ LL | if let Range { start: F, end } = F..|| true {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:158:12 + --> $DIR/disallowed-positions.rs:157:12 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` @@ -1168,7 +1132,7 @@ LL | if let Range { start: true, end } = t..&&false {} found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:114:20 + --> $DIR/disallowed-positions.rs:113:20 | LL | if let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` @@ -1176,7 +1140,7 @@ LL | if let 0 = 0? {} = help: the trait `Try` is not implemented for `{integer}` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:225:11 + --> $DIR/disallowed-positions.rs:224:11 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>` @@ -1185,7 +1149,7 @@ LL | while true..(let 0 = 0) {} found struct `std::ops::Range<bool>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:234:15 + --> $DIR/disallowed-positions.rs:233:15 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1196,7 +1160,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:237:15 + --> $DIR/disallowed-positions.rs:236:15 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1207,7 +1171,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:243:15 + --> $DIR/disallowed-positions.rs:242:15 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` @@ -1218,7 +1182,7 @@ LL | while let Range { start: F, end } = F..|| true {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:249:15 + --> $DIR/disallowed-positions.rs:248:15 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` @@ -1229,7 +1193,7 @@ LL | while let Range { start: true, end } = t..&&false {} found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:205:23 + --> $DIR/disallowed-positions.rs:204:23 | LL | while let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` @@ -1237,7 +1201,7 @@ LL | while let 0 = 0? {} = help: the trait `Try` is not implemented for `{integer}` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:334:10 + --> $DIR/disallowed-positions.rs:333:10 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1248,7 +1212,7 @@ LL | (let Range { start: _, end: _ } = true..true || false); found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:309:17 + --> $DIR/disallowed-positions.rs:308:17 | LL | let 0 = 0?; | ^^ the `?` operator cannot be applied to type `{integer}` @@ -1257,5 +1221,5 @@ LL | let 0 = 0?; error: aborting due to 134 previous errors -Some errors have detailed explanations: E0277, E0308, E0658. +Some errors have detailed explanations: E0277, E0308. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.feature.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.e2024.stderr index 141a6d255d0..20af65cf89a 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.feature.stderr +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.e2024.stderr @@ -1,239 +1,239 @@ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:33:9 + --> $DIR/disallowed-positions.rs:32:9 | LL | if (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:33:9 + --> $DIR/disallowed-positions.rs:32:9 | LL | if (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:36:11 + --> $DIR/disallowed-positions.rs:35:11 | LL | if (((let 0 = 1))) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:36:11 + --> $DIR/disallowed-positions.rs:35:11 | LL | if (((let 0 = 1))) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:39:9 + --> $DIR/disallowed-positions.rs:38:9 | LL | if (let 0 = 1) && true {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:39:9 + --> $DIR/disallowed-positions.rs:38:9 | LL | if (let 0 = 1) && true {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:42:17 + --> $DIR/disallowed-positions.rs:41:17 | LL | if true && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:42:17 + --> $DIR/disallowed-positions.rs:41:17 | LL | if true && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:45:9 + --> $DIR/disallowed-positions.rs:44:9 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:45:9 + --> $DIR/disallowed-positions.rs:44:9 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:45:24 + --> $DIR/disallowed-positions.rs:44:24 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:45:24 + --> $DIR/disallowed-positions.rs:44:24 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:49:35 + --> $DIR/disallowed-positions.rs:48:35 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:49:35 + --> $DIR/disallowed-positions.rs:48:35 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:49:48 + --> $DIR/disallowed-positions.rs:48:48 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:49:35 + --> $DIR/disallowed-positions.rs:48:35 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:49:61 + --> $DIR/disallowed-positions.rs:48:61 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:49:35 + --> $DIR/disallowed-positions.rs:48:35 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:59:12 + --> $DIR/disallowed-positions.rs:58:12 | LL | while (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:59:12 + --> $DIR/disallowed-positions.rs:58:12 | LL | while (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:62:14 + --> $DIR/disallowed-positions.rs:61:14 | LL | while (((let 0 = 1))) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:62:14 + --> $DIR/disallowed-positions.rs:61:14 | LL | while (((let 0 = 1))) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:65:12 + --> $DIR/disallowed-positions.rs:64:12 | LL | while (let 0 = 1) && true {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:65:12 + --> $DIR/disallowed-positions.rs:64:12 | LL | while (let 0 = 1) && true {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:68:20 + --> $DIR/disallowed-positions.rs:67:20 | LL | while true && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:68:20 + --> $DIR/disallowed-positions.rs:67:20 | LL | while true && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:71:12 + --> $DIR/disallowed-positions.rs:70:12 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:71:12 + --> $DIR/disallowed-positions.rs:70:12 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:71:27 + --> $DIR/disallowed-positions.rs:70:27 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:71:27 + --> $DIR/disallowed-positions.rs:70:27 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:75:38 + --> $DIR/disallowed-positions.rs:74:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:75:38 + --> $DIR/disallowed-positions.rs:74:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:75:51 + --> $DIR/disallowed-positions.rs:74:51 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:75:38 + --> $DIR/disallowed-positions.rs:74:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:75:64 + --> $DIR/disallowed-positions.rs:74:64 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:75:38 + --> $DIR/disallowed-positions.rs:74:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:103:9 + --> $DIR/disallowed-positions.rs:102:9 | LL | if &let 0 = 0 {} | ^^^^^^^^^ @@ -241,7 +241,7 @@ LL | if &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:106:9 + --> $DIR/disallowed-positions.rs:105:9 | LL | if !let 0 = 0 {} | ^^^^^^^^^ @@ -249,7 +249,7 @@ LL | if !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:108:9 + --> $DIR/disallowed-positions.rs:107:9 | LL | if *let 0 = 0 {} | ^^^^^^^^^ @@ -257,7 +257,7 @@ LL | if *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:110:9 + --> $DIR/disallowed-positions.rs:109:9 | LL | if -let 0 = 0 {} | ^^^^^^^^^ @@ -265,7 +265,7 @@ LL | if -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:118:9 + --> $DIR/disallowed-positions.rs:117:9 | LL | if (let 0 = 0)? {} | ^^^^^^^^^ @@ -273,13 +273,13 @@ LL | if (let 0 = 0)? {} = note: only supported directly in conditions of `if` and `while` expressions error: `||` operators are not supported in let chain conditions - --> $DIR/disallowed-positions.rs:121:13 + --> $DIR/disallowed-positions.rs:120:13 | LL | if true || let 0 = 0 {} | ^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:123:17 + --> $DIR/disallowed-positions.rs:122:17 | LL | if (true || let 0 = 0) {} | ^^^^^^^^^ @@ -287,7 +287,7 @@ LL | if (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:125:25 + --> $DIR/disallowed-positions.rs:124:25 | LL | if true && (true || let 0 = 0) {} | ^^^^^^^^^ @@ -295,7 +295,7 @@ LL | if true && (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:127:25 + --> $DIR/disallowed-positions.rs:126:25 | LL | if true || (true && let 0 = 0) {} | ^^^^^^^^^ @@ -303,7 +303,7 @@ LL | if true || (true && let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:131:12 + --> $DIR/disallowed-positions.rs:130:12 | LL | if x = let 0 = 0 {} | ^^^ @@ -311,7 +311,7 @@ LL | if x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:134:15 + --> $DIR/disallowed-positions.rs:133:15 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^ @@ -319,7 +319,7 @@ LL | if true..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:137:11 + --> $DIR/disallowed-positions.rs:136:11 | LL | if ..(let 0 = 0) {} | ^^^^^^^^^ @@ -327,7 +327,7 @@ LL | if ..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:139:9 + --> $DIR/disallowed-positions.rs:138:9 | LL | if (let 0 = 0).. {} | ^^^^^^^^^ @@ -335,7 +335,7 @@ LL | if (let 0 = 0).. {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:143:8 + --> $DIR/disallowed-positions.rs:142:8 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -343,7 +343,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:146:8 + --> $DIR/disallowed-positions.rs:145:8 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -351,7 +351,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:152:8 + --> $DIR/disallowed-positions.rs:151:8 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -359,7 +359,7 @@ LL | if let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:158:8 + --> $DIR/disallowed-positions.rs:157:8 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -367,7 +367,7 @@ LL | if let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:162:19 + --> $DIR/disallowed-positions.rs:161:19 | LL | if let true = let true = true {} | ^^^ @@ -375,7 +375,7 @@ LL | if let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:165:15 + --> $DIR/disallowed-positions.rs:164:15 | LL | if return let 0 = 0 {} | ^^^ @@ -383,7 +383,7 @@ LL | if return let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:168:21 + --> $DIR/disallowed-positions.rs:167:21 | LL | loop { if break let 0 = 0 {} } | ^^^ @@ -391,7 +391,7 @@ LL | loop { if break let 0 = 0 {} } = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:171:15 + --> $DIR/disallowed-positions.rs:170:15 | LL | if (match let 0 = 0 { _ => { false } }) {} | ^^^ @@ -399,7 +399,7 @@ LL | if (match let 0 = 0 { _ => { false } }) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:174:9 + --> $DIR/disallowed-positions.rs:173:9 | LL | if (let 0 = 0, false).1 {} | ^^^^^^^^^ @@ -407,7 +407,7 @@ LL | if (let 0 = 0, false).1 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:177:9 + --> $DIR/disallowed-positions.rs:176:9 | LL | if (let 0 = 0,) {} | ^^^^^^^^^ @@ -415,7 +415,7 @@ LL | if (let 0 = 0,) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:181:13 + --> $DIR/disallowed-positions.rs:180:13 | LL | if (let 0 = 0).await {} | ^^^^^^^^^ @@ -423,7 +423,7 @@ LL | if (let 0 = 0).await {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:185:12 + --> $DIR/disallowed-positions.rs:184:12 | LL | if (|| let 0 = 0) {} | ^^^ @@ -431,7 +431,7 @@ LL | if (|| let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:188:9 + --> $DIR/disallowed-positions.rs:187:9 | LL | if (let 0 = 0)() {} | ^^^^^^^^^ @@ -439,7 +439,7 @@ LL | if (let 0 = 0)() {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:194:12 + --> $DIR/disallowed-positions.rs:193:12 | LL | while &let 0 = 0 {} | ^^^^^^^^^ @@ -447,7 +447,7 @@ LL | while &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:197:12 + --> $DIR/disallowed-positions.rs:196:12 | LL | while !let 0 = 0 {} | ^^^^^^^^^ @@ -455,7 +455,7 @@ LL | while !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:199:12 + --> $DIR/disallowed-positions.rs:198:12 | LL | while *let 0 = 0 {} | ^^^^^^^^^ @@ -463,7 +463,7 @@ LL | while *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:201:12 + --> $DIR/disallowed-positions.rs:200:12 | LL | while -let 0 = 0 {} | ^^^^^^^^^ @@ -471,7 +471,7 @@ LL | while -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:209:12 + --> $DIR/disallowed-positions.rs:208:12 | LL | while (let 0 = 0)? {} | ^^^^^^^^^ @@ -479,13 +479,13 @@ LL | while (let 0 = 0)? {} = note: only supported directly in conditions of `if` and `while` expressions error: `||` operators are not supported in let chain conditions - --> $DIR/disallowed-positions.rs:212:16 + --> $DIR/disallowed-positions.rs:211:16 | LL | while true || let 0 = 0 {} | ^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:214:20 + --> $DIR/disallowed-positions.rs:213:20 | LL | while (true || let 0 = 0) {} | ^^^^^^^^^ @@ -493,7 +493,7 @@ LL | while (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:216:28 + --> $DIR/disallowed-positions.rs:215:28 | LL | while true && (true || let 0 = 0) {} | ^^^^^^^^^ @@ -501,7 +501,7 @@ LL | while true && (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:218:28 + --> $DIR/disallowed-positions.rs:217:28 | LL | while true || (true && let 0 = 0) {} | ^^^^^^^^^ @@ -509,7 +509,7 @@ LL | while true || (true && let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:222:15 + --> $DIR/disallowed-positions.rs:221:15 | LL | while x = let 0 = 0 {} | ^^^ @@ -517,7 +517,7 @@ LL | while x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:225:18 + --> $DIR/disallowed-positions.rs:224:18 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^ @@ -525,7 +525,7 @@ LL | while true..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:228:14 + --> $DIR/disallowed-positions.rs:227:14 | LL | while ..(let 0 = 0) {} | ^^^^^^^^^ @@ -533,7 +533,7 @@ LL | while ..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:230:12 + --> $DIR/disallowed-positions.rs:229:12 | LL | while (let 0 = 0).. {} | ^^^^^^^^^ @@ -541,7 +541,7 @@ LL | while (let 0 = 0).. {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:234:11 + --> $DIR/disallowed-positions.rs:233:11 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -549,7 +549,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:237:11 + --> $DIR/disallowed-positions.rs:236:11 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -557,7 +557,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:243:11 + --> $DIR/disallowed-positions.rs:242:11 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -565,7 +565,7 @@ LL | while let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:249:11 + --> $DIR/disallowed-positions.rs:248:11 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -573,7 +573,7 @@ LL | while let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:253:22 + --> $DIR/disallowed-positions.rs:252:22 | LL | while let true = let true = true {} | ^^^ @@ -581,7 +581,7 @@ LL | while let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:256:18 + --> $DIR/disallowed-positions.rs:255:18 | LL | while return let 0 = 0 {} | ^^^ @@ -589,7 +589,7 @@ LL | while return let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:259:39 + --> $DIR/disallowed-positions.rs:258:39 | LL | 'outer: loop { while break 'outer let 0 = 0 {} } | ^^^ @@ -597,7 +597,7 @@ LL | 'outer: loop { while break 'outer let 0 = 0 {} } = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:262:18 + --> $DIR/disallowed-positions.rs:261:18 | LL | while (match let 0 = 0 { _ => { false } }) {} | ^^^ @@ -605,7 +605,7 @@ LL | while (match let 0 = 0 { _ => { false } }) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:265:12 + --> $DIR/disallowed-positions.rs:264:12 | LL | while (let 0 = 0, false).1 {} | ^^^^^^^^^ @@ -613,7 +613,7 @@ LL | while (let 0 = 0, false).1 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:268:12 + --> $DIR/disallowed-positions.rs:267:12 | LL | while (let 0 = 0,) {} | ^^^^^^^^^ @@ -621,7 +621,7 @@ LL | while (let 0 = 0,) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:272:16 + --> $DIR/disallowed-positions.rs:271:16 | LL | while (let 0 = 0).await {} | ^^^^^^^^^ @@ -629,7 +629,7 @@ LL | while (let 0 = 0).await {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:276:15 + --> $DIR/disallowed-positions.rs:275:15 | LL | while (|| let 0 = 0) {} | ^^^ @@ -637,7 +637,7 @@ LL | while (|| let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:279:12 + --> $DIR/disallowed-positions.rs:278:12 | LL | while (let 0 = 0)() {} | ^^^^^^^^^ @@ -645,7 +645,7 @@ LL | while (let 0 = 0)() {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:296:6 + --> $DIR/disallowed-positions.rs:295:6 | LL | &let 0 = 0; | ^^^ @@ -653,7 +653,7 @@ LL | &let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:299:6 + --> $DIR/disallowed-positions.rs:298:6 | LL | !let 0 = 0; | ^^^ @@ -661,7 +661,7 @@ LL | !let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:301:6 + --> $DIR/disallowed-positions.rs:300:6 | LL | *let 0 = 0; | ^^^ @@ -669,7 +669,7 @@ LL | *let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:303:6 + --> $DIR/disallowed-positions.rs:302:6 | LL | -let 0 = 0; | ^^^ @@ -677,7 +677,7 @@ LL | -let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:305:13 + --> $DIR/disallowed-positions.rs:304:13 | LL | let _ = let _ = 3; | ^^^ @@ -685,7 +685,7 @@ LL | let _ = let _ = 3; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:313:6 + --> $DIR/disallowed-positions.rs:312:6 | LL | (let 0 = 0)?; | ^^^ @@ -693,7 +693,7 @@ LL | (let 0 = 0)?; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:316:13 + --> $DIR/disallowed-positions.rs:315:13 | LL | true || let 0 = 0; | ^^^ @@ -701,7 +701,7 @@ LL | true || let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:318:14 + --> $DIR/disallowed-positions.rs:317:14 | LL | (true || let 0 = 0); | ^^^ @@ -709,7 +709,7 @@ LL | (true || let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:320:22 + --> $DIR/disallowed-positions.rs:319:22 | LL | true && (true || let 0 = 0); | ^^^ @@ -717,7 +717,7 @@ LL | true && (true || let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:324:9 + --> $DIR/disallowed-positions.rs:323:9 | LL | x = let 0 = 0; | ^^^ @@ -725,7 +725,7 @@ LL | x = let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:327:12 + --> $DIR/disallowed-positions.rs:326:12 | LL | true..(let 0 = 0); | ^^^ @@ -733,7 +733,7 @@ LL | true..(let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:329:8 + --> $DIR/disallowed-positions.rs:328:8 | LL | ..(let 0 = 0); | ^^^ @@ -741,7 +741,7 @@ LL | ..(let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:331:6 + --> $DIR/disallowed-positions.rs:330:6 | LL | (let 0 = 0)..; | ^^^ @@ -749,7 +749,7 @@ LL | (let 0 = 0)..; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:334:6 + --> $DIR/disallowed-positions.rs:333:6 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^ @@ -757,7 +757,7 @@ LL | (let Range { start: _, end: _ } = true..true || false); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:338:6 + --> $DIR/disallowed-positions.rs:337:6 | LL | (let true = let true = true); | ^^^ @@ -765,7 +765,7 @@ LL | (let true = let true = true); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:338:17 + --> $DIR/disallowed-positions.rs:337:17 | LL | (let true = let true = true); | ^^^ @@ -773,7 +773,7 @@ LL | (let true = let true = true); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:344:25 + --> $DIR/disallowed-positions.rs:343:25 | LL | let x = true && let y = 1; | ^^^ @@ -781,7 +781,7 @@ LL | let x = true && let y = 1; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:350:19 + --> $DIR/disallowed-positions.rs:349:19 | LL | [1, 2, 3][let _ = ()] | ^^^ @@ -789,7 +789,7 @@ LL | [1, 2, 3][let _ = ()] = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:355:6 + --> $DIR/disallowed-positions.rs:354:6 | LL | &let 0 = 0 | ^^^ @@ -797,7 +797,7 @@ LL | &let 0 = 0 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:366:17 + --> $DIR/disallowed-positions.rs:365:17 | LL | true && let 1 = 1 | ^^^ @@ -805,7 +805,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:371:17 + --> $DIR/disallowed-positions.rs:370:17 | LL | true && let 1 = 1 | ^^^ @@ -813,7 +813,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:376:17 + --> $DIR/disallowed-positions.rs:375:17 | LL | true && let 1 = 1 | ^^^ @@ -821,7 +821,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:387:17 + --> $DIR/disallowed-positions.rs:386:17 | LL | true && let 1 = 1 | ^^^ @@ -829,7 +829,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/disallowed-positions.rs:387:9 + --> $DIR/disallowed-positions.rs:386:9 | LL | true && let 1 = 1 | ^^^^^^^^^^^^^^^^^ @@ -840,124 +840,124 @@ LL | { true && let 1 = 1 } | + + error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:397:9 + --> $DIR/disallowed-positions.rs:396:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:397:9 + --> $DIR/disallowed-positions.rs:396:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:401:9 + --> $DIR/disallowed-positions.rs:400:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:401:9 + --> $DIR/disallowed-positions.rs:400:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:404:9 + --> $DIR/disallowed-positions.rs:403:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:404:9 + --> $DIR/disallowed-positions.rs:403:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:404:32 + --> $DIR/disallowed-positions.rs:403:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:404:32 + --> $DIR/disallowed-positions.rs:403:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:412:9 + --> $DIR/disallowed-positions.rs:411:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:412:9 + --> $DIR/disallowed-positions.rs:411:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:412:31 + --> $DIR/disallowed-positions.rs:411:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:412:31 + --> $DIR/disallowed-positions.rs:411:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:416:9 + --> $DIR/disallowed-positions.rs:415:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:416:9 + --> $DIR/disallowed-positions.rs:415:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:416:31 + --> $DIR/disallowed-positions.rs:415:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:416:31 + --> $DIR/disallowed-positions.rs:415:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:420:9 + --> $DIR/disallowed-positions.rs:419:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:420:9 + --> $DIR/disallowed-positions.rs:419:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:440:22 + --> $DIR/disallowed-positions.rs:439:22 | LL | let x = (true && let y = 1); | ^^^ @@ -965,7 +965,7 @@ LL | let x = (true && let y = 1); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:445:20 + --> $DIR/disallowed-positions.rs:444:20 | LL | ([1, 2, 3][let _ = ()]) | ^^^ @@ -973,7 +973,7 @@ LL | ([1, 2, 3][let _ = ()]) = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:91:16 + --> $DIR/disallowed-positions.rs:90:16 | LL | use_expr!((let 0 = 1 && 0 == 0)); | ^^^ @@ -981,7 +981,7 @@ LL | use_expr!((let 0 = 1 && 0 == 0)); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:91:16 + --> $DIR/disallowed-positions.rs:90:16 | LL | use_expr!((let 0 = 1 && 0 == 0)); | ^^^ @@ -990,7 +990,7 @@ LL | use_expr!((let 0 = 1 && 0 == 0)); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:91:16 + --> $DIR/disallowed-positions.rs:90:16 | LL | use_expr!((let 0 = 1 && 0 == 0)); | ^^^ @@ -999,7 +999,7 @@ LL | use_expr!((let 0 = 1 && 0 == 0)); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:95:16 + --> $DIR/disallowed-positions.rs:94:16 | LL | use_expr!((let 0 = 1)); | ^^^ @@ -1007,7 +1007,7 @@ LL | use_expr!((let 0 = 1)); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:95:16 + --> $DIR/disallowed-positions.rs:94:16 | LL | use_expr!((let 0 = 1)); | ^^^ @@ -1016,7 +1016,7 @@ LL | use_expr!((let 0 = 1)); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:95:16 + --> $DIR/disallowed-positions.rs:94:16 | LL | use_expr!((let 0 = 1)); | ^^^ @@ -1025,7 +1025,7 @@ LL | use_expr!((let 0 = 1)); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:134:8 + --> $DIR/disallowed-positions.rs:133:8 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>` @@ -1034,7 +1034,7 @@ LL | if true..(let 0 = 0) {} found struct `std::ops::Range<bool>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:143:12 + --> $DIR/disallowed-positions.rs:142:12 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1045,7 +1045,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:146:12 + --> $DIR/disallowed-positions.rs:145:12 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1056,7 +1056,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:152:12 + --> $DIR/disallowed-positions.rs:151:12 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` @@ -1067,7 +1067,7 @@ LL | if let Range { start: F, end } = F..|| true {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:158:12 + --> $DIR/disallowed-positions.rs:157:12 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` @@ -1078,7 +1078,7 @@ LL | if let Range { start: true, end } = t..&&false {} found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:114:20 + --> $DIR/disallowed-positions.rs:113:20 | LL | if let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` @@ -1086,7 +1086,7 @@ LL | if let 0 = 0? {} = help: the trait `Try` is not implemented for `{integer}` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:225:11 + --> $DIR/disallowed-positions.rs:224:11 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>` @@ -1095,7 +1095,7 @@ LL | while true..(let 0 = 0) {} found struct `std::ops::Range<bool>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:234:15 + --> $DIR/disallowed-positions.rs:233:15 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1106,7 +1106,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:237:15 + --> $DIR/disallowed-positions.rs:236:15 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1117,7 +1117,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:243:15 + --> $DIR/disallowed-positions.rs:242:15 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` @@ -1128,7 +1128,7 @@ LL | while let Range { start: F, end } = F..|| true {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:249:15 + --> $DIR/disallowed-positions.rs:248:15 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` @@ -1139,7 +1139,7 @@ LL | while let Range { start: true, end } = t..&&false {} found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:205:23 + --> $DIR/disallowed-positions.rs:204:23 | LL | while let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` @@ -1147,7 +1147,7 @@ LL | while let 0 = 0? {} = help: the trait `Try` is not implemented for `{integer}` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:334:10 + --> $DIR/disallowed-positions.rs:333:10 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1158,7 +1158,7 @@ LL | (let Range { start: _, end: _ } = true..true || false); found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:309:17 + --> $DIR/disallowed-positions.rs:308:17 | LL | let 0 = 0?; | ^^ the `?` operator cannot be applied to type `{integer}` diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nothing.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nothing.stderr index 5b53691cbf5..f69c18ff0d9 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nothing.stderr +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nothing.stderr @@ -1,239 +1,239 @@ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:33:9 + --> $DIR/disallowed-positions.rs:32:9 | LL | if (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:33:9 + --> $DIR/disallowed-positions.rs:32:9 | LL | if (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:36:11 + --> $DIR/disallowed-positions.rs:35:11 | LL | if (((let 0 = 1))) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:36:11 + --> $DIR/disallowed-positions.rs:35:11 | LL | if (((let 0 = 1))) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:39:9 + --> $DIR/disallowed-positions.rs:38:9 | LL | if (let 0 = 1) && true {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:39:9 + --> $DIR/disallowed-positions.rs:38:9 | LL | if (let 0 = 1) && true {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:42:17 + --> $DIR/disallowed-positions.rs:41:17 | LL | if true && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:42:17 + --> $DIR/disallowed-positions.rs:41:17 | LL | if true && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:45:9 + --> $DIR/disallowed-positions.rs:44:9 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:45:9 + --> $DIR/disallowed-positions.rs:44:9 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:45:24 + --> $DIR/disallowed-positions.rs:44:24 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:45:24 + --> $DIR/disallowed-positions.rs:44:24 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:49:35 + --> $DIR/disallowed-positions.rs:48:35 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:49:35 + --> $DIR/disallowed-positions.rs:48:35 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:49:48 + --> $DIR/disallowed-positions.rs:48:48 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:49:35 + --> $DIR/disallowed-positions.rs:48:35 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:49:61 + --> $DIR/disallowed-positions.rs:48:61 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:49:35 + --> $DIR/disallowed-positions.rs:48:35 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:59:12 + --> $DIR/disallowed-positions.rs:58:12 | LL | while (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:59:12 + --> $DIR/disallowed-positions.rs:58:12 | LL | while (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:62:14 + --> $DIR/disallowed-positions.rs:61:14 | LL | while (((let 0 = 1))) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:62:14 + --> $DIR/disallowed-positions.rs:61:14 | LL | while (((let 0 = 1))) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:65:12 + --> $DIR/disallowed-positions.rs:64:12 | LL | while (let 0 = 1) && true {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:65:12 + --> $DIR/disallowed-positions.rs:64:12 | LL | while (let 0 = 1) && true {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:68:20 + --> $DIR/disallowed-positions.rs:67:20 | LL | while true && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:68:20 + --> $DIR/disallowed-positions.rs:67:20 | LL | while true && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:71:12 + --> $DIR/disallowed-positions.rs:70:12 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:71:12 + --> $DIR/disallowed-positions.rs:70:12 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:71:27 + --> $DIR/disallowed-positions.rs:70:27 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:71:27 + --> $DIR/disallowed-positions.rs:70:27 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:75:38 + --> $DIR/disallowed-positions.rs:74:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:75:38 + --> $DIR/disallowed-positions.rs:74:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:75:51 + --> $DIR/disallowed-positions.rs:74:51 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:75:38 + --> $DIR/disallowed-positions.rs:74:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:75:64 + --> $DIR/disallowed-positions.rs:74:64 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:75:38 + --> $DIR/disallowed-positions.rs:74:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:103:9 + --> $DIR/disallowed-positions.rs:102:9 | LL | if &let 0 = 0 {} | ^^^^^^^^^ @@ -241,7 +241,7 @@ LL | if &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:106:9 + --> $DIR/disallowed-positions.rs:105:9 | LL | if !let 0 = 0 {} | ^^^^^^^^^ @@ -249,7 +249,7 @@ LL | if !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:108:9 + --> $DIR/disallowed-positions.rs:107:9 | LL | if *let 0 = 0 {} | ^^^^^^^^^ @@ -257,7 +257,7 @@ LL | if *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:110:9 + --> $DIR/disallowed-positions.rs:109:9 | LL | if -let 0 = 0 {} | ^^^^^^^^^ @@ -265,7 +265,7 @@ LL | if -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:118:9 + --> $DIR/disallowed-positions.rs:117:9 | LL | if (let 0 = 0)? {} | ^^^^^^^^^ @@ -273,13 +273,13 @@ LL | if (let 0 = 0)? {} = note: only supported directly in conditions of `if` and `while` expressions error: `||` operators are not supported in let chain conditions - --> $DIR/disallowed-positions.rs:121:13 + --> $DIR/disallowed-positions.rs:120:13 | LL | if true || let 0 = 0 {} | ^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:123:17 + --> $DIR/disallowed-positions.rs:122:17 | LL | if (true || let 0 = 0) {} | ^^^^^^^^^ @@ -287,7 +287,7 @@ LL | if (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:125:25 + --> $DIR/disallowed-positions.rs:124:25 | LL | if true && (true || let 0 = 0) {} | ^^^^^^^^^ @@ -295,7 +295,7 @@ LL | if true && (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:127:25 + --> $DIR/disallowed-positions.rs:126:25 | LL | if true || (true && let 0 = 0) {} | ^^^^^^^^^ @@ -303,7 +303,7 @@ LL | if true || (true && let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:131:12 + --> $DIR/disallowed-positions.rs:130:12 | LL | if x = let 0 = 0 {} | ^^^ @@ -311,7 +311,7 @@ LL | if x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:134:15 + --> $DIR/disallowed-positions.rs:133:15 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^ @@ -319,7 +319,7 @@ LL | if true..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:137:11 + --> $DIR/disallowed-positions.rs:136:11 | LL | if ..(let 0 = 0) {} | ^^^^^^^^^ @@ -327,7 +327,7 @@ LL | if ..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:139:9 + --> $DIR/disallowed-positions.rs:138:9 | LL | if (let 0 = 0).. {} | ^^^^^^^^^ @@ -335,7 +335,7 @@ LL | if (let 0 = 0).. {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:143:8 + --> $DIR/disallowed-positions.rs:142:8 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -343,7 +343,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:146:8 + --> $DIR/disallowed-positions.rs:145:8 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -351,7 +351,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:152:8 + --> $DIR/disallowed-positions.rs:151:8 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -359,7 +359,7 @@ LL | if let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:158:8 + --> $DIR/disallowed-positions.rs:157:8 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -367,7 +367,7 @@ LL | if let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:162:19 + --> $DIR/disallowed-positions.rs:161:19 | LL | if let true = let true = true {} | ^^^ @@ -375,7 +375,7 @@ LL | if let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:165:15 + --> $DIR/disallowed-positions.rs:164:15 | LL | if return let 0 = 0 {} | ^^^ @@ -383,7 +383,7 @@ LL | if return let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:168:21 + --> $DIR/disallowed-positions.rs:167:21 | LL | loop { if break let 0 = 0 {} } | ^^^ @@ -391,7 +391,7 @@ LL | loop { if break let 0 = 0 {} } = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:171:15 + --> $DIR/disallowed-positions.rs:170:15 | LL | if (match let 0 = 0 { _ => { false } }) {} | ^^^ @@ -399,7 +399,7 @@ LL | if (match let 0 = 0 { _ => { false } }) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:174:9 + --> $DIR/disallowed-positions.rs:173:9 | LL | if (let 0 = 0, false).1 {} | ^^^^^^^^^ @@ -407,7 +407,7 @@ LL | if (let 0 = 0, false).1 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:177:9 + --> $DIR/disallowed-positions.rs:176:9 | LL | if (let 0 = 0,) {} | ^^^^^^^^^ @@ -415,7 +415,7 @@ LL | if (let 0 = 0,) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:181:13 + --> $DIR/disallowed-positions.rs:180:13 | LL | if (let 0 = 0).await {} | ^^^^^^^^^ @@ -423,7 +423,7 @@ LL | if (let 0 = 0).await {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:185:12 + --> $DIR/disallowed-positions.rs:184:12 | LL | if (|| let 0 = 0) {} | ^^^ @@ -431,7 +431,7 @@ LL | if (|| let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:188:9 + --> $DIR/disallowed-positions.rs:187:9 | LL | if (let 0 = 0)() {} | ^^^^^^^^^ @@ -439,7 +439,7 @@ LL | if (let 0 = 0)() {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:194:12 + --> $DIR/disallowed-positions.rs:193:12 | LL | while &let 0 = 0 {} | ^^^^^^^^^ @@ -447,7 +447,7 @@ LL | while &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:197:12 + --> $DIR/disallowed-positions.rs:196:12 | LL | while !let 0 = 0 {} | ^^^^^^^^^ @@ -455,7 +455,7 @@ LL | while !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:199:12 + --> $DIR/disallowed-positions.rs:198:12 | LL | while *let 0 = 0 {} | ^^^^^^^^^ @@ -463,7 +463,7 @@ LL | while *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:201:12 + --> $DIR/disallowed-positions.rs:200:12 | LL | while -let 0 = 0 {} | ^^^^^^^^^ @@ -471,7 +471,7 @@ LL | while -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:209:12 + --> $DIR/disallowed-positions.rs:208:12 | LL | while (let 0 = 0)? {} | ^^^^^^^^^ @@ -479,13 +479,13 @@ LL | while (let 0 = 0)? {} = note: only supported directly in conditions of `if` and `while` expressions error: `||` operators are not supported in let chain conditions - --> $DIR/disallowed-positions.rs:212:16 + --> $DIR/disallowed-positions.rs:211:16 | LL | while true || let 0 = 0 {} | ^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:214:20 + --> $DIR/disallowed-positions.rs:213:20 | LL | while (true || let 0 = 0) {} | ^^^^^^^^^ @@ -493,7 +493,7 @@ LL | while (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:216:28 + --> $DIR/disallowed-positions.rs:215:28 | LL | while true && (true || let 0 = 0) {} | ^^^^^^^^^ @@ -501,7 +501,7 @@ LL | while true && (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:218:28 + --> $DIR/disallowed-positions.rs:217:28 | LL | while true || (true && let 0 = 0) {} | ^^^^^^^^^ @@ -509,7 +509,7 @@ LL | while true || (true && let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:222:15 + --> $DIR/disallowed-positions.rs:221:15 | LL | while x = let 0 = 0 {} | ^^^ @@ -517,7 +517,7 @@ LL | while x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:225:18 + --> $DIR/disallowed-positions.rs:224:18 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^ @@ -525,7 +525,7 @@ LL | while true..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:228:14 + --> $DIR/disallowed-positions.rs:227:14 | LL | while ..(let 0 = 0) {} | ^^^^^^^^^ @@ -533,7 +533,7 @@ LL | while ..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:230:12 + --> $DIR/disallowed-positions.rs:229:12 | LL | while (let 0 = 0).. {} | ^^^^^^^^^ @@ -541,7 +541,7 @@ LL | while (let 0 = 0).. {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:234:11 + --> $DIR/disallowed-positions.rs:233:11 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -549,7 +549,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:237:11 + --> $DIR/disallowed-positions.rs:236:11 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -557,7 +557,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:243:11 + --> $DIR/disallowed-positions.rs:242:11 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -565,7 +565,7 @@ LL | while let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:249:11 + --> $DIR/disallowed-positions.rs:248:11 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -573,7 +573,7 @@ LL | while let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:253:22 + --> $DIR/disallowed-positions.rs:252:22 | LL | while let true = let true = true {} | ^^^ @@ -581,7 +581,7 @@ LL | while let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:256:18 + --> $DIR/disallowed-positions.rs:255:18 | LL | while return let 0 = 0 {} | ^^^ @@ -589,7 +589,7 @@ LL | while return let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:259:39 + --> $DIR/disallowed-positions.rs:258:39 | LL | 'outer: loop { while break 'outer let 0 = 0 {} } | ^^^ @@ -597,7 +597,7 @@ LL | 'outer: loop { while break 'outer let 0 = 0 {} } = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:262:18 + --> $DIR/disallowed-positions.rs:261:18 | LL | while (match let 0 = 0 { _ => { false } }) {} | ^^^ @@ -605,7 +605,7 @@ LL | while (match let 0 = 0 { _ => { false } }) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:265:12 + --> $DIR/disallowed-positions.rs:264:12 | LL | while (let 0 = 0, false).1 {} | ^^^^^^^^^ @@ -613,7 +613,7 @@ LL | while (let 0 = 0, false).1 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:268:12 + --> $DIR/disallowed-positions.rs:267:12 | LL | while (let 0 = 0,) {} | ^^^^^^^^^ @@ -621,7 +621,7 @@ LL | while (let 0 = 0,) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:272:16 + --> $DIR/disallowed-positions.rs:271:16 | LL | while (let 0 = 0).await {} | ^^^^^^^^^ @@ -629,7 +629,7 @@ LL | while (let 0 = 0).await {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:276:15 + --> $DIR/disallowed-positions.rs:275:15 | LL | while (|| let 0 = 0) {} | ^^^ @@ -637,7 +637,7 @@ LL | while (|| let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:279:12 + --> $DIR/disallowed-positions.rs:278:12 | LL | while (let 0 = 0)() {} | ^^^^^^^^^ @@ -645,7 +645,7 @@ LL | while (let 0 = 0)() {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:296:6 + --> $DIR/disallowed-positions.rs:295:6 | LL | &let 0 = 0; | ^^^ @@ -653,7 +653,7 @@ LL | &let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:299:6 + --> $DIR/disallowed-positions.rs:298:6 | LL | !let 0 = 0; | ^^^ @@ -661,7 +661,7 @@ LL | !let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:301:6 + --> $DIR/disallowed-positions.rs:300:6 | LL | *let 0 = 0; | ^^^ @@ -669,7 +669,7 @@ LL | *let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:303:6 + --> $DIR/disallowed-positions.rs:302:6 | LL | -let 0 = 0; | ^^^ @@ -677,7 +677,7 @@ LL | -let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:305:13 + --> $DIR/disallowed-positions.rs:304:13 | LL | let _ = let _ = 3; | ^^^ @@ -685,7 +685,7 @@ LL | let _ = let _ = 3; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:313:6 + --> $DIR/disallowed-positions.rs:312:6 | LL | (let 0 = 0)?; | ^^^ @@ -693,7 +693,7 @@ LL | (let 0 = 0)?; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:316:13 + --> $DIR/disallowed-positions.rs:315:13 | LL | true || let 0 = 0; | ^^^ @@ -701,7 +701,7 @@ LL | true || let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:318:14 + --> $DIR/disallowed-positions.rs:317:14 | LL | (true || let 0 = 0); | ^^^ @@ -709,7 +709,7 @@ LL | (true || let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:320:22 + --> $DIR/disallowed-positions.rs:319:22 | LL | true && (true || let 0 = 0); | ^^^ @@ -717,7 +717,7 @@ LL | true && (true || let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:324:9 + --> $DIR/disallowed-positions.rs:323:9 | LL | x = let 0 = 0; | ^^^ @@ -725,7 +725,7 @@ LL | x = let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:327:12 + --> $DIR/disallowed-positions.rs:326:12 | LL | true..(let 0 = 0); | ^^^ @@ -733,7 +733,7 @@ LL | true..(let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:329:8 + --> $DIR/disallowed-positions.rs:328:8 | LL | ..(let 0 = 0); | ^^^ @@ -741,7 +741,7 @@ LL | ..(let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:331:6 + --> $DIR/disallowed-positions.rs:330:6 | LL | (let 0 = 0)..; | ^^^ @@ -749,7 +749,7 @@ LL | (let 0 = 0)..; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:334:6 + --> $DIR/disallowed-positions.rs:333:6 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^ @@ -757,7 +757,7 @@ LL | (let Range { start: _, end: _ } = true..true || false); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:338:6 + --> $DIR/disallowed-positions.rs:337:6 | LL | (let true = let true = true); | ^^^ @@ -765,7 +765,7 @@ LL | (let true = let true = true); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:338:17 + --> $DIR/disallowed-positions.rs:337:17 | LL | (let true = let true = true); | ^^^ @@ -773,7 +773,7 @@ LL | (let true = let true = true); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:344:25 + --> $DIR/disallowed-positions.rs:343:25 | LL | let x = true && let y = 1; | ^^^ @@ -781,7 +781,7 @@ LL | let x = true && let y = 1; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:350:19 + --> $DIR/disallowed-positions.rs:349:19 | LL | [1, 2, 3][let _ = ()] | ^^^ @@ -789,7 +789,7 @@ LL | [1, 2, 3][let _ = ()] = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:355:6 + --> $DIR/disallowed-positions.rs:354:6 | LL | &let 0 = 0 | ^^^ @@ -797,7 +797,7 @@ LL | &let 0 = 0 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:366:17 + --> $DIR/disallowed-positions.rs:365:17 | LL | true && let 1 = 1 | ^^^ @@ -805,7 +805,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:371:17 + --> $DIR/disallowed-positions.rs:370:17 | LL | true && let 1 = 1 | ^^^ @@ -813,7 +813,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:376:17 + --> $DIR/disallowed-positions.rs:375:17 | LL | true && let 1 = 1 | ^^^ @@ -821,7 +821,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:387:17 + --> $DIR/disallowed-positions.rs:386:17 | LL | true && let 1 = 1 | ^^^ @@ -829,7 +829,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/disallowed-positions.rs:387:9 + --> $DIR/disallowed-positions.rs:386:9 | LL | true && let 1 = 1 | ^^^^^^^^^^^^^^^^^ @@ -840,124 +840,124 @@ LL | { true && let 1 = 1 } | + + error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:397:9 + --> $DIR/disallowed-positions.rs:396:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:397:9 + --> $DIR/disallowed-positions.rs:396:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:401:9 + --> $DIR/disallowed-positions.rs:400:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:401:9 + --> $DIR/disallowed-positions.rs:400:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:404:9 + --> $DIR/disallowed-positions.rs:403:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:404:9 + --> $DIR/disallowed-positions.rs:403:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:404:32 + --> $DIR/disallowed-positions.rs:403:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:404:32 + --> $DIR/disallowed-positions.rs:403:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:412:9 + --> $DIR/disallowed-positions.rs:411:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:412:9 + --> $DIR/disallowed-positions.rs:411:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:412:31 + --> $DIR/disallowed-positions.rs:411:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:412:31 + --> $DIR/disallowed-positions.rs:411:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:416:9 + --> $DIR/disallowed-positions.rs:415:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:416:9 + --> $DIR/disallowed-positions.rs:415:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:416:31 + --> $DIR/disallowed-positions.rs:415:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:416:31 + --> $DIR/disallowed-positions.rs:415:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:420:9 + --> $DIR/disallowed-positions.rs:419:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:420:9 + --> $DIR/disallowed-positions.rs:419:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:440:22 + --> $DIR/disallowed-positions.rs:439:22 | LL | let x = (true && let y = 1); | ^^^ @@ -965,7 +965,7 @@ LL | let x = (true && let y = 1); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:445:20 + --> $DIR/disallowed-positions.rs:444:20 | LL | ([1, 2, 3][let _ = ()]) | ^^^ diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs index 65beccf2214..142ea6b4ea8 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs @@ -1,5 +1,7 @@ -//@ revisions: no_feature feature nothing -//@ edition: 2021 +//@ revisions: e2021 e2024 nothing +//@ [e2021] edition: 2021 +//@ [e2024] edition: 2024 +//@ [nothing] edition: 2024 // Here we test that `lowering` behaves correctly wrt. `let $pats = $expr` expressions. // // We want to make sure that `let` is banned in situations other than: @@ -19,9 +21,6 @@ // // To that end, we check some positions which is not part of the language above. -// Avoid inflating `.stderr` with overzealous gates (or test what happens if you disable the gate) -#![cfg_attr(not(no_feature), feature(let_chains))] - #![allow(irrefutable_let_patterns)] use std::ops::Range; @@ -50,8 +49,8 @@ fn _if() { //~^ ERROR expected expression, found `let` statement //~| ERROR expected expression, found `let` statement //~| ERROR expected expression, found `let` statement - //[no_feature]~| ERROR `let` expressions in this position are unstable - //[no_feature]~| ERROR `let` expressions in this position are unstable + //[e2021]~| ERROR let chains are only allowed in Rust 2024 or later + //[e2021]~| ERROR let chains are only allowed in Rust 2024 or later } #[cfg(not(nothing))] @@ -76,8 +75,8 @@ fn _while() { //~^ ERROR expected expression, found `let` statement //~| ERROR expected expression, found `let` statement //~| ERROR expected expression, found `let` statement - //[no_feature]~| ERROR `let` expressions in this position are unstable - //[no_feature]~| ERROR `let` expressions in this position are unstable + //[e2021]~| ERROR let chains are only allowed in Rust 2024 or later + //[e2021]~| ERROR let chains are only allowed in Rust 2024 or later } #[cfg(not(nothing))] @@ -89,13 +88,13 @@ fn _macros() { } } use_expr!((let 0 = 1 && 0 == 0)); - //[feature,no_feature]~^ ERROR expected expression, found `let` statement - //[feature,no_feature]~| ERROR expected expression, found `let` statement - //[feature,no_feature]~| ERROR expected expression, found `let` statement + //[e2021,e2024]~^ ERROR expected expression, found `let` statement + //[e2021,e2024]~| ERROR expected expression, found `let` statement + //[e2021,e2024]~| ERROR expected expression, found `let` statement use_expr!((let 0 = 1)); - //[feature,no_feature]~^ ERROR expected expression, found `let` statement - //[feature,no_feature]~| ERROR expected expression, found `let` statement - //[feature,no_feature]~| ERROR expected expression, found `let` statement + //[e2021,e2024]~^ ERROR expected expression, found `let` statement + //[e2021,e2024]~| ERROR expected expression, found `let` statement + //[e2021,e2024]~| ERROR expected expression, found `let` statement } #[cfg(not(nothing))] @@ -112,7 +111,7 @@ fn nested_within_if_expr() { fn _check_try_binds_tighter() -> Result<(), ()> { if let 0 = 0? {} - //[feature,no_feature]~^ ERROR the `?` operator can only be applied to values that implement `Try` + //[e2021,e2024]~^ ERROR the `?` operator can only be applied to values that implement `Try` Ok(()) } if (let 0 = 0)? {} @@ -133,7 +132,7 @@ fn nested_within_if_expr() { if true..(let 0 = 0) {} //~^ ERROR expected expression, found `let` statement - //[feature,no_feature]~| ERROR mismatched types + //[e2021,e2024]~| ERROR mismatched types if ..(let 0 = 0) {} //~^ ERROR expected expression, found `let` statement if (let 0 = 0).. {} @@ -142,22 +141,22 @@ fn nested_within_if_expr() { // Binds as `(let ... = true)..true &&/|| false`. if let Range { start: _, end: _ } = true..true && false {} //~^ ERROR expected expression, found `let` statement - //[feature,no_feature]~| ERROR mismatched types + //[e2021,e2024]~| ERROR mismatched types if let Range { start: _, end: _ } = true..true || false {} //~^ ERROR expected expression, found `let` statement - //[feature,no_feature]~| ERROR mismatched types + //[e2021,e2024]~| ERROR mismatched types // Binds as `(let Range { start: F, end } = F)..(|| true)`. const F: fn() -> bool = || true; if let Range { start: F, end } = F..|| true {} //~^ ERROR expected expression, found `let` statement - //[feature,no_feature]~| ERROR mismatched types + //[e2021,e2024]~| ERROR mismatched types // Binds as `(let Range { start: true, end } = t)..(&&false)`. let t = &&true; if let Range { start: true, end } = t..&&false {} //~^ ERROR expected expression, found `let` statement - //[feature,no_feature]~| ERROR mismatched types + //[e2021,e2024]~| ERROR mismatched types if let true = let true = true {} //~^ ERROR expected expression, found `let` statement @@ -203,7 +202,7 @@ fn nested_within_while_expr() { fn _check_try_binds_tighter() -> Result<(), ()> { while let 0 = 0? {} - //[feature,no_feature]~^ ERROR the `?` operator can only be applied to values that implement `Try` + //[e2021,e2024]~^ ERROR the `?` operator can only be applied to values that implement `Try` Ok(()) } while (let 0 = 0)? {} @@ -224,7 +223,7 @@ fn nested_within_while_expr() { while true..(let 0 = 0) {} //~^ ERROR expected expression, found `let` statement - //[feature,no_feature]~| ERROR mismatched types + //[e2021,e2024]~| ERROR mismatched types while ..(let 0 = 0) {} //~^ ERROR expected expression, found `let` statement while (let 0 = 0).. {} @@ -233,22 +232,22 @@ fn nested_within_while_expr() { // Binds as `(let ... = true)..true &&/|| false`. while let Range { start: _, end: _ } = true..true && false {} //~^ ERROR expected expression, found `let` statement - //[feature,no_feature]~| ERROR mismatched types + //[e2021,e2024]~| ERROR mismatched types while let Range { start: _, end: _ } = true..true || false {} //~^ ERROR expected expression, found `let` statement - //[feature,no_feature]~| ERROR mismatched types + //[e2021,e2024]~| ERROR mismatched types // Binds as `(let Range { start: F, end } = F)..(|| true)`. const F: fn() -> bool = || true; while let Range { start: F, end } = F..|| true {} //~^ ERROR expected expression, found `let` statement - //[feature,no_feature]~| ERROR mismatched types + //[e2021,e2024]~| ERROR mismatched types // Binds as `(let Range { start: true, end } = t)..(&&false)`. let t = &&true; while let Range { start: true, end } = t..&&false {} //~^ ERROR expected expression, found `let` statement - //[feature,no_feature]~| ERROR mismatched types + //[e2021,e2024]~| ERROR mismatched types while let true = let true = true {} //~^ ERROR expected expression, found `let` statement @@ -307,7 +306,7 @@ fn outside_if_and_while_expr() { fn _check_try_binds_tighter() -> Result<(), ()> { let 0 = 0?; - //[feature,no_feature]~^ ERROR the `?` operator can only be applied to values that implement `Try` + //[e2021,e2024]~^ ERROR the `?` operator can only be applied to values that implement `Try` Ok(()) } (let 0 = 0)?; @@ -333,7 +332,7 @@ fn outside_if_and_while_expr() { (let Range { start: _, end: _ } = true..true || false); //~^ ERROR expected expression, found `let` statement - //[feature,no_feature]~| ERROR mismatched types + //[e2021,e2024]~| ERROR mismatched types (let true = let true = true); //~^ ERROR expected expression, found `let` statement @@ -406,7 +405,7 @@ fn with_parenthesis() { //~| ERROR expected expression, found `let` statement } if let Some(a) = opt && (true && true) { - //[no_feature]~^ ERROR `let` expressions in this position are unstable + //[e2021]~^ ERROR let chains are only allowed in Rust 2024 or later } if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { @@ -422,18 +421,18 @@ fn with_parenthesis() { } if (true && (true)) && let Some(a) = opt { - //[no_feature]~^ ERROR `let` expressions in this position are unstable + //[e2021]~^ ERROR let chains are only allowed in Rust 2024 or later } if (true) && let Some(a) = opt { - //[no_feature]~^ ERROR `let` expressions in this position are unstable + //[e2021]~^ ERROR let chains are only allowed in Rust 2024 or later } if true && let Some(a) = opt { - //[no_feature]~^ ERROR `let` expressions in this position are unstable + //[e2021]~^ ERROR let chains are only allowed in Rust 2024 or later } let fun = || true; if let true = (true && fun()) && (true) { - //[no_feature]~^ ERROR `let` expressions in this position are unstable + //[e2021]~^ ERROR let chains are only allowed in Rust 2024 or later } #[cfg(false)] diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/edition-gate-macro-error.edition2021.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/edition-gate-macro-error.edition2021.stderr index 23700f89f10..7fc91e9d980 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/edition-gate-macro-error.edition2021.stderr +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/edition-gate-macro-error.edition2021.stderr @@ -1,65 +1,42 @@ -error[E0658]: `let` expressions in this position are unstable +error: let chains are only allowed in Rust 2024 or later --> $DIR/edition-gate-macro-error.rs:19:30 | LL | macro_in_2021::make_if!((let Some(0) = None && let Some(0) = None) { never!() } { never!() }); | ^^^^^^^^^^^^^^^^^^ - | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` 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]: `let` expressions in this position are unstable +error: let chains are only allowed in Rust 2024 or later --> $DIR/edition-gate-macro-error.rs:19:52 | LL | macro_in_2021::make_if!((let Some(0) = None && let Some(0) = None) { never!() } { never!() }); | ^^^^^^^^^^^^^^^^^^ - | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` 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]: `let` expressions in this position are unstable +error: let chains are only allowed in Rust 2024 or later --> $DIR/edition-gate-macro-error.rs:22:5 | LL | macro_in_2021::make_if!(let (Some(0)) let (Some(0)) { never!() } { never!() }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this error originates in the macro `macro_in_2021::make_if` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0658]: `let` expressions in this position are unstable +error: let chains are only allowed in Rust 2024 or later --> $DIR/edition-gate-macro-error.rs:22:5 | LL | macro_in_2021::make_if!(let (Some(0)) let (Some(0)) { never!() } { never!() }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this error originates in the macro `macro_in_2021::make_if` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0658]: `let` expressions in this position are unstable +error: let chains are only allowed in Rust 2024 or later --> $DIR/edition-gate-macro-error.rs:26:30 | LL | macro_in_2024::make_if!((let Some(0) = None && let Some(0) = None) { never!() } { never!() }); | ^^^^^^^^^^^^^^^^^^ - | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` 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]: `let` expressions in this position are unstable +error: let chains are only allowed in Rust 2024 or later --> $DIR/edition-gate-macro-error.rs:26:52 | LL | macro_in_2024::make_if!((let Some(0) = None && let Some(0) = None) { never!() } { never!() }); | ^^^^^^^^^^^^^^^^^^ - | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` 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/rfcs/rfc-2497-if-let-chains/edition-gate-macro-error.edition2024.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/edition-gate-macro-error.edition2024.stderr index 3af844f4f96..35ac848561c 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/edition-gate-macro-error.edition2024.stderr +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/edition-gate-macro-error.edition2024.stderr @@ -1,45 +1,30 @@ -error[E0658]: `let` expressions in this position are unstable +error: let chains are only allowed in Rust 2024 or later --> $DIR/edition-gate-macro-error.rs:19:30 | LL | macro_in_2021::make_if!((let Some(0) = None && let Some(0) = None) { never!() } { never!() }); | ^^^^^^^^^^^^^^^^^^ - | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` 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]: `let` expressions in this position are unstable +error: let chains are only allowed in Rust 2024 or later --> $DIR/edition-gate-macro-error.rs:19:52 | LL | macro_in_2021::make_if!((let Some(0) = None && let Some(0) = None) { never!() } { never!() }); | ^^^^^^^^^^^^^^^^^^ - | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` 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]: `let` expressions in this position are unstable +error: let chains are only allowed in Rust 2024 or later --> $DIR/edition-gate-macro-error.rs:22:5 | LL | macro_in_2021::make_if!(let (Some(0)) let (Some(0)) { never!() } { never!() }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this error originates in the macro `macro_in_2021::make_if` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0658]: `let` expressions in this position are unstable +error: let chains are only allowed in Rust 2024 or later --> $DIR/edition-gate-macro-error.rs:22:5 | LL | macro_in_2021::make_if!(let (Some(0)) let (Some(0)) { never!() } { never!() }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this error originates in the macro `macro_in_2021::make_if` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/edition-gate-macro-error.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/edition-gate-macro-error.rs index 89b555d2c50..a56c11264c1 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/edition-gate-macro-error.rs +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/edition-gate-macro-error.rs @@ -17,14 +17,14 @@ fn main() { // No gating if both the `if` and the chain are from a 2024 macro macro_in_2021::make_if!((let Some(0) = None && let Some(0) = None) { never!() } { never!() }); - //~^ ERROR `let` expressions in this position are unstable - //~| ERROR `let` expressions in this position are unstable + //~^ ERROR let chains are only allowed in Rust 2024 or later + //~| ERROR let chains are only allowed in Rust 2024 or later macro_in_2021::make_if!(let (Some(0)) let (Some(0)) { never!() } { never!() }); - //~^ ERROR `let` expressions in this position are unstable - //~| ERROR `let` expressions in this position are unstable + //~^ ERROR let chains are only allowed in Rust 2024 or later + //~| ERROR let chains are only allowed in Rust 2024 or later macro_in_2024::make_if!((let Some(0) = None && let Some(0) = None) { never!() } { never!() }); - //[edition2021]~^ ERROR `let` expressions in this position are unstable - //[edition2021]~| ERROR `let` expressions in this position are unstable + //[edition2021]~^ ERROR let chains are only allowed in Rust 2024 or later + //[edition2021]~| ERROR let chains are only allowed in Rust 2024 or later macro_in_2024::make_if!(let (Some(0)) let (Some(0)) { never!() } { never!() }); } diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/edition-gate.rs index dad02b7f106..0096e6985d3 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.rs +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/edition-gate.rs @@ -1,6 +1,4 @@ -// gate-test-let_chains - -// Here we test feature gating for ´let_chains`. +// Here we test Rust 2024 edition gating for ´let_chains`. // See `disallowed-positions.rs` for the grammar // defining the language for gated allowed positions. @@ -12,17 +10,17 @@ fn _if() { if let 0 = 1 {} // Stable! if true && let 0 = 1 {} - //~^ ERROR `let` expressions in this position are unstable [E0658] + //~^ ERROR let chains are only allowed in Rust 2024 or later if let 0 = 1 && true {} - //~^ ERROR `let` expressions in this position are unstable [E0658] + //~^ ERROR let chains are only allowed in Rust 2024 or later if let Range { start: _, end: _ } = (true..true) && false {} - //~^ ERROR `let` expressions in this position are unstable [E0658] + //~^ ERROR let chains are only allowed in Rust 2024 or later if let 1 = 1 && let true = { true } && false { - //~^ ERROR `let` expressions in this position are unstable [E0658] - //~| ERROR `let` expressions in this position are unstable [E0658] + //~^ ERROR let chains are only allowed in Rust 2024 or later + //~| ERROR let chains are only allowed in Rust 2024 or later } } @@ -30,13 +28,13 @@ fn _while() { while let 0 = 1 {} // Stable! while true && let 0 = 1 {} - //~^ ERROR `let` expressions in this position are unstable [E0658] + //~^ ERROR let chains are only allowed in Rust 2024 or later while let 0 = 1 && true {} - //~^ ERROR `let` expressions in this position are unstable [E0658] + //~^ ERROR let chains are only allowed in Rust 2024 or later while let Range { start: _, end: _ } = (true..true) && false {} - //~^ ERROR `let` expressions in this position are unstable [E0658] + //~^ ERROR let chains are only allowed in Rust 2024 or later } fn _macros() { diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/edition-gate.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/edition-gate.stderr new file mode 100644 index 00000000000..f75dd858941 --- /dev/null +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/edition-gate.stderr @@ -0,0 +1,81 @@ +error: let chains are only allowed in Rust 2024 or later + --> $DIR/edition-gate.rs:12:16 + | +LL | if true && let 0 = 1 {} + | ^^^^^^^^^ + +error: let chains are only allowed in Rust 2024 or later + --> $DIR/edition-gate.rs:15:8 + | +LL | if let 0 = 1 && true {} + | ^^^^^^^^^ + +error: let chains are only allowed in Rust 2024 or later + --> $DIR/edition-gate.rs:18:8 + | +LL | if let Range { start: _, end: _ } = (true..true) && false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: let chains are only allowed in Rust 2024 or later + --> $DIR/edition-gate.rs:21:8 + | +LL | if let 1 = 1 && let true = { true } && false { + | ^^^^^^^^^ + +error: let chains are only allowed in Rust 2024 or later + --> $DIR/edition-gate.rs:21:21 + | +LL | if let 1 = 1 && let true = { true } && false { + | ^^^^^^^^^^^^^^^^^^^ + +error: let chains are only allowed in Rust 2024 or later + --> $DIR/edition-gate.rs:30:19 + | +LL | while true && let 0 = 1 {} + | ^^^^^^^^^ + +error: let chains are only allowed in Rust 2024 or later + --> $DIR/edition-gate.rs:33:11 + | +LL | while let 0 = 1 && true {} + | ^^^^^^^^^ + +error: let chains are only allowed in Rust 2024 or later + --> $DIR/edition-gate.rs:36:11 + | +LL | while let Range { start: _, end: _ } = (true..true) && false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/edition-gate.rs:52:20 + | +LL | #[cfg(false)] (let 0 = 1); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/edition-gate.rs:43:17 + | +LL | noop_expr!((let 0 = 1)); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: no rules expected keyword `let` + --> $DIR/edition-gate.rs:54:15 + | +LL | macro_rules! use_expr { + | --------------------- when calling this macro +... +LL | use_expr!(let 0 = 1); + | ^^^ no rules expected this token in macro call + | +note: while trying to match meta-variable `$e:expr` + --> $DIR/edition-gate.rs:47:10 + | +LL | ($e:expr) => { + | ^^^^^^^ + +error: aborting due to 11 previous errors + diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.stderr deleted file mode 100644 index b9dac472dca..00000000000 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.stderr +++ /dev/null @@ -1,114 +0,0 @@ -error: expected expression, found `let` statement - --> $DIR/feature-gate.rs:54:20 - | -LL | #[cfg(false)] (let 0 = 1); - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/feature-gate.rs:45:17 - | -LL | noop_expr!((let 0 = 1)); - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: no rules expected keyword `let` - --> $DIR/feature-gate.rs:56:15 - | -LL | macro_rules! use_expr { - | --------------------- when calling this macro -... -LL | use_expr!(let 0 = 1); - | ^^^ no rules expected this token in macro call - | -note: while trying to match meta-variable `$e:expr` - --> $DIR/feature-gate.rs:49:10 - | -LL | ($e:expr) => { - | ^^^^^^^ - -error[E0658]: `let` expressions in this position are unstable - --> $DIR/feature-gate.rs:14:16 - | -LL | if true && let 0 = 1 {} - | ^^^^^^^^^ - | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` 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]: `let` expressions in this position are unstable - --> $DIR/feature-gate.rs:17:8 - | -LL | if let 0 = 1 && true {} - | ^^^^^^^^^ - | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` 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]: `let` expressions in this position are unstable - --> $DIR/feature-gate.rs:20:8 - | -LL | if let Range { start: _, end: _ } = (true..true) && false {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` 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]: `let` expressions in this position are unstable - --> $DIR/feature-gate.rs:23:8 - | -LL | if let 1 = 1 && let true = { true } && false { - | ^^^^^^^^^ - | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` 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]: `let` expressions in this position are unstable - --> $DIR/feature-gate.rs:23:21 - | -LL | if let 1 = 1 && let true = { true } && false { - | ^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` 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]: `let` expressions in this position are unstable - --> $DIR/feature-gate.rs:32:19 - | -LL | while true && let 0 = 1 {} - | ^^^^^^^^^ - | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` 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]: `let` expressions in this position are unstable - --> $DIR/feature-gate.rs:35:11 - | -LL | while let 0 = 1 && true {} - | ^^^^^^^^^ - | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` 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]: `let` expressions in this position are unstable - --> $DIR/feature-gate.rs:38:11 - | -LL | while let Range { start: _, end: _ } = (true..true) && false {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` 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 11 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs index ae525aed414..3711dd5abb2 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs @@ -1,4 +1,4 @@ -#![feature(let_chains)] +//@ edition: 2024 fn main() { let _opt = Some(1i32); diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/irrefutable-lets.disallowed.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/irrefutable-lets.disallowed.stderr index 130d0296c5e..008e769cf0b 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/irrefutable-lets.disallowed.stderr +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/irrefutable-lets.disallowed.stderr @@ -1,19 +1,19 @@ error: leading irrefutable pattern in let chain - --> $DIR/irrefutable-lets.rs:13:8 + --> $DIR/irrefutable-lets.rs:14:8 | -LL | if let first = &opt && let Some(ref second) = first && let None = second.start {} +LL | if let first = &opt && let Some(second) = first && let None = second.start {} | ^^^^^^^^^^^^^^^^ | = note: this pattern will always match = help: consider moving it outside of the construct note: the lint level is defined here - --> $DIR/irrefutable-lets.rs:6:30 + --> $DIR/irrefutable-lets.rs:7:30 | LL | #![cfg_attr(disallowed, deny(irrefutable_let_patterns))] | ^^^^^^^^^^^^^^^^^^^^^^^^ error: irrefutable `if let` patterns - --> $DIR/irrefutable-lets.rs:19:8 + --> $DIR/irrefutable-lets.rs:20:8 | LL | if let first = &opt && let (a, b) = (1, 2) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -22,25 +22,25 @@ LL | if let first = &opt && let (a, b) = (1, 2) {} = help: consider replacing the `if let` with a `let` error: leading irrefutable pattern in let chain - --> $DIR/irrefutable-lets.rs:22:8 + --> $DIR/irrefutable-lets.rs:23:8 | -LL | if let first = &opt && let Some(ref second) = first && let None = second.start && let v = 0 {} +LL | if let first = &opt && let Some(second) = first && let None = second.start && let v = 0 {} | ^^^^^^^^^^^^^^^^ | = note: this pattern will always match = help: consider moving it outside of the construct error: trailing irrefutable pattern in let chain - --> $DIR/irrefutable-lets.rs:22:87 + --> $DIR/irrefutable-lets.rs:23:83 | -LL | if let first = &opt && let Some(ref second) = first && let None = second.start && let v = 0 {} - | ^^^^^^^^^ +LL | if let first = &opt && let Some(second) = first && let None = second.start && let v = 0 {} + | ^^^^^^^^^ | = note: this pattern will always match = help: consider moving it into the body error: trailing irrefutable patterns in let chain - --> $DIR/irrefutable-lets.rs:26:37 + --> $DIR/irrefutable-lets.rs:27:37 | LL | if let Some(ref first) = opt && let second = first && let _third = second {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL | if let Some(ref first) = opt && let second = first && let _third = seco = help: consider moving them into the body error: leading irrefutable pattern in let chain - --> $DIR/irrefutable-lets.rs:29:8 + --> $DIR/irrefutable-lets.rs:30:8 | LL | if let Range { start: local_start, end: _ } = (None..Some(1)) && let None = local_start {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -58,7 +58,7 @@ LL | if let Range { start: local_start, end: _ } = (None..Some(1)) && let No = help: consider moving it outside of the construct error: leading irrefutable pattern in let chain - --> $DIR/irrefutable-lets.rs:32:8 + --> $DIR/irrefutable-lets.rs:33:8 | LL | if let (a, b, c) = (Some(1), Some(1), Some(1)) && let None = Some(1) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -67,7 +67,7 @@ LL | if let (a, b, c) = (Some(1), Some(1), Some(1)) && let None = Some(1) {} = help: consider moving it outside of the construct error: leading irrefutable pattern in let chain - --> $DIR/irrefutable-lets.rs:35:8 + --> $DIR/irrefutable-lets.rs:36:8 | LL | if let first = &opt && let None = Some(1) {} | ^^^^^^^^^^^^^^^^ @@ -76,7 +76,7 @@ LL | if let first = &opt && let None = Some(1) {} = help: consider moving it outside of the construct error: irrefutable `if let` guard patterns - --> $DIR/irrefutable-lets.rs:44:28 + --> $DIR/irrefutable-lets.rs:45:28 | LL | Some(ref first) if let second = first && let _third = second && let v = 4 + 4 => {}, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -85,7 +85,7 @@ LL | Some(ref first) if let second = first && let _third = second && let = help: consider removing the guard and adding a `let` inside the match arm error: trailing irrefutable patterns in let chain - --> $DIR/irrefutable-lets.rs:59:16 + --> $DIR/irrefutable-lets.rs:60:16 | LL | && let v = local_end && let w = v => {}, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -94,7 +94,7 @@ LL | && let v = local_end && let w = v => {}, = help: consider moving them into the body error: irrefutable `while let` patterns - --> $DIR/irrefutable-lets.rs:68:11 + --> $DIR/irrefutable-lets.rs:69:11 | LL | while let first = &opt && let (a, b) = (1, 2) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -103,7 +103,7 @@ LL | while let first = &opt && let (a, b) = (1, 2) {} = help: consider instead using a `loop { ... }` with a `let` inside it error: trailing irrefutable patterns in let chain - --> $DIR/irrefutable-lets.rs:71:40 + --> $DIR/irrefutable-lets.rs:72:40 | LL | while let Some(ref first) = opt && let second = first && let _third = second {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -112,7 +112,7 @@ LL | while let Some(ref first) = opt && let second = first && let _third = s = help: consider moving them into the body error: trailing irrefutable pattern in let chain - --> $DIR/irrefutable-lets.rs:87:12 + --> $DIR/irrefutable-lets.rs:88:12 | LL | && let x = &opt | ^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL | && let x = &opt = help: consider moving it into the body error: leading irrefutable pattern in let chain - --> $DIR/irrefutable-lets.rs:93:12 + --> $DIR/irrefutable-lets.rs:94:12 | LL | if let x = opt.clone().map(|_| 1) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/irrefutable-lets.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/irrefutable-lets.rs index e7d69f89773..c8b9ac313ba 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/irrefutable-lets.rs +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/irrefutable-lets.rs @@ -1,7 +1,8 @@ //@ revisions: allowed disallowed //@[allowed] check-pass +//@ edition: 2024 -#![feature(if_let_guard, let_chains)] +#![feature(if_let_guard)] #![cfg_attr(allowed, allow(irrefutable_let_patterns))] #![cfg_attr(disallowed, deny(irrefutable_let_patterns))] @@ -10,16 +11,16 @@ use std::ops::Range; fn main() { let opt = Some(None..Some(1)); - if let first = &opt && let Some(ref second) = first && let None = second.start {} + if let first = &opt && let Some(second) = first && let None = second.start {} //[disallowed]~^ ERROR leading irrefutable pattern in let chain // No lint as the irrefutable pattern is surrounded by other stuff - if 4 * 2 == 0 && let first = &opt && let Some(ref second) = first && let None = second.start {} + if 4 * 2 == 0 && let first = &opt && let Some(second) = first && let None = second.start {} if let first = &opt && let (a, b) = (1, 2) {} //[disallowed]~^ ERROR irrefutable `if let` patterns - if let first = &opt && let Some(ref second) = first && let None = second.start && let v = 0 {} + if let first = &opt && let Some(second) = first && let None = second.start && let v = 0 {} //[disallowed]~^ ERROR leading irrefutable pattern in let chain //[disallowed]~^^ ERROR trailing irrefutable pattern in let chain @@ -63,7 +64,7 @@ fn main() { // No error, despite the prefix being irrefutable: moving out could change the behaviour, // due to possible side effects of the operation. - while let first = &opt && let Some(ref second) = first && let None = second.start {} + while let first = &opt && let Some(second) = first && let None = second.start {} while let first = &opt && let (a, b) = (1, 2) {} //[disallowed]~^ ERROR irrefutable `while let` patterns diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/then-else-blocks.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/then-else-blocks.rs index 6d307be90c1..287c73b41e9 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/then-else-blocks.rs +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/then-else-blocks.rs @@ -1,6 +1,7 @@ //@ run-pass +//@ edition: 2024 -#![feature(if_let_guard, let_chains)] +#![feature(if_let_guard)] fn check_if_let(opt: Option<Option<Option<i32>>>, value: i32) -> bool { if let Some(first) = opt diff --git a/tests/ui/sanitizer/cfi/closures.rs b/tests/ui/sanitizer/cfi/closures.rs index 9f9002da674..424e70560db 100644 --- a/tests/ui/sanitizer/cfi/closures.rs +++ b/tests/ui/sanitizer/cfi/closures.rs @@ -31,7 +31,7 @@ fn dyn_fn_with_params() { #[test] fn call_fn_trait() { - let f: &(dyn Fn()) = &(|| {}) as _; + let f: &dyn Fn() = &(|| {}) as _; f.call(()); } @@ -47,7 +47,7 @@ fn use_fnmut<F: FnMut()>(mut f: F) { #[test] fn fn_to_fnmut() { - let f: &(dyn Fn()) = &(|| {}) as _; + let f: &dyn Fn() = &(|| {}) as _; use_fnmut(f); } diff --git a/tests/ui/target-feature/invalid-attribute.rs b/tests/ui/target-feature/invalid-attribute.rs index 9ef7a686d25..d13098c3a6a 100644 --- a/tests/ui/target-feature/invalid-attribute.rs +++ b/tests/ui/target-feature/invalid-attribute.rs @@ -19,13 +19,16 @@ extern "Rust" {} #[target_feature = "+sse2"] //~^ ERROR malformed `target_feature` attribute +//~| NOTE expected this to be a list #[target_feature(enable = "foo")] //~^ ERROR not valid for this target //~| NOTE `foo` is not valid for this target #[target_feature(bar)] //~^ ERROR malformed `target_feature` attribute +//~| NOTE expected this to be of the form `enable = "..."` #[target_feature(disable = "baz")] //~^ ERROR malformed `target_feature` attribute +//~| NOTE expected this to be of the form `enable = "..."` unsafe fn foo() {} #[target_feature(enable = "sse2")] @@ -117,3 +120,8 @@ fn main() { || {}; //~^ NOTE not a function } + +#[target_feature(enable = "+sse2")] +//~^ ERROR `+sse2` is not valid for this target +//~| NOTE `+sse2` is not valid for this target +unsafe fn hey() {} diff --git a/tests/ui/target-feature/invalid-attribute.stderr b/tests/ui/target-feature/invalid-attribute.stderr index 05ae49d6b0d..113c0c3695a 100644 --- a/tests/ui/target-feature/invalid-attribute.stderr +++ b/tests/ui/target-feature/invalid-attribute.stderr @@ -1,8 +1,29 @@ -error: malformed `target_feature` attribute input +error[E0539]: malformed `target_feature` attribute input --> $DIR/invalid-attribute.rs:20:1 | LL | #[target_feature = "+sse2"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[target_feature(enable = "name")]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected this to be a list + | help: must be of the form: `#[target_feature(enable = "feat1, feat2")]` + +error[E0539]: malformed `target_feature` attribute input + --> $DIR/invalid-attribute.rs:26:1 + | +LL | #[target_feature(bar)] + | ^^^^^^^^^^^^^^^^^---^^ + | | | + | | expected this to be of the form `enable = "..."` + | help: must be of the form: `#[target_feature(enable = "feat1, feat2")]` + +error[E0539]: malformed `target_feature` attribute input + --> $DIR/invalid-attribute.rs:29:1 + | +LL | #[target_feature(disable = "baz")] + | ^^^^^^^^^^^^^^^^^-------^^^^^^^^^^ + | | | + | | expected this to be of the form `enable = "..."` + | help: must be of the form: `#[target_feature(enable = "feat1, feat2")]` error: attribute should be applied to a function definition --> $DIR/invalid-attribute.rs:5:1 @@ -32,7 +53,7 @@ LL | extern "Rust" {} | ---------------- not a function definition error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:31:1 + --> $DIR/invalid-attribute.rs:34:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -41,7 +62,7 @@ LL | mod another {} | -------------- not a function definition error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:36:1 + --> $DIR/invalid-attribute.rs:39:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -50,7 +71,7 @@ LL | const FOO: usize = 7; | --------------------- not a function definition error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:41:1 + --> $DIR/invalid-attribute.rs:44:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -59,7 +80,7 @@ LL | struct Foo; | ----------- not a function definition error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:46:1 + --> $DIR/invalid-attribute.rs:49:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -68,7 +89,7 @@ LL | enum Bar {} | ----------- not a function definition error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:51:1 + --> $DIR/invalid-attribute.rs:54:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -81,7 +102,7 @@ LL | | } | |_- not a function definition error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:59:1 + --> $DIR/invalid-attribute.rs:62:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -90,7 +111,7 @@ LL | type Uwu = (); | -------------- not a function definition error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:64:1 + --> $DIR/invalid-attribute.rs:67:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -99,13 +120,13 @@ LL | trait Baz {} | ------------ not a function definition error: cannot use `#[inline(always)]` with `#[target_feature]` - --> $DIR/invalid-attribute.rs:69:1 + --> $DIR/invalid-attribute.rs:72:1 | LL | #[inline(always)] | ^^^^^^^^^^^^^^^^^ error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:74:1 + --> $DIR/invalid-attribute.rs:77:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -114,7 +135,7 @@ LL | static A: () = (); | ------------------ not a function definition error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:79:1 + --> $DIR/invalid-attribute.rs:82:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -123,7 +144,7 @@ LL | impl Quux for u8 {} | ------------------- not a function definition error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:86:1 + --> $DIR/invalid-attribute.rs:89:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -132,7 +153,7 @@ LL | impl Foo {} | ----------- not a function definition error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:108:5 + --> $DIR/invalid-attribute.rs:111:5 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -143,7 +164,7 @@ LL | | } | |_____- not a function definition error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:115:5 + --> $DIR/invalid-attribute.rs:118:5 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -152,25 +173,13 @@ LL | || {}; | ----- not a function definition error: the feature named `foo` is not valid for this target - --> $DIR/invalid-attribute.rs:22:18 + --> $DIR/invalid-attribute.rs:23:18 | LL | #[target_feature(enable = "foo")] | ^^^^^^^^^^^^^^ `foo` is not valid for this target -error: malformed `target_feature` attribute input - --> $DIR/invalid-attribute.rs:25:18 - | -LL | #[target_feature(bar)] - | ^^^ help: must be of the form: `enable = ".."` - -error: malformed `target_feature` attribute input - --> $DIR/invalid-attribute.rs:27:18 - | -LL | #[target_feature(disable = "baz")] - | ^^^^^^^^^^^^^^^ help: must be of the form: `enable = ".."` - error[E0046]: not all trait items implemented, missing: `foo` - --> $DIR/invalid-attribute.rs:81:1 + --> $DIR/invalid-attribute.rs:84:1 | LL | impl Quux for u8 {} | ^^^^^^^^^^^^^^^^ missing `foo` in implementation @@ -179,7 +188,7 @@ LL | fn foo(); | --------- `foo` from trait error: `#[target_feature(..)]` cannot be applied to safe trait method - --> $DIR/invalid-attribute.rs:97:5 + --> $DIR/invalid-attribute.rs:100:5 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot be applied to safe trait method @@ -188,20 +197,28 @@ LL | fn foo() {} | -------- not an `unsafe` function error[E0053]: method `foo` has an incompatible type for trait - --> $DIR/invalid-attribute.rs:100:5 + --> $DIR/invalid-attribute.rs:103:5 | LL | fn foo() {} | ^^^^^^^^ expected safe fn, found unsafe fn | note: type in trait - --> $DIR/invalid-attribute.rs:92:5 + --> $DIR/invalid-attribute.rs:95:5 | LL | fn foo(); | ^^^^^^^^^ = note: expected signature `fn()` found signature `#[target_features] fn()` -error: aborting due to 23 previous errors +error: the feature named `+sse2` is not valid for this target + --> $DIR/invalid-attribute.rs:124:18 + | +LL | #[target_feature(enable = "+sse2")] + | ^^^^^^^^^^^^^^^^ `+sse2` is not valid for this target + | + = help: consider removing the leading `+` in the feature name + +error: aborting due to 24 previous errors -Some errors have detailed explanations: E0046, E0053. +Some errors have detailed explanations: E0046, E0053, E0539. For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/thir-print/thir-tree-loop-match.stdout b/tests/ui/thir-print/thir-tree-loop-match.stdout index 828b93da6be..5c4c50cb156 100644 --- a/tests/ui/thir-print/thir-tree-loop-match.stdout +++ b/tests/ui/thir-print/thir-tree-loop-match.stdout @@ -89,158 +89,182 @@ body: } } region_scope: Node(10) - match_span: $DIR/thir-tree-loop-match.rs:11:13: 17:14 (#0) - arms: [ - Arm { - pattern: - Pat: { - ty: bool - span: $DIR/thir-tree-loop-match.rs:12:17: 12:21 (#0) - kind: PatKind { - Constant { - value: Ty(bool, true) - } - } - } - guard: None - body: + match_data: + LoopMatchMatchData { + span: $DIR/thir-tree-loop-match.rs:11:13: 17:14 (#0) + scrutinee: Expr { ty: bool - temp_lifetime: TempLifetime { temp_lifetime: Some(Node(16)), backwards_incompatible: None } - span: $DIR/thir-tree-loop-match.rs:12:25: 15:18 (#0) + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(5)), backwards_incompatible: None } + span: $DIR/thir-tree-loop-match.rs:11:19: 11:24 (#0) kind: Scope { - region_scope: Node(17) - lint_level: Explicit(HirId(DefId(0:3 ~ thir_tree_loop_match[3c53]::boolean).17)) + region_scope: Node(12) + lint_level: Explicit(HirId(DefId(0:3 ~ thir_tree_loop_match[3c53]::boolean).12)) value: Expr { ty: bool - temp_lifetime: TempLifetime { temp_lifetime: Some(Node(16)), backwards_incompatible: None } - span: $DIR/thir-tree-loop-match.rs:12:25: 15:18 (#0) + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(5)), backwards_incompatible: None } + span: $DIR/thir-tree-loop-match.rs:11:19: 11:24 (#0) kind: - NeverToAny { - source: - Expr { - ty: ! - temp_lifetime: TempLifetime { temp_lifetime: Some(Node(16)), backwards_incompatible: None } - span: $DIR/thir-tree-loop-match.rs:12:25: 15:18 (#0) - kind: - Block { - targeted_by_break: false + VarRef { + id: LocalVarId(HirId(DefId(0:3 ~ thir_tree_loop_match[3c53]::boolean).2)) + } + } + } + } + arms: [ + Arm { + pattern: + Pat: { + ty: bool + span: $DIR/thir-tree-loop-match.rs:12:17: 12:21 (#0) + kind: PatKind { + Constant { + value: Ty(bool, true) + } + } + } + guard: None + body: + Expr { + ty: bool + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(16)), backwards_incompatible: None } + span: $DIR/thir-tree-loop-match.rs:12:25: 15:18 (#0) + kind: + Scope { + region_scope: Node(17) + lint_level: Explicit(HirId(DefId(0:3 ~ thir_tree_loop_match[3c53]::boolean).17)) + value: + Expr { + ty: bool + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(16)), backwards_incompatible: None } + span: $DIR/thir-tree-loop-match.rs:12:25: 15:18 (#0) + kind: + NeverToAny { + source: + Expr { + ty: ! + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(16)), backwards_incompatible: None } span: $DIR/thir-tree-loop-match.rs:12:25: 15:18 (#0) - region_scope: Node(18) - safety_mode: Safe - stmts: [ - Stmt { - kind: Expr { - scope: Node(21) - expr: - Expr { - ty: ! - temp_lifetime: TempLifetime { temp_lifetime: Some(Node(21)), backwards_incompatible: None } - span: $DIR/thir-tree-loop-match.rs:14:21: 14:37 (#0) - kind: - Scope { - region_scope: Node(19) - lint_level: Explicit(HirId(DefId(0:3 ~ thir_tree_loop_match[3c53]::boolean).19)) - value: - Expr { - ty: ! - temp_lifetime: TempLifetime { temp_lifetime: Some(Node(21)), backwards_incompatible: None } - span: $DIR/thir-tree-loop-match.rs:14:21: 14:37 (#0) - kind: - ConstContinue ( - label: Node(10) - value: - Expr { - ty: bool - temp_lifetime: TempLifetime { temp_lifetime: Some(Node(21)), backwards_incompatible: None } - span: $DIR/thir-tree-loop-match.rs:14:32: 14:37 (#0) - kind: - Scope { - region_scope: Node(20) - lint_level: Explicit(HirId(DefId(0:3 ~ thir_tree_loop_match[3c53]::boolean).20)) - value: - Expr { - ty: bool - temp_lifetime: TempLifetime { temp_lifetime: Some(Node(21)), backwards_incompatible: None } - span: $DIR/thir-tree-loop-match.rs:14:32: 14:37 (#0) - kind: - Literal( lit: Spanned { node: Bool(false), span: $DIR/thir-tree-loop-match.rs:14:32: 14:37 (#0) }, neg: false) + kind: + Block { + targeted_by_break: false + span: $DIR/thir-tree-loop-match.rs:12:25: 15:18 (#0) + region_scope: Node(18) + safety_mode: Safe + stmts: [ + Stmt { + kind: Expr { + scope: Node(21) + expr: + Expr { + ty: ! + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(21)), backwards_incompatible: None } + span: $DIR/thir-tree-loop-match.rs:14:21: 14:37 (#0) + kind: + Scope { + region_scope: Node(19) + lint_level: Explicit(HirId(DefId(0:3 ~ thir_tree_loop_match[3c53]::boolean).19)) + value: + Expr { + ty: ! + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(21)), backwards_incompatible: None } + span: $DIR/thir-tree-loop-match.rs:14:21: 14:37 (#0) + kind: + ConstContinue ( + label: Node(10) + value: + Expr { + ty: bool + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(21)), backwards_incompatible: None } + span: $DIR/thir-tree-loop-match.rs:14:32: 14:37 (#0) + kind: + Scope { + region_scope: Node(20) + lint_level: Explicit(HirId(DefId(0:3 ~ thir_tree_loop_match[3c53]::boolean).20)) + value: + Expr { + ty: bool + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(21)), backwards_incompatible: None } + span: $DIR/thir-tree-loop-match.rs:14:32: 14:37 (#0) + kind: + Literal( lit: Spanned { node: Bool(false), span: $DIR/thir-tree-loop-match.rs:14:32: 14:37 (#0) }, neg: false) + } } } - } - ) + ) + } } } } - } + } + ] + expr: [] } - ] - expr: [] } } } } } + lint_level: Explicit(HirId(DefId(0:3 ~ thir_tree_loop_match[3c53]::boolean).16)) + scope: Node(16) + span: $DIR/thir-tree-loop-match.rs:12:17: 15:18 (#0) } - lint_level: Explicit(HirId(DefId(0:3 ~ thir_tree_loop_match[3c53]::boolean).16)) - scope: Node(16) - span: $DIR/thir-tree-loop-match.rs:12:17: 15:18 (#0) - } - Arm { - pattern: - Pat: { - ty: bool - span: $DIR/thir-tree-loop-match.rs:16:17: 16:22 (#0) - kind: PatKind { - Constant { - value: Ty(bool, false) + Arm { + pattern: + Pat: { + ty: bool + span: $DIR/thir-tree-loop-match.rs:16:17: 16:22 (#0) + kind: PatKind { + Constant { + value: Ty(bool, false) + } + } } - } - } - guard: None - body: - Expr { - ty: bool - temp_lifetime: TempLifetime { temp_lifetime: Some(Node(24)), backwards_incompatible: None } - span: $DIR/thir-tree-loop-match.rs:16:26: 16:38 (#0) - kind: - Scope { - region_scope: Node(25) - lint_level: Explicit(HirId(DefId(0:3 ~ thir_tree_loop_match[3c53]::boolean).25)) - value: - Expr { - ty: bool - temp_lifetime: TempLifetime { temp_lifetime: Some(Node(24)), backwards_incompatible: None } - span: $DIR/thir-tree-loop-match.rs:16:26: 16:38 (#0) - kind: - NeverToAny { - source: - Expr { - ty: ! - temp_lifetime: TempLifetime { temp_lifetime: Some(Node(24)), backwards_incompatible: None } - span: $DIR/thir-tree-loop-match.rs:16:26: 16:38 (#0) - kind: - Return { - value: - Expr { - ty: bool - temp_lifetime: TempLifetime { temp_lifetime: Some(Node(24)), backwards_incompatible: None } - span: $DIR/thir-tree-loop-match.rs:16:33: 16:38 (#0) - kind: - Scope { - region_scope: Node(26) - lint_level: Explicit(HirId(DefId(0:3 ~ thir_tree_loop_match[3c53]::boolean).26)) - value: - Expr { - ty: bool - temp_lifetime: TempLifetime { temp_lifetime: Some(Node(24)), backwards_incompatible: None } - span: $DIR/thir-tree-loop-match.rs:16:33: 16:38 (#0) - kind: - VarRef { - id: LocalVarId(HirId(DefId(0:3 ~ thir_tree_loop_match[3c53]::boolean).2)) + guard: None + body: + Expr { + ty: bool + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(24)), backwards_incompatible: None } + span: $DIR/thir-tree-loop-match.rs:16:26: 16:38 (#0) + kind: + Scope { + region_scope: Node(25) + lint_level: Explicit(HirId(DefId(0:3 ~ thir_tree_loop_match[3c53]::boolean).25)) + value: + Expr { + ty: bool + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(24)), backwards_incompatible: None } + span: $DIR/thir-tree-loop-match.rs:16:26: 16:38 (#0) + kind: + NeverToAny { + source: + Expr { + ty: ! + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(24)), backwards_incompatible: None } + span: $DIR/thir-tree-loop-match.rs:16:26: 16:38 (#0) + kind: + Return { + value: + Expr { + ty: bool + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(24)), backwards_incompatible: None } + span: $DIR/thir-tree-loop-match.rs:16:33: 16:38 (#0) + kind: + Scope { + region_scope: Node(26) + lint_level: Explicit(HirId(DefId(0:3 ~ thir_tree_loop_match[3c53]::boolean).26)) + value: + Expr { + ty: bool + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(24)), backwards_incompatible: None } + span: $DIR/thir-tree-loop-match.rs:16:33: 16:38 (#0) + kind: + VarRef { + id: LocalVarId(HirId(DefId(0:3 ~ thir_tree_loop_match[3c53]::boolean).2)) + } } } } @@ -250,12 +274,12 @@ body: } } } + lint_level: Explicit(HirId(DefId(0:3 ~ thir_tree_loop_match[3c53]::boolean).24)) + scope: Node(24) + span: $DIR/thir-tree-loop-match.rs:16:17: 16:38 (#0) } - lint_level: Explicit(HirId(DefId(0:3 ~ thir_tree_loop_match[3c53]::boolean).24)) - scope: Node(24) - span: $DIR/thir-tree-loop-match.rs:16:17: 16:38 (#0) + ] } - ] } } } diff --git a/tests/ui/traits/const-traits/const-via-item-bound.rs b/tests/ui/traits/const-traits/const-via-item-bound.rs new file mode 100644 index 00000000000..23f122b7413 --- /dev/null +++ b/tests/ui/traits/const-traits/const-via-item-bound.rs @@ -0,0 +1,19 @@ +//@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +#![feature(const_trait_impl)] + +#[const_trait] +trait Bar {} + +trait Baz: const Bar {} + +trait Foo { + // Well-formedenss of `Baz` requires `<Self as Foo>::Bar: const Bar`. + // Make sure we assemble a candidate for that via the item bounds. + type Bar: Baz; +} + +fn main() {} diff --git a/tests/ui/traits/dyn-trait.rs b/tests/ui/traits/dyn-trait.rs index 4fb7aea5cba..a378ce5a696 100644 --- a/tests/ui/traits/dyn-trait.rs +++ b/tests/ui/traits/dyn-trait.rs @@ -7,7 +7,7 @@ static BYTE: u8 = 33; fn main() { let x: &(dyn 'static + Display) = &BYTE; let y: Box<dyn Display + 'static> = Box::new(BYTE); - let _: &dyn (Display) = &BYTE; + let _: &dyn Display = &BYTE; let _: &dyn (::std::fmt::Display) = &BYTE; let xstr = format!("{}", x); let ystr = format!("{}", y); diff --git a/tests/ui/traits/impl-2.rs b/tests/ui/traits/impl-2.rs index 41fa1cd334f..eafbaeaa167 100644 --- a/tests/ui/traits/impl-2.rs +++ b/tests/ui/traits/impl-2.rs @@ -10,7 +10,7 @@ pub mod Foo { } mod Bar { - impl<'a> dyn (crate::Foo::Trait) + 'a { + impl<'a> dyn crate::Foo::Trait + 'a { fn bar(&self) { self.foo() } } } diff --git a/tests/ui/traits/negative-bounds/negative-sized.rs b/tests/ui/traits/negative-bounds/negative-sized.rs new file mode 100644 index 00000000000..18369c78427 --- /dev/null +++ b/tests/ui/traits/negative-bounds/negative-sized.rs @@ -0,0 +1,8 @@ +#![feature(negative_bounds)] + +fn foo<T: !Sized>() {} + +fn main() { + foo::<()>(); + //~^ ERROR the trait bound `(): !Sized` is not satisfied +} diff --git a/tests/ui/traits/negative-bounds/negative-sized.stderr b/tests/ui/traits/negative-bounds/negative-sized.stderr new file mode 100644 index 00000000000..143933803b8 --- /dev/null +++ b/tests/ui/traits/negative-bounds/negative-sized.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `(): !Sized` is not satisfied + --> $DIR/negative-sized.rs:6:11 + | +LL | foo::<()>(); + | ^^ the trait bound `(): !Sized` is not satisfied + | +note: required by a bound in `foo` + --> $DIR/negative-sized.rs:3:11 + | +LL | fn foo<T: !Sized>() {} + | ^^^^^^ required by this bound in `foo` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/auxiliary/private-dep.rs b/tests/ui/typeck/auxiliary/private-dep.rs new file mode 100644 index 00000000000..472b40ef622 --- /dev/null +++ b/tests/ui/typeck/auxiliary/private-dep.rs @@ -0,0 +1,3 @@ +pub trait A { + fn foo() {} +} diff --git a/tests/ui/typeck/auxiliary/public-dep.rs b/tests/ui/typeck/auxiliary/public-dep.rs new file mode 100644 index 00000000000..438692a1caa --- /dev/null +++ b/tests/ui/typeck/auxiliary/public-dep.rs @@ -0,0 +1,11 @@ +//@ aux-crate:priv:private_dep=private-dep.rs +//@ compile-flags: -Zunstable-options + +extern crate private_dep; +use private_dep::A; + +pub struct B; + +impl A for B { + fn foo() {} +} diff --git a/tests/ui/typeck/dont-suggest-private-dependencies.rs b/tests/ui/typeck/dont-suggest-private-dependencies.rs new file mode 100644 index 00000000000..ee5224e2d82 --- /dev/null +++ b/tests/ui/typeck/dont-suggest-private-dependencies.rs @@ -0,0 +1,37 @@ +// Don't suggest importing a function from a private dependency. +// Issues: #138191, #142676 + +// Avoid suggesting traits from std-private deps +//@ forbid-output: compiler_builtins +//@ forbid-output: object + +// Check a custom trait to withstand changes in above crates +//@ aux-crate:public_dep=public-dep.rs +//@ compile-flags: -Zunstable-options +//@ forbid-output: private_dep + +// By default, the `read` diagnostic suggests `std::os::unix::fs::FileExt::read_at`. Add +// something more likely to be recommended to make the diagnostic cross-platform. +trait DecoyRead { + fn read1(&self) {} +} +impl<T> DecoyRead for Vec<T> {} + +struct VecReader(Vec<u8>); + +impl std::io::Read for VecReader { + fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> { + self.0.read(buf) + //~^ ERROR no method named `read` found for struct `Vec<u8>` + } +} + +extern crate public_dep; +use public_dep::B; + +fn main() { + let _ = u8::cast_from_lossy(9); + //~^ ERROR no function or associated item named `cast_from_lossy` found for type `u8` + let _ = B::foo(); + //~^ ERROR no function or associated item named `foo` found for struct `B` +} diff --git a/tests/ui/typeck/dont-suggest-private-dependencies.stderr b/tests/ui/typeck/dont-suggest-private-dependencies.stderr new file mode 100644 index 00000000000..b7b14ee6b9b --- /dev/null +++ b/tests/ui/typeck/dont-suggest-private-dependencies.stderr @@ -0,0 +1,27 @@ +error[E0599]: no method named `read` found for struct `Vec<u8>` in the current scope + --> $DIR/dont-suggest-private-dependencies.rs:24:16 + | +LL | self.0.read(buf) + | ^^^^ + | +help: there is a method `read1` with a similar name, but with different arguments + --> $DIR/dont-suggest-private-dependencies.rs:16:5 + | +LL | fn read1(&self) {} + | ^^^^^^^^^^^^^^^ + +error[E0599]: no function or associated item named `cast_from_lossy` found for type `u8` in the current scope + --> $DIR/dont-suggest-private-dependencies.rs:33:17 + | +LL | let _ = u8::cast_from_lossy(9); + | ^^^^^^^^^^^^^^^ function or associated item not found in `u8` + +error[E0599]: no function or associated item named `foo` found for struct `B` in the current scope + --> $DIR/dont-suggest-private-dependencies.rs:35:16 + | +LL | let _ = B::foo(); + | ^^^ function or associated item not found in `B` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/underscore-lifetime/in-binder.stderr b/tests/ui/underscore-lifetime/in-binder.stderr index fcd7eddb576..f25db4d0889 100644 --- a/tests/ui/underscore-lifetime/in-binder.stderr +++ b/tests/ui/underscore-lifetime/in-binder.stderr @@ -3,36 +3,48 @@ error[E0637]: `'_` cannot be used here | LL | impl<'_> IceCube<'_> {} | ^^ `'_` is a reserved lifetime name + | + = help: use another lifetime specifier error[E0637]: `'_` cannot be used here --> $DIR/in-binder.rs:12:15 | LL | struct Struct<'_> { | ^^ `'_` is a reserved lifetime name + | + = help: use another lifetime specifier error[E0637]: `'_` cannot be used here --> $DIR/in-binder.rs:17:11 | LL | enum Enum<'_> { | ^^ `'_` is a reserved lifetime name + | + = help: use another lifetime specifier error[E0637]: `'_` cannot be used here --> $DIR/in-binder.rs:22:13 | LL | union Union<'_> { | ^^ `'_` is a reserved lifetime name + | + = help: use another lifetime specifier error[E0637]: `'_` cannot be used here --> $DIR/in-binder.rs:27:13 | LL | trait Trait<'_> { | ^^ `'_` is a reserved lifetime name + | + = help: use another lifetime specifier error[E0637]: `'_` cannot be used here --> $DIR/in-binder.rs:31:8 | LL | fn foo<'_>() { | ^^ `'_` is a reserved lifetime name + | + = help: use another lifetime specifier error: aborting due to 6 previous errors diff --git a/tests/ui/underscore-lifetime/underscore-lifetime-binders.stderr b/tests/ui/underscore-lifetime/underscore-lifetime-binders.stderr index d940166e9e2..50359309c92 100644 --- a/tests/ui/underscore-lifetime/underscore-lifetime-binders.stderr +++ b/tests/ui/underscore-lifetime/underscore-lifetime-binders.stderr @@ -15,12 +15,16 @@ error[E0637]: `'_` cannot be used here | LL | fn foo<'_> | ^^ `'_` is a reserved lifetime name + | + = help: use another lifetime specifier error[E0637]: `'_` cannot be used here --> $DIR/underscore-lifetime-binders.rs:10:25 | LL | fn meh() -> Box<dyn for<'_> Meh<'_>> | ^^ `'_` is a reserved lifetime name + | + = help: use another lifetime specifier error[E0106]: missing lifetime specifier --> $DIR/underscore-lifetime-binders.rs:10:33 diff --git a/triagebot.toml b/triagebot.toml index 6385528e7b6..64a8a7c46b4 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1,6 +1,11 @@ # This file's format is documented at # https://forge.rust-lang.org/triagebot/pr-assignment.html#configuration + +# ------------------------------------------------------------------------------ +# Labels +# ------------------------------------------------------------------------------ + [relabel] allow-unauthenticated = [ "A-*", @@ -44,6 +49,11 @@ remove_labels = ["S-waiting-on-author"] # Those labels are added when PR author requests a review from an assignee add_labels = ["S-waiting-on-review"] + +# ------------------------------------------------------------------------------ +# Ping groups +# ------------------------------------------------------------------------------ + [ping.windows] message = """\ Hey Windows Group! This bug has been identified as a good "Windows candidate". @@ -153,6 +163,11 @@ Hi relnotes-interest-group, this issue/PR could use some help in reviewing / adjusting release notes. Could you take a look if available? Thanks <3 """ + +# ------------------------------------------------------------------------------ +# Autolabels +# ------------------------------------------------------------------------------ + [prioritize] label = "I-prioritize" @@ -582,6 +597,11 @@ trigger_files = [ "compiler/rustc_codegen_llvm", ] + +# ------------------------------------------------------------------------------ +# Prioritization and team nominations +# ------------------------------------------------------------------------------ + [notify-zulip."I-prioritize"] zulip_stream = 245100 # #t-compiler/prioritization/alerts topic = "#{number} {title}" @@ -598,6 +618,21 @@ message_on_remove = "Issue #{number}'s prioritization request has been removed." message_on_close = "Issue #{number} has been closed while requested for prioritization." message_on_reopen = "Issue #{number} has been reopened." +[notify-zulip."I-types-nominated"] +zulip_stream = 326866 # #T-types/nominated +topic = "#{number}: {title}" +message_on_add = """\ +@*T-types* issue #{number} "{title}" has been nominated for team discussion. +""" +message_on_remove = "Issue #{number}'s nomination has been removed. Thanks all for participating!" +message_on_close = "Issue #{number} has been closed. Thanks for participating!" +message_on_reopen = "Issue #{number} has been reopened. Pinging @*T-types*." + + +# ------------------------------------------------------------------------------ +# Zulip notifications +# ------------------------------------------------------------------------------ + [notify-zulip."beta-nominated".rustdoc] required_labels = ["T-rustdoc"] zulip_stream = 266220 # #t-rustdoc @@ -661,15 +696,6 @@ message_on_remove = "PR #{number}'s stable-acceptance has been **removed**." message_on_close = "PR #{number} has been closed. Thanks for participating!" message_on_reopen = "PR #{number} has been reopened. Pinging @*T-rustdoc*." -[notify-zulip."I-types-nominated"] -zulip_stream = 326866 # #T-types/nominated -topic = "#{number}: {title}" -message_on_add = """\ -@*T-types* issue #{number} "{title}" has been nominated for team discussion. -""" -message_on_remove = "Issue #{number}'s nomination has been removed. Thanks all for participating!" -message_on_close = "Issue #{number} has been closed. Thanks for participating!" -message_on_reopen = "Issue #{number} has been reopened. Pinging @*T-types*." [notify-zulip."beta-nominated".compiler] required_labels = ["T-compiler"] @@ -688,6 +714,13 @@ don't know ] message_on_remove = "PR #{number}'s beta-nomination has been removed." +[notify-zulip."beta-accepted".compiler] +required_labels = ["T-compiler"] +zulip_stream = 474880 # #t-compiler/backports +# Put it in the same thread as beta-nominated. +topic = "#{number}: beta-nominated" +message_on_add = "PR #{number} has been **accepted** for **beta** backport." + [notify-zulip."stable-nominated".compiler] required_labels = ["T-compiler"] zulip_stream = 474880 # #t-compiler/backports @@ -706,6 +739,14 @@ don't know ] message_on_remove = "PR #{number}'s stable-nomination has been removed." +[notify-zulip."stable-accepted".compiler] +required_labels = ["T-compiler"] +zulip_stream = 474880 # #t-compiler/backports +# Put it in the same thread as stable-nominated. +topic = "#{number}: stable-nominated" +message_on_add = "PR #{number} has been **accepted** for **stable** backport." + + [notify-zulip."beta-nominated".bootstrap] required_labels = ["T-bootstrap"] zulip_stream = 507486 # #t-infra/bootstrap/backports @@ -723,6 +764,13 @@ don't know ] message_on_remove = "PR #{number}'s beta-nomination has been removed." +[notify-zulip."beta-accepted".bootstrap] +required_labels = ["T-bootstrap"] +zulip_stream = 507486 # #t-infra/bootstrap/backports +# Put it in the same thread as beta-nominated. +topic = "#{number}: beta-nominated" +message_on_add = "PR #{number} has been **accepted** for **beta** backport." + [notify-zulip."stable-nominated".bootstrap] required_labels = ["T-bootstrap"] zulip_stream = 507486 # #t-infra/bootstrap/backports @@ -741,6 +789,14 @@ don't know ] message_on_remove = "PR #{number}'s stable-nomination has been removed." +[notify-zulip."stable-accepted".bootstrap] +required_labels = ["T-bootstrap"] +zulip_stream = 507486 # #t-infra/bootstrap/backports +# Put it in the same thread as stable-nominated. +topic = "#{number}: stable-nominated" +message_on_add = "PR #{number} has been **accepted** for **stable** backport." + + [notify-zulip."A-edition-2021"] required_labels = ["C-bug"] zulip_stream = 268952 # #edition @@ -757,17 +813,10 @@ message_on_add = """\ Issue #{number} "{title}" has been added. """ -[no-merges] -exclude_titles = ["Rollup of", "subtree update", "Subtree update"] -labels = ["has-merge-commits", "S-waiting-on-author"] - -[github-releases] -format = "rustc" -project-name = "Rust" -changelog-path = "RELEASES.md" -changelog-branch = "master" -[shortcut] +# ------------------------------------------------------------------------------ +# Mentions +# ------------------------------------------------------------------------------ [mentions."triagebot.toml"] message = "`triagebot.toml` has been modified, there may have been changes to the review queue." @@ -1201,6 +1250,11 @@ cc = ["@m-ou-se"] [mentions."compiler/rustc_ast_lowering/src/format.rs"] cc = ["@m-ou-se"] + +# ------------------------------------------------------------------------------ +# PR assignments +# ------------------------------------------------------------------------------ + [assign] warn_non_default_branch.enable = true contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" @@ -1442,6 +1496,23 @@ compiletest = [ [pr-tracking] + +# ------------------------------------------------------------------------------ +# Misc +# ------------------------------------------------------------------------------ + +[no-merges] +exclude_titles = ["Rollup of", "subtree update", "Subtree update"] +labels = ["has-merge-commits", "S-waiting-on-author"] + +[github-releases] +format = "rustc" +project-name = "Rust" +changelog-path = "RELEASES.md" +changelog-branch = "master" + +[shortcut] + # Enable issue transfers within the org # Documentation at: https://forge.rust-lang.org/triagebot/transfer.html [transfer] diff --git a/typos.toml b/typos.toml new file mode 100644 index 00000000000..4035f206a46 --- /dev/null +++ b/typos.toml @@ -0,0 +1,74 @@ +[files] +extend-exclude = [ + # exclude git (sub)modules and generated content + "compiler/rustc_codegen_gcc", + "compiler/rustc_codegen_cranelift", + "compiler/rustc_baked_icu_data", + "library/compiler-builtins", + "library/backtrace", + "library/stdarch", + # generated lorem ipsum texts + "library/alloctests/benches/str.rs", + "library/alloctests/tests/str.rs", +] + +[default.extend-words] +# Add exclusions here, lines should be like `x = "x"`, where `x` is excluded word. +# +# Also see docs: https://github.com/crate-ci/typos/blob/v1.28.2/docs/reference.md +rplace = "rplace" +arange = "arange" +unstalled = "unstalled" +taits = "taits" +Datas = "Datas" +splitted = "splitted" +leafs = "leafs" +makro = "makro" +optin = "optin" +unparseable = "unparseable" +smove = "smove" +childs = "childs" +filetimes = "filetimes" +misformed = "misformed" +targetting = "targetting" +publically = "publically" +clonable = "clonable" + +# this can be valid word, depends on dictionary edition +#matcheable = "matcheable" + +[default.extend-identifiers] +# An entry goes here if the typo is part of some existing ident +# where you want to keep it, but don't want to allow +# such typos everywhere. +# +# I.e. you don't want (or can't) fix some constant name, like +# `DNS_ERROR_INVAILD_VIRTUALIZATION_INSTANCE_NAME` but actually +# want to see `INVAILD` typo fixed in other places. +ERROR_FILENAME_EXCED_RANGE = "ERROR_FILENAME_EXCED_RANGE" +DNS_ERROR_INVAILD_VIRTUALIZATION_INSTANCE_NAME = "DNS_ERROR_INVAILD_VIRTUALIZATION_INSTANCE_NAME" +ERROR_DS_FILTER_USES_CONTRUCTED_ATTRS = "ERROR_DS_FILTER_USES_CONTRUCTED_ATTRS" +ERROR_DS_NOT_AUTHORITIVE_FOR_DST_NC = "ERROR_DS_NOT_AUTHORITIVE_FOR_DST_NC" +ERROR_MCA_OCCURED = "ERROR_MCA_OCCURED" +ERRNO_ACCES = "ERRNO_ACCES" +tolen = "tolen" +numer = "numer" + +[default] +extend-ignore-words-re = [ + # words with length <= 4 chars is likely noise + "^[a-zA-Z]{1,4}$", +] + +extend-ignore-re = [ + # ignore these intentional typo examples + "/// 1 \\| #\\[cfg\\(widnows\\)\\]", + "/// warning: unexpected `cfg` condition name: `widnows`", + "/// #\\[cfg\\(widnows\\)\\]", + "\\.arg\\(\"Oh no, a tpyo!\"\\)", + # string used in benches + "\"core::iter::adapters::Copie\"", + "-Ccontrol-flow-guard", + "concat!\\(\"CURRENT_RUSTC_VERSIO\", \"N\"\\)", + "\\*\\*v\\*\\*ariable" +] |
